This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Improve warnings about MIPS macros
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: binutils at sources dot redhat dot com
- Date: Wed, 21 Jan 2004 23:00:12 +0000
- Subject: Improve warnings about MIPS macros
This patch is an attempt to improve the way MIPS gas deals with macro
warnings. It's a follow-on from last weekend's patch to the relaxation
machinery.
There are a couple of nits to pick here:
- If we end up creating a relaxable macro, any warnings about the
second implementation will have the file and line number of the
end of the file, not the line containing the macro.
- There are a few cases in which the second implementation of a
relaxable macro is shorter than the first. E.g., with n32 PIC:
la $4,foo+12
takes only one insn (a GOT_DISP access) when foo is local but
takes 2 when foo is global. The current code assumes that
the global sequence is shorter and therefore always warns.
At the moment, every macro expander keeps a local count of the macro's
length and passes it macro_build and macro_build_lui. These functions
update the counter and warn on-the-fly when the macro gets too long.
The update and warning is disabled when expanding the second
implementation of a relaxable macro.
The patch removes this counter and instead wraps each macro expansion in
calls to two new functions, macro_start() and macro_end(). (I thought
it was better to use generic names in case the functions need to do
something else later.) macro_start() sets up some global vars,
append_insn() updates them, and macro_end() uses them to decide
whether a warning is needed. If the macro is relaxable and only
one alternative needs a warning, macro_end() caches the necessary
info in the fr_subtype of the first variant frag. Otherwise it
decides immediately whether to warn.
Tested on mips64-linux-gnu. OK to install?
Richard
gas/
* config/tc-mips.c (RELAX_ENCODE): Remove WARN argument.
(RELAX_FIRST, RELAX_SECOND): Turn into 8-bit quantities.
(RELAX_USE_SECOND): Bump to 0x10000.
(RELAX_SECOND_LONGER, RELAX_NOMACRO, RELAX_DELAY_SLOT): New flags.
(mips_macro_warning): New variable.
(md_assemble): Wrap macro expansion in macro_start() and macro_end().
(s_cpload, s_cpsetup, s_cprestore, s_cpreturn): Likewise.
(relax_close_frag): Set mips_macro_warning.first_frag. Adjust use
of RELAX_ENCODE.
(append_insn): Update mips_macro_warning.sizes.
(macro_start, macro_warning, macro_end): New functions.
(macro_build): Don't emit warnings here.
(macro_build_lui, md_estimate_size_before_relax): ...or here.
(md_convert_frag): Check for cases where one macro alternative
needs a warning and the other doesn't. Emit a warning if the
longer sequence was chosen.
gas/testsuite/
* gas/mips/macro-warn-[1234].[sdl]: New tests.
* gas/mips/macro-warn-[12]-n32.[dl]: New tests.
* gas/mips/mips.exp: Run them.
*** config/tc-mips.c.relax Fri Jan 16 17:16:58 2004
--- config/tc-mips.c Wed Jan 21 22:22:19 2004
*************** static int mips_relax_branch;
*** 629,642 ****
absolute one. In SVR4 PIC, the first sequence will be for global
symbols and the second will be for local symbols.
! The frag's "subtype" is RELAX_ENCODE (FIRST, SECOND, WARN), where
! FIRST and SECOND are the lengths of the two sequences in bytes
! and WARN is true if ".set nomacro" was in effect when the macro
! was expanded. These fields can be extracted using RELAX_FIRST(),
! RELAX_SECOND() and RELAX_WARN().
! In addition, the RELAX_USE_SECOND flag is set if it has been decided
! that we should use the second sequence instead of the first.
The frag's "opcode" points to the first fixup for relaxable code.
--- 629,655 ----
absolute one. In SVR4 PIC, the first sequence will be for global
symbols and the second will be for local symbols.
! The frag's "subtype" is RELAX_ENCODE (FIRST, SECOND), where FIRST and
! SECOND are the lengths of the two sequences in bytes. These fields
! can be extracted using RELAX_FIRST() and RELAX_SECOND(). In addition,
! the subtype has the following flags:
! RELAX_USE_SECOND
! Set if it has been decided that we should use the second
! sequence instead of the first.
!
! RELAX_SECOND_LONGER
! Set in the first variant frag if the macro's second implementation
! is longer than its first. This refers to the macro as a whole,
! not an individual relaxation.
!
! RELAX_NOMACRO
! Set in the first variant frag if the macro appeared in a .set nomacro
! block and if one alternative requires a warning but the other does not.
!
! RELAX_DELAY_SLOT
! Like RELAX_NOMACRO, but indicates that the macro appears in a branch
! delay slot.
The frag's "opcode" points to the first fixup for relaxable code.
*************** static int mips_relax_branch;
*** 650,662 ****
The code and fixups for the unwanted alternative are discarded
by md_convert_frag. */
! #define RELAX_ENCODE(FIRST, SECOND, WARN) \
! (((FIRST) << 8) | ((SECOND) << 1) | ((WARN) != 0))
! #define RELAX_FIRST(X) (((X) >> 8) & 0x7f)
! #define RELAX_SECOND(X) (((X) >> 1) & 0x7f)
! #define RELAX_WARN(X) ((X) & 1)
! #define RELAX_USE_SECOND 0x8000
/* Branch without likely bit. If label is out of range, we turn:
--- 663,676 ----
The code and fixups for the unwanted alternative are discarded
by md_convert_frag. */
! #define RELAX_ENCODE(FIRST, SECOND) (((FIRST) << 8) | (SECOND))
! #define RELAX_FIRST(X) (((X) >> 8) & 0xff)
! #define RELAX_SECOND(X) ((X) & 0xff)
! #define RELAX_USE_SECOND 0x10000
! #define RELAX_SECOND_LONGER 0x20000
! #define RELAX_NOMACRO 0x40000
! #define RELAX_DELAY_SLOT 0x80000
/* Branch without likely bit. If label is out of range, we turn:
*************** static struct {
*** 810,815 ****
--- 824,844 ----
symbolS *symbol;
} mips_relax;
+ /* Global variables used to decide whether a macro needs a warning. */
+ static struct {
+ /* True if the macro is in a branch delay slot. */
+ bfd_boolean delay_slot_p;
+
+ /* For relaxable macros, sizes[0] is the length of the first alternative
+ in bytes and sizes[1] is the length of the second alternative.
+ For non-relaxable macros, both elements give the length of the
+ macro in bytes. */
+ unsigned int sizes[2];
+
+ /* The first variant frag for this macro. */
+ fragS *first_frag;
+ } mips_macro_warning;
+
/* Prototypes for static functions. */
#define internalError() \
*************** static void mips_no_prev_insn (int);
*** 823,828 ****
--- 852,859 ----
static void mips16_macro_build
(int *, expressionS *, const char *, const char *, va_list);
static void load_register (int *, int, expressionS *, int);
+ static void macro_start (void);
+ static void macro_end (void);
static void macro (struct mips_cl_insn * ip);
static void mips16_macro (struct mips_cl_insn * ip);
#ifdef LOSING_COMPILER
*************** md_assemble (char *str)
*** 1340,1349 ****
--- 1371,1382 ----
if (insn.insn_mo->pinfo == INSN_MACRO)
{
+ macro_start ();
if (mips_opts.mips16)
mips16_macro (&insn);
else
macro (&insn);
+ macro_end ();
}
else
{
*************** mips16_mark_labels (void)
*** 1518,1527 ****
static void
relax_close_frag (void)
{
frag_var (rs_machine_dependent, 0, 0,
! RELAX_ENCODE (mips_relax.sizes[0],
! mips_relax.sizes[1],
! mips_opts.warn_about_macros),
mips_relax.symbol, 0, (char *) mips_relax.first_fixup);
memset (&mips_relax.sizes, 0, sizeof (mips_relax.sizes));
--- 1551,1559 ----
static void
relax_close_frag (void)
{
+ mips_macro_warning.first_frag = frag_now;
frag_var (rs_machine_dependent, 0, 0,
! RELAX_ENCODE (mips_relax.sizes[0], mips_relax.sizes[1]),
mips_relax.symbol, 0, (char *) mips_relax.first_fixup);
memset (&mips_relax.sizes, 0, sizeof (mips_relax.sizes));
*************** append_insn (struct mips_cl_insn *ip, ex
*** 2025,2030 ****
--- 2057,2067 ----
mips_relax.sizes[mips_relax.sequence - 1] += 4;
}
+ if (mips_relax.sequence != 2)
+ mips_macro_warning.sizes[0] += 4;
+ if (mips_relax.sequence != 1)
+ mips_macro_warning.sizes[1] += 4;
+
f = frag_more (4);
}
*************** mips_emit_delays (bfd_boolean insns)
*** 2851,2856 ****
--- 2888,2958 ----
mips_no_prev_insn (insns);
}
+ /* Set up global variables for the start of a new macro. */
+
+ static void
+ macro_start (void)
+ {
+ memset (&mips_macro_warning.sizes, 0, sizeof (mips_macro_warning.sizes));
+ mips_macro_warning.delay_slot_p = (mips_opts.noreorder
+ && (prev_insn.insn_mo->pinfo
+ & (INSN_UNCOND_BRANCH_DELAY
+ | INSN_COND_BRANCH_DELAY
+ | INSN_COND_BRANCH_LIKELY)) != 0);
+ }
+
+ /* Given that a macro is longer than 4 bytes, return the appropriate warning
+ for it. Return null if no warning is needed. SUBTYPE is a bitmask of
+ RELAX_DELAY_SLOT and RELAX_NOMACRO. */
+
+ static const char *
+ macro_warning (relax_substateT subtype)
+ {
+ if (subtype & RELAX_DELAY_SLOT)
+ return _("Macro instruction expanded into multiple instructions"
+ " in a branch delay slot");
+ else if (subtype & RELAX_NOMACRO)
+ return _("Macro instruction expanded into multiple instructions");
+ else
+ return 0;
+ }
+
+ /* Finish up a macro. Emit warnings as appropriate. */
+
+ static void
+ macro_end (void)
+ {
+ if (mips_macro_warning.sizes[0] > 4 || mips_macro_warning.sizes[1] > 4)
+ {
+ relax_substateT subtype;
+
+ /* Set up the relaxation warning flags. */
+ subtype = 0;
+ if (mips_macro_warning.sizes[1] > mips_macro_warning.sizes[0])
+ subtype |= RELAX_SECOND_LONGER;
+ if (mips_opts.warn_about_macros)
+ subtype |= RELAX_NOMACRO;
+ if (mips_macro_warning.delay_slot_p)
+ subtype |= RELAX_DELAY_SLOT;
+
+ if (mips_macro_warning.sizes[0] > 4 && mips_macro_warning.sizes[1] > 4)
+ {
+ /* Either the macro has a single implementation or both
+ implementations are longer than 4 bytes. Emit the
+ warning now. */
+ const char *msg = macro_warning (subtype);
+ if (msg != 0)
+ as_warn (msg);
+ }
+ else
+ {
+ /* One implementation might need a warning but the other
+ definitely doesn't. */
+ mips_macro_warning.first_frag->fr_subtype |= subtype;
+ }
+ }
+ }
+
/* 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
*************** macro_build (char *place ATTRIBUTE_UNUSE
*** 2866,2893 ****
va_start (args, fmt);
- if (mips_relax.sequence != 2)
- {
- if (*counter == 1)
- {
- /* If the macro is about to expand into a second instruction,
- and it is in a delay slot, print a warning. */
- if (mips_opts.noreorder
- && (prev_prev_insn.insn_mo->pinfo
- & (INSN_UNCOND_BRANCH_DELAY
- | INSN_COND_BRANCH_DELAY
- | INSN_COND_BRANCH_LIKELY)) != 0)
- as_warn (_("Macro instruction expanded into multiple instructions in a branch delay slot"));
-
- /* 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... */
- else if (mips_opts.warn_about_macros)
- as_warn (_("Macro instruction expanded into multiple instructions"));
- }
- ++*counter;
- }
-
if (mips_opts.mips16)
{
mips16_macro_build (counter, ep, name, fmt, args);
--- 2968,2973 ----
*************** macro_build_jalr (int icnt, expressionS
*** 3253,3259 ****
* Generate a "lui" instruction.
*/
static void
! macro_build_lui (char *place ATTRIBUTE_UNUSED, int *counter,
expressionS *ep, int regnum)
{
expressionS high_expr;
--- 3333,3339 ----
* Generate a "lui" instruction.
*/
static void
! macro_build_lui (char *place ATTRIBUTE_UNUSED, int *counter ATTRIBUTE_UNUSED,
expressionS *ep, int regnum)
{
expressionS high_expr;
*************** macro_build_lui (char *place ATTRIBUTE_U
*** 3266,3280 ****
assert (! mips_opts.mips16);
high_expr = *ep;
- if (mips_relax.sequence != 2)
- {
- /* 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_opts.warn_about_macros && *counter == 1)
- as_warn (_("Macro instruction expanded into multiple instructions"));
- ++*counter;
- }
if (high_expr.X_op == O_constant)
{
--- 3346,3351 ----
*************** s_cpload (int ignore ATTRIBUTE_UNUSED)
*** 12230,12241 ****
--- 12301,12314 ----
/* In ELF, this symbol is implicitly an STT_OBJECT symbol. */
symbol_get_bfdsym (ex.X_add_symbol)->flags |= BSF_OBJECT;
+ macro_start ();
macro_build_lui (NULL, &icnt, &ex, mips_gp_register);
macro_build (NULL, &icnt, &ex, "addiu", "t,r,j", mips_gp_register,
mips_gp_register, BFD_RELOC_LO16);
macro_build (NULL, &icnt, NULL, "addu", "d,v,t", mips_gp_register,
mips_gp_register, tc_get_register (0));
+ macro_end ();
demand_empty_rest_of_line ();
}
*************** s_cpsetup (int ignore ATTRIBUTE_UNUSED)
*** 12303,12308 ****
--- 12376,12382 ----
SKIP_WHITESPACE ();
expression (&ex_sym);
+ macro_start ();
if (mips_cpreturn_register == -1)
{
ex_off.X_op = O_constant;
*************** s_cpsetup (int ignore ATTRIBUTE_UNUSED)
*** 12338,12343 ****
--- 12412,12418 ----
macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t", mips_gp_register,
mips_gp_register, reg1);
+ macro_end ();
demand_empty_rest_of_line ();
}
*************** s_cprestore (int ignore ATTRIBUTE_UNUSED
*** 12383,12390 ****
--- 12458,12467 ----
ex.X_op_symbol = NULL;
ex.X_add_number = mips_cprestore_offset;
+ macro_start ();
macro_build_ldst_constoffset (NULL, &icnt, &ex, ADDRESS_STORE_INSN,
mips_gp_register, SP, HAVE_64BIT_ADDRESSES);
+ macro_end ();
demand_empty_rest_of_line ();
}
*************** s_cpreturn (int ignore ATTRIBUTE_UNUSED)
*** 12410,12415 ****
--- 12487,12493 ----
return;
}
+ macro_start ();
if (mips_cpreturn_register == -1)
{
ex.X_op = O_constant;
*************** s_cpreturn (int ignore ATTRIBUTE_UNUSED)
*** 12423,12428 ****
--- 12501,12507 ----
else
macro_build (NULL, &icnt, NULL, "daddu", "d,v,t", mips_gp_register,
mips_cpreturn_register, 0);
+ macro_end ();
demand_empty_rest_of_line ();
}
*************** s_cpadd (int ignore ATTRIBUTE_UNUSED)
*** 12545,12553 ****
--- 12624,12634 ----
}
/* Add $gp to the register named as an argument. */
+ macro_start ();
reg = tc_get_register (0);
macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
reg, reg, mips_gp_register);
+ macro_end ();
demand_empty_rest_of_line ();
}
*************** md_estimate_size_before_relax (fragS *fr
*** 13155,13165 ****
if (change)
{
fragp->fr_subtype |= RELAX_USE_SECOND;
- /* FIXME: This really needs as_warn_where. */
- if (RELAX_WARN (fragp->fr_subtype))
- as_warn (_("AT used after \".set noat\" or macro used after "
- "\".set nomacro\""));
-
return -RELAX_FIRST (fragp->fr_subtype);
}
else
--- 13236,13241 ----
*************** md_convert_frag (bfd *abfd ATTRIBUTE_UNU
*** 13679,13684 ****
--- 13755,13769 ----
first = RELAX_FIRST (fragp->fr_subtype);
second = RELAX_SECOND (fragp->fr_subtype);
fixp = (fixS *) fragp->fr_opcode;
+
+ /* Possibly emit a warning if we've chosen the longer option. */
+ if (((fragp->fr_subtype & RELAX_USE_SECOND) != 0)
+ == ((fragp->fr_subtype & RELAX_SECOND_LONGER) != 0))
+ {
+ const char *msg = macro_warning (fragp->fr_subtype);
+ if (msg != 0)
+ as_warn_where (fragp->fr_file, fragp->fr_line, msg);
+ }
/* Go through all the fixups for the first sequence. Disable them
(by marking them as done) if we're going to use the second
Index: testsuite/gas/mips/mips.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
retrieving revision 1.85
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.85 mips.exp
*** testsuite/gas/mips/mips.exp 14 Jan 2004 18:01:09 -0000 1.85
--- testsuite/gas/mips/mips.exp 21 Jan 2004 22:24:32 -0000
*************** if { [istarget mips*-*-*] } then {
*** 733,737 ****
--- 734,747 ----
run_dump_test "ldstla-n32-shared"
run_dump_test "ldstla-n64"
run_dump_test "ldstla-n64-shared"
+ }
+
+ run_dump_test "macro-warn-1"
+ run_dump_test "macro-warn-2"
+ run_dump_test "macro-warn-3"
+ run_dump_test "macro-warn-4"
+ if $has_newabi {
+ run_dump_test "macro-warn-1-n32"
+ run_dump_test "macro-warn-2-n32"
}
}
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-1.d Wed Jan 21 21:19:12 2004
***************
*** 0 ****
--- 1,5 ----
+ #as: -32 -KPIC
+ #source: macro-warn-1.s
+ #stderr: macro-warn-1.l
+ #objdump: -p
+ #pass
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-1.l Wed Jan 21 22:17:07 2004
***************
*** 0 ****
--- 1,8 ----
+ .*: Assembler messages:
+ .*:5: Warning: Macro instruction expanded into multiple instructions
+ .*:10: Warning: Macro instruction expanded into multiple instructions
+ .*:11: Warning: Macro instruction expanded into multiple instructions
+ .*:12: Warning: Macro instruction expanded into multiple instructions
+ .*:16: Warning: Macro instruction expanded into multiple instructions.*slot
+ .*:18: Warning: Macro instruction expanded into multiple instructions.*slot
+ .*:20: Warning: Macro instruction expanded into multiple instructions.*slot
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-1-n32.d Wed Jan 21 21:19:07 2004
***************
*** 0 ****
--- 1,5 ----
+ #as: -n32 -KPIC
+ #source: macro-warn-1.s
+ #stderr: macro-warn-1-n32.l
+ #objdump: -p
+ #pass
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-1-n32.l Wed Jan 21 22:16:26 2004
***************
*** 0 ****
--- 1,6 ----
+ .*: Assembler messages:
+ .*:6: Warning: Macro instruction expanded into multiple instructions
+ .*:10: Warning: Macro instruction expanded into multiple instructions
+ .*:12: Warning: Macro instruction expanded into multiple instructions
+ .*:16: Warning: Macro instruction expanded into multiple instructions.*slot
+ .*:20: Warning: Macro instruction expanded into multiple instructions.*slot
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-1.s Wed Jan 21 22:16:05 2004
***************
*** 0 ****
--- 1,21 ----
+ .set noreorder
+ .set nomacro
+ .globl early_global
+ local:
+ .cpload $25
+ .cpsetup $25,16,local
+ .cprestore 16
+ .cpreturn
+ la $4,early_global
+ la $4,early_global+10
+ la $4,local+10
+ la $4,late_global+10
+ jr $5
+ la $4,early_global
+ jr $5
+ la $4,early_global+10
+ jr $5
+ la $4,local+10
+ jr $5
+ la $4,late_global+10
+ .globl late_global
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-2.d Wed Jan 21 21:19:19 2004
***************
*** 0 ****
--- 1,5 ----
+ #as: -32 -KPIC
+ #source: macro-warn-2.s
+ #stderr: macro-warn-2.l
+ #objdump: -p
+ #pass
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-2.l Wed Jan 21 21:14:47 2004
***************
*** 0 ****
--- 1,3 ----
+ .*: Assembler messages:
+ .*:5: Warning: Macro instruction expanded into multiple instructions
+ .*:9: Warning: Macro instruction expanded into multiple instructions.*slot
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-2-n32.d Wed Jan 21 21:28:12 2004
***************
*** 0 ****
--- 1,4 ----
+ #as: -n32 -KPIC
+ #source: macro-warn-2.s
+ #objdump: -p
+ #pass
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-2.s Wed Jan 21 21:14:00 2004
***************
*** 0 ****
--- 1,10 ----
+ .set noreorder
+ .set nomacro
+ local:
+ la $4,late_global
+ la $4,local
+ jr $5
+ la $4,late_global
+ jr $5
+ la $4,local
+ .globl local_global
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-3.d Wed Jan 21 21:25:09 2004
***************
*** 0 ****
--- 1,5 ----
+ #as: -32
+ #source: macro-warn-3.s
+ #stderr: macro-warn-3.l
+ #objdump: -p
+ #pass
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-3.l Wed Jan 21 21:27:16 2004
***************
*** 0 ****
--- 1,3 ----
+ .*: Assembler messages:
+ .*:4: Warning: Macro instruction expanded into multiple instructions
+ .*:7: Warning: Macro instruction expanded into multiple instructions.*slot
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-3.s Wed Jan 21 21:26:56 2004
***************
*** 0 ****
--- 1,10 ----
+ .set noreorder
+ .set nomacro
+ early_big:
+ la $4,early_big
+ la $4,sdata
+ jr $5
+ la $4,early_big
+ jr $5
+ la $4,sdata
+ .comm sdata,4
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-4.d Wed Jan 21 21:28:56 2004
***************
*** 0 ****
--- 1,5 ----
+ #as: -32
+ #source: macro-warn-4.s
+ #stderr: macro-warn-4.l
+ #objdump: -p
+ #pass
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-4.l Wed Jan 21 21:29:29 2004
***************
*** 0 ****
--- 1,3 ----
+ .*: Assembler messages:
+ .*:3: Warning: Macro instruction expanded into multiple instructions
+ .*:5: Warning: Macro instruction expanded into multiple instructions.*slot
*** /dev/null Tue Jun 17 23:06:41 2003
--- testsuite/gas/mips/macro-warn-4.s Wed Jan 21 21:26:37 2004
***************
*** 0 ****
--- 1,7 ----
+ .set noreorder
+ .set nomacro
+ la $4,late_big
+ jr $5
+ la $4,late_big
+ .comm sdata,4
+ late_big: