1 /* tc-mips.c -- assemble code for a MIPS chip.
2 Copyright (C) 1993 Free Software Foundation, Inc.
3 Contributed by the OSF and Ralph Campbell.
4 Written by Keith Knowles and Ralph Campbell, working independently.
5 Modified for ECOFF support by Ian Lance Taylor of Cygnus Support.
7 This file is part of GAS.
9 GAS is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 GAS is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GAS; see the file COPYING. If not, write to
21 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
38 #endif /* NO_VARARGS */
39 #endif /* NO_STDARG */
41 #include "opcode/mips.h"
47 static int mips_warn_about_macros
;
48 static int mips_noreorder
;
49 static int mips_nomove
;
51 static int mips_nobopt
;
54 /* The size of the small data section. */
55 static int g_switch_value
= 8;
61 /* handle of the OPCODE hash table */
62 static struct hash_control
*op_hash
= NULL
;
64 /* This array holds the chars that always start a comment. If the
65 pre-processor is disabled, these aren't very useful */
66 const char comment_chars
[] = "#";
68 /* This array holds the chars that only start a comment at the beginning of
69 a line. If the line seems to have the form '# 123 filename'
70 .line and .file directives will appear in the pre-processed output */
71 /* Note that input_file.c hand checks for '#' at the beginning of the
72 first line of the input file. This is because the compiler outputs
73 #NO_APP at the beginning of its output. */
74 /* Also note that C style comments are always supported. */
75 const char line_comment_chars
[] = "#";
77 /* This array holds machine specific line separator characters. */
78 const char line_separator_chars
[] = "";
80 /* Chars that can be used to separate mant from exp in floating point nums */
81 const char EXP_CHARS
[] = "eE";
83 /* Chars that mean this number is a floating point constant */
86 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
88 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
89 changed in read.c . Ideally it shouldn't have to know about it at all,
90 but nothing is ideal around here.
93 static char *insn_error
;
95 static int byte_order
= BYTE_ORDER
;
97 static int auto_align
= 1;
99 /* Symbol labelling the current insn. */
100 static symbolS
*insn_label
;
102 /* To output NOP instructions correctly, we need to keep information
103 about the previous two instructions. */
105 /* Whether we are optimizing. We always optimize unless -O0 is given.
106 For the very simple optimizations we do, this is compatible with
107 the MIPS assembler. */
108 static int mips_optimize
= 1;
110 /* The previous instruction. */
111 static struct mips_cl_insn prev_insn
;
113 /* The instruction before prev_insn. */
114 static struct mips_cl_insn prev_prev_insn
;
116 /* If we don't want information for prev_insn or prev_prev_insn, we
117 point the insn_mo field at this dummy integer. */
118 static const struct mips_opcode dummy_opcode
= { 0 };
120 /* Non-zero if prev_insn is valid. */
121 static int prev_insn_valid
;
123 /* The frag for the previous instruction. */
124 static struct frag
*prev_insn_frag
;
126 /* The offset into prev_insn_frag for the previous instruction. */
127 static long prev_insn_where
;
129 /* The reloc for the previous instruction, if any. */
130 static fixS
*prev_insn_fixp
;
132 /* Non-zero if the previous instruction was in a delay slot. */
133 static int prev_insn_is_delay_slot
;
135 /* Non-zero if the previous instruction was in a .set noreorder. */
136 static int prev_insn_unreordered
;
138 /* Non-zero if the previous previous instruction was in a .set
140 static int prev_prev_insn_unreordered
;
142 /* Prototypes for static functions. */
145 #define internalError() \
146 as_fatal ("internal Error, line %d, %s", __LINE__, __FILE__)
148 #define internalError() as_fatal ("MIPS internal Error");
151 static int insn_uses_reg
PARAMS ((struct mips_cl_insn
*ip
,
153 static void append_insn
PARAMS ((struct mips_cl_insn
* ip
,
155 bfd_reloc_code_real_type r
));
156 static void mips_no_prev_insn
PARAMS ((void));
157 static void mips_emit_delays
PARAMS ((void));
158 static int gp_reference
PARAMS ((expressionS
* ep
));
159 static void macro_build
PARAMS ((int *counter
, expressionS
* ep
,
160 const char *name
, const char *fmt
,
162 static void macro_build_lui
PARAMS ((int *counter
, expressionS
* ep
,
164 static void set_at
PARAMS ((int *counter
, int reg
));
165 static void set_at_unsigned
PARAMS ((int *counter
, int reg
));
166 static void check_absolute_expr
PARAMS ((struct mips_cl_insn
* ip
,
167 expressionS
* expr
));
168 static void load_register
PARAMS ((int *counter
,
169 struct mips_cl_insn
* ip
,
170 int reg
, expressionS
* ep
));
171 static void macro
PARAMS ((struct mips_cl_insn
* ip
));
172 static void mips_ip
PARAMS ((char *str
, struct mips_cl_insn
* ip
));
173 static int my_getSmallExpression
PARAMS ((expressionS
* ep
, char *str
));
174 static void my_getExpression
PARAMS ((expressionS
* ep
, char *str
));
175 static symbolS
*get_symbol
PARAMS ((void));
176 static void mips_align
PARAMS ((int to
, int fill
));
177 static void s_align
PARAMS ((int));
178 static void s_stringer
PARAMS ((int));
179 static void s_change_sec
PARAMS ((int));
180 static void s_cons
PARAMS ((int));
181 static void s_err
PARAMS ((int));
182 static void s_extern
PARAMS ((int));
183 static void s_float_cons
PARAMS ((int));
184 static void s_option
PARAMS ((int));
185 static void s_mipsset
PARAMS ((int));
186 static void s_mips_space
PARAMS ((int));
188 static void md_obj_begin
PARAMS ((void));
189 static void md_obj_end
PARAMS ((void));
190 static long get_number
PARAMS ((void));
191 static void s_ent
PARAMS ((int));
192 static void s_mipsend
PARAMS ((int));
193 static void s_file
PARAMS ((int));
194 static void s_frame
PARAMS ((int));
195 static void s_loc
PARAMS ((int));
196 static void s_mask
PARAMS ((char));
201 The following pseudo-ops from the Kane and Heinrich MIPS book
202 should be defined here, but are currently unsupported: .alias,
203 .galive, .gjaldef, .gjrlive, .livereg, .noalias.
205 The following pseudo-ops from the Kane and Heinrich MIPS book are
206 specific to the type of debugging information being generated, and
207 should be defined by the object format: .aent, .begin, .bend,
208 .bgnb, .end, .endb, .ent, .fmask, .frame, .loc, .mask, .verstamp,
211 The following pseudo-ops from the Kane and Heinrich MIPS book are
212 not MIPS CPU specific, but are also not specific to the object file
213 format. This file is probably the best place to define them, but
214 they are not currently supported: .asm0, .endr, .lab, .repeat,
215 .struct, .weakext. */
217 const pseudo_typeS md_pseudo_table
[] =
219 /* MIPS specific pseudo-ops. */
220 {"option", s_option
, 0},
221 {"set", s_mipsset
, 0},
222 {"rdata", s_change_sec
, 'r',},
223 {"sdata", s_change_sec
, 's',},
225 /* Relatively generic pseudo-ops that happen to be used on MIPS
227 {"asciiz", s_stringer
, 1},
228 {"bss", s_change_sec
, 'b'},
232 /* These pseudo-ops are defined in read.c, but must be overridden
233 here for one reason or another. */
234 {"align", s_align
, 0},
235 {"ascii", s_stringer
, 0},
236 {"asciz", s_stringer
, 1},
238 {"data", s_change_sec
, 'd'},
239 {"double", s_float_cons
, 'd'},
240 {"extern", s_extern
, 0},
241 {"float", s_float_cons
, 'f'},
242 {"space", s_mips_space
, 0},
243 {"text", s_change_sec
, 't'},
247 /* These pseudo-ops should be defined by the object file format.
248 However, ECOFF is the only format which currently defines them,
249 so we have versions here for a.out. */
251 {"end", s_mipsend
, 0},
254 {"fmask", s_ignore
, 'F'},
255 {"frame", s_ignore
, 0},
256 {"loc", s_ignore
, 0},
257 {"mask", s_ignore
, 'R'},
258 {"verstamp", s_ignore
, 0},
265 const relax_typeS md_relax_table
[] =
271 static char *expr_end
;
273 static expressionS imm_expr
;
274 static expressionS offset_expr
;
275 static bfd_reloc_code_real_type imm_reloc
;
276 static bfd_reloc_code_real_type offset_reloc
;
279 * This function is called once, at assembler startup time. It should
280 * set up all the tables, etc. that the MD part of the assembler will need.
285 register char *retval
= NULL
;
286 register unsigned int i
= 0;
288 if ((op_hash
= hash_new ()) == NULL
)
290 as_fatal ("Virtual memory exhausted");
292 for (i
= 0; i
< NUMOPCODES
;)
294 const char *name
= mips_opcodes
[i
].name
;
296 retval
= hash_insert (op_hash
, name
, &mips_opcodes
[i
]);
297 if (retval
!= NULL
&& *retval
!= '\0')
299 fprintf (stderr
, "internal error: can't hash `%s': %s\n",
300 mips_opcodes
[i
].name
, retval
);
301 as_fatal ("Broken assembler. No assembly attempted.");
305 if ((mips_opcodes
[i
].match
& mips_opcodes
[i
].mask
) !=
306 mips_opcodes
[i
].match
)
308 fprintf (stderr
, "internal error: bad opcode: `%s' \"%s\"\n",
309 mips_opcodes
[i
].name
, mips_opcodes
[i
].args
);
310 as_fatal ("Broken assembler. No assembly attempted.");
314 while ((i
< NUMOPCODES
) && !strcmp (mips_opcodes
[i
].name
, name
));
317 mips_no_prev_insn ();
336 struct mips_cl_insn insn
;
341 /* set the default alignment for the text section (2**2) */
342 /* This should go in md_begin but text_section isn't initialized then */
343 record_alignment (text_section
, 2);
345 bfd_set_gp_size (stdoutput
, g_switch_value
);
350 imm_expr
.X_op
= O_absent
;
351 offset_expr
.X_op
= O_absent
;
353 mips_ip (str
, &insn
);
356 as_bad ("%s `%s'", insn_error
, str
);
359 if (insn
.insn_mo
->pinfo
== INSN_MACRO
)
365 if (imm_expr
.X_op
!= O_absent
)
366 append_insn (&insn
, &imm_expr
, imm_reloc
);
367 else if (offset_expr
.X_op
!= O_absent
)
368 append_insn (&insn
, &offset_expr
, offset_reloc
);
370 append_insn (&insn
, NULL
, BFD_RELOC_UNUSED
);
374 /* See whether instruction IP reads register REG. If FPR is non-zero,
375 REG is a floating point register. */
378 insn_uses_reg (ip
, reg
, fpr
)
379 struct mips_cl_insn
*ip
;
383 /* Don't report on general register 0, since it never changes. */
384 if (! fpr
&& reg
== 0)
389 /* If we are called with either $f0 or $f1, we must check $f0.
390 This is not optimal, because it will introduce an unnecessary
391 NOP between "lwc1 $f0" and "swc1 $f1". To fix this we would
392 need to distinguish reading both $f0 and $f1 or just one of
393 them. Note that we don't have to check the other way,
394 because there is no instruction that sets both $f0 and $f1
395 and requires a delay. */
396 if ((ip
->insn_mo
->pinfo
& INSN_READ_FPR_S
)
397 && ((ip
->insn_opcode
>> OP_SH_FS
) & OP_MASK_FS
) == (reg
&~ 1))
399 if ((ip
->insn_mo
->pinfo
& INSN_READ_FPR_T
)
400 && ((ip
->insn_opcode
>> OP_SH_FT
) & OP_MASK_FT
) == (reg
&~ 1))
405 if ((ip
->insn_mo
->pinfo
& INSN_READ_GPR_S
)
406 && ((ip
->insn_opcode
>> OP_SH_RS
) & OP_MASK_RS
) == reg
)
408 if ((ip
->insn_mo
->pinfo
& INSN_READ_GPR_T
)
409 && ((ip
->insn_opcode
>> OP_SH_RT
) & OP_MASK_RT
) == reg
)
416 #define ALIGN_ERR "Attempt to assemble instruction onto non word boundary."
417 #define ALIGN_ERR2 "GAS doesn't do implicit alignment; use .align directive."
421 * Output an instruction.
424 append_insn (ip
, address_expr
, reloc_type
)
425 struct mips_cl_insn
*ip
;
426 expressionS
*address_expr
;
427 bfd_reloc_code_real_type reloc_type
;
433 if (! mips_noreorder
)
435 /* If the previous insn required any delay slots, see if we need
436 to insert a NOP or two. There are six kinds of possible
437 hazards, of which an instruction can have at most one type.
439 (2) an unconditional branch delay
440 (3) a conditional branch delay
441 (4) a generic coprocessor delay
442 (5) a coprocessor condition code delay
443 (6) a HI/LO special register delay
445 There are a lot of optimizations we could do that we don't.
446 In particular, we do not, in general, reorder instructions.
447 If you use gcc with optimization, it will reorder
448 instructions and generally do much more optimization then we
449 do here; repeating all that work in the assembler would only
450 benefit hand written assembly code, and does not seem worth
453 /* This is how a NOP is emitted. */
454 #define emit_nop() md_number_to_chars (frag_more (4), 0, 4)
456 /* The previous insn might require a delay slot, depending upon
457 the contents of the current insn. */
458 if (prev_insn
.insn_mo
->pinfo
& INSN_LOAD_DELAY
)
460 /* A load delay. All load delays delay the use of general
461 register rt for one instruction. */
462 know (prev_insn
.insn_mo
->pinfo
& INSN_WRITE_GPR_T
);
463 if (insn_uses_reg (ip
,
464 (prev_insn
.insn_opcode
>> OP_SH_RT
) & OP_MASK_RT
,
468 else if (prev_insn
.insn_mo
->pinfo
& INSN_COPROC_DELAY
)
470 /* A generic coprocessor delay. The previous instruction
471 modified a coprocessor general or control register. If
472 it modified a control register, we need to avoid any
473 coprocessor instruction (this is probably not always
474 required, but it sometimes is). If it modified a general
475 register, we avoid using that register.
477 This case is not handled very well. There is no special
478 knowledge of CP0 handling, and the coprocessors other
479 than the floating point unit are not distinguished at
481 if (prev_insn
.insn_mo
->pinfo
& INSN_WRITE_FPR_T
)
483 if (insn_uses_reg (ip
,
484 ((prev_insn
.insn_opcode
>> OP_SH_RT
)
489 else if (prev_insn
.insn_mo
->pinfo
& INSN_WRITE_FPR_D
)
491 if (insn_uses_reg (ip
,
492 ((prev_insn
.insn_opcode
>> OP_SH_RD
)
499 /* We don't know exactly what the previous instruction
500 does. If the current instruction uses a coprocessor
501 register, we must insert a NOP. If previous
502 instruction may set the condition codes, and the
503 current instruction uses them, we must insert two
505 if ((prev_insn
.insn_mo
->pinfo
& INSN_WRITE_COND_CODE
)
506 && (ip
->insn_mo
->pinfo
& INSN_READ_COND_CODE
))
508 else if (ip
->insn_mo
->pinfo
& INSN_COP
)
512 else if (prev_insn
.insn_mo
->pinfo
& INSN_WRITE_COND_CODE
)
514 /* The previous instruction sets the coprocessor condition
515 codes, but does not require a general coprocessor delay
516 (this means it is a floating point comparison
517 instruction). If this instruction uses the condition
518 codes, we need to insert a single NOP. */
519 if (ip
->insn_mo
->pinfo
& INSN_READ_COND_CODE
)
522 else if (prev_insn
.insn_mo
->pinfo
& INSN_READ_LO
)
524 /* The previous instruction reads the LO register; if the
525 current instruction writes to the LO register, we must
527 if (ip
->insn_mo
->pinfo
& INSN_WRITE_LO
)
530 else if (prev_insn
.insn_mo
->pinfo
& INSN_READ_HI
)
532 /* The previous instruction reads the HI register; if the
533 current instruction writes to the HI register, we must
535 if (ip
->insn_mo
->pinfo
& INSN_WRITE_HI
)
539 /* There are two cases which require two intervening
540 instructions: 1) setting the condition codes using a move to
541 coprocessor instruction which requires a general coprocessor
542 delay and then reading the condition codes 2) reading the HI
543 or LO register and then writing to it. If we are not already
544 emitting a NOP instruction, we must check for these cases
545 compared to the instruction previous to the previous
548 && (((prev_prev_insn
.insn_mo
->pinfo
& INSN_COPROC_DELAY
)
549 && (prev_prev_insn
.insn_mo
->pinfo
& INSN_WRITE_COND_CODE
)
550 && (ip
->insn_mo
->pinfo
& INSN_READ_COND_CODE
))
551 || ((prev_prev_insn
.insn_mo
->pinfo
& INSN_READ_LO
)
552 && (ip
->insn_mo
->pinfo
& INSN_WRITE_LO
))
553 || ((prev_prev_insn
.insn_mo
->pinfo
& INSN_READ_HI
)
554 && (ip
->insn_mo
->pinfo
& INSN_WRITE_HI
))))
557 /* Now emit the right number of NOP instructions. */
563 if (insn_label
!= NULL
)
565 assert (S_GET_SEGMENT (insn_label
) == now_seg
);
566 insn_label
->sy_frag
= frag_now
;
567 S_SET_VALUE (insn_label
, frag_now_fix ());
574 /* This is testing the address of the frag, not the alignment of
575 the instruction in the current section. */
583 if (address_expr
!= NULL
)
585 if (address_expr
->X_op
== O_constant
)
590 ip
->insn_opcode
|= address_expr
->X_add_number
;
594 ip
->insn_opcode
|= address_expr
->X_add_number
& 0xffff;
597 case BFD_RELOC_MIPS_JMP
:
598 case BFD_RELOC_16_PCREL_S2
:
607 assert (reloc_type
!= BFD_RELOC_UNUSED
);
609 fixp
= fix_new_exp (frag_now
, f
- frag_now
->fr_literal
, 4,
611 reloc_type
== BFD_RELOC_16_PCREL_S2
,
616 md_number_to_chars (f
, ip
->insn_opcode
, 4);
618 if (! mips_noreorder
)
620 /* Filling the branch delay slot is more complex. We try to
621 switch the branch with the previous instruction, which we can
622 do if the previous instruction does not set up a condition
623 that the branch tests and if the branch is not itself the
624 target of any branch. */
625 if ((ip
->insn_mo
->pinfo
& INSN_UNCOND_BRANCH_DELAY
)
626 || (ip
->insn_mo
->pinfo
& INSN_COND_BRANCH_DELAY
))
629 /* If we had to emit any NOP instructions, then we
630 already know we can not swap. */
632 /* If we don't even know the previous insn, we can not
635 /* If the previous insn is already in a branch delay
636 slot, then we can not swap. */
637 || prev_insn_is_delay_slot
638 /* If the previous previous insn was in a .set
639 noreorder, we can't swap. Actually, the MIPS
640 assembler will swap in this situation. However, gcc
641 configured -with-gnu-as will generate code like
647 in which we can not swap the bne and INSN. If gcc is
648 not configured -with-gnu-as, it does not output the
649 .set pseudo-ops. We don't have to check
650 prev_insn_unreordered, because prev_insn_valid will
651 be 0 in that case. We don't want to use
652 prev_prev_insn_valid, because we do want to be able
653 to swap at the start of a function. */
654 || prev_prev_insn_unreordered
655 /* If the branch is itself the target of a branch, we
656 can not swap. We cheat on this; all we check for is
657 whether there is a label on this instruction. If
658 there are any branches to anything other than a
659 label, users must use .set noreorder. */
660 || insn_label
!= NULL
661 /* If the branch reads the condition codes, we don't
662 even try to swap, because in the sequence
667 we can not swap, and I don't feel like handling that
669 || (ip
->insn_mo
->pinfo
& INSN_READ_COND_CODE
)
670 /* We can not swap with an instruction that requires a
671 delay slot, becase the target of the branch might
672 interfere with that instruction. */
673 || (prev_insn
.insn_mo
->pinfo
676 | INSN_WRITE_COND_CODE
679 /* We can not swap with a branch instruction. */
680 || (prev_insn
.insn_mo
->pinfo
681 & (INSN_UNCOND_BRANCH_DELAY
| INSN_COND_BRANCH_DELAY
))
682 /* If the branch reads a register that the previous
683 instruction sets, we can not swap. */
684 || ((prev_insn
.insn_mo
->pinfo
& INSN_WRITE_GPR_T
)
685 && insn_uses_reg (ip
,
686 ((prev_insn
.insn_opcode
>> OP_SH_RT
)
689 || ((prev_insn
.insn_mo
->pinfo
& INSN_WRITE_GPR_D
)
690 && insn_uses_reg (ip
,
691 ((prev_insn
.insn_opcode
>> OP_SH_RD
)
694 /* If the branch writes a register that the previous
695 instruction reads, we can not swap (we know that
696 branches only write to RD or to $31). */
697 || ((ip
->insn_mo
->pinfo
& INSN_WRITE_GPR_D
)
698 && insn_uses_reg (&prev_insn
,
699 ((ip
->insn_opcode
>> OP_SH_RD
)
702 || ((ip
->insn_mo
->pinfo
& INSN_WRITE_GPR_31
)
703 && insn_uses_reg (&prev_insn
, 31, 0))
704 /* If the previous previous instruction has a load
705 delay, and sets a register that the branch reads, we
707 || ((prev_prev_insn
.insn_mo
->pinfo
& INSN_LOAD_DELAY
)
708 && insn_uses_reg (ip
,
709 ((prev_prev_insn
.insn_opcode
>> OP_SH_RT
)
713 /* We could do even better for unconditional branches to
714 portions of this object file; we could pick up the
715 instruction at the destination, put it in the delay
716 slot, and bump the destination address. */
718 /* Update the previous insn information. */
719 prev_prev_insn
= *ip
;
720 prev_insn
.insn_mo
= &dummy_opcode
;
727 /* It looks like we can actually do the swap. */
728 prev_f
= prev_insn_frag
->fr_literal
+ prev_insn_where
;
729 memcpy (temp
, prev_f
, 4);
730 memcpy (prev_f
, f
, 4);
734 prev_insn_fixp
->fx_frag
= frag_now
;
735 prev_insn_fixp
->fx_where
= f
- frag_now
->fr_literal
;
739 fixp
->fx_frag
= prev_insn_frag
;
740 fixp
->fx_where
= prev_insn_where
;
742 /* Update the previous insn information; leave prev_insn
744 prev_prev_insn
= *ip
;
746 prev_insn_is_delay_slot
= 1;
748 /* If that was an unconditional branch, forget the previous
750 if (ip
->insn_mo
->pinfo
& INSN_UNCOND_BRANCH_DELAY
)
752 prev_prev_insn
.insn_mo
= &dummy_opcode
;
753 prev_insn
.insn_mo
= &dummy_opcode
;
758 /* Update the previous insn information. */
760 prev_prev_insn
.insn_mo
= &dummy_opcode
;
762 prev_prev_insn
= prev_insn
;
765 /* Any time we see a branch, we always fill the delay slot
766 immediately; since this insn is not a branch, we know it
767 is not in a delay slot. */
768 prev_insn_is_delay_slot
= 0;
771 prev_prev_insn_unreordered
= prev_insn_unreordered
;
772 prev_insn_unreordered
= 0;
773 prev_insn_frag
= frag_now
;
774 prev_insn_where
= f
- frag_now
->fr_literal
;
775 prev_insn_fixp
= fixp
;
779 /* We just output an insn, so the next one doesn't have a label. */
783 /* This function forgets that there was any previous instruction or
789 prev_insn
.insn_mo
= &dummy_opcode
;
790 prev_prev_insn
.insn_mo
= &dummy_opcode
;
792 prev_insn_is_delay_slot
= 0;
793 prev_insn_unreordered
= 0;
794 prev_prev_insn_unreordered
= 0;
798 /* This function must be called whenever we turn on noreorder or emit
799 something other than instructions. It inserts any NOPS which might
800 be needed by the previous instruction, and clears the information
801 kept for the previous instructions. */
806 if (! mips_noreorder
)
811 if (prev_insn
.insn_mo
->pinfo
& ANY_DELAY
)
814 if ((prev_insn
.insn_mo
->pinfo
& INSN_WRITE_COND_CODE
)
815 || (prev_insn
.insn_mo
->pinfo
& INSN_READ_HI
)
816 || (prev_insn
.insn_mo
->pinfo
& INSN_READ_LO
))
819 else if ((prev_prev_insn
.insn_mo
->pinfo
& INSN_WRITE_COND_CODE
)
820 || (prev_prev_insn
.insn_mo
->pinfo
& INSN_READ_HI
)
821 || (prev_prev_insn
.insn_mo
->pinfo
& INSN_READ_LO
))
826 if (insn_label
!= NULL
)
828 assert (S_GET_SEGMENT (insn_label
) == now_seg
);
829 insn_label
->sy_frag
= frag_now
;
830 S_SET_VALUE (insn_label
, frag_now_fix ());
833 mips_no_prev_insn ();
837 /* Return 1 if an expression can be accessed via the GP register. */
848 sym
= ep
->X_add_symbol
;
849 if (sym
== (symbolS
*) NULL
850 || ep
->X_op_symbol
!= (symbolS
*) NULL
)
853 /* Certain symbols can not be referenced off the GP, although it
854 appears as though they can. */
855 symname
= S_GET_NAME (sym
);
856 if (symname
!= (const char *) NULL
857 && (strcmp (symname
, "eprol") == 0
858 || strcmp (symname
, "etext") == 0
859 || strcmp (symname
, "_gp") == 0
860 || strcmp (symname
, "edata") == 0
861 || strcmp (symname
, "_fbss") == 0
862 || strcmp (symname
, "_fdata") == 0
863 || strcmp (symname
, "_ftext") == 0
864 || strcmp (symname
, "end") == 0))
866 if (! S_IS_DEFINED (sym
)
867 && S_GET_VALUE (sym
) != 0
868 && S_GET_VALUE (sym
) <= g_switch_value
)
870 segname
= segment_name (S_GET_SEGMENT (ep
->X_add_symbol
));
871 return (strcmp (segname
, ".sdata") == 0
872 || strcmp (segname
, ".sbss") == 0);
873 #else /* ! defined (OBJ_ECOFF) */
874 /* The GP register is only used for ECOFF. */
876 #endif /* ! defined (OBJ_ECOFF) */
879 /* Build an instruction created by a macro expansion. This is passed
880 a pointer to the count of instructions created so far, an
881 expression, the name of the instruction to build, an operand format
882 string, and corresponding arguments. */
886 macro_build (int *counter
,
891 #else /* ! defined (NO_STDARG) */
893 macro_build (counter
, ep
, name
, fmt
, va_alist
)
899 #endif /* ! defined (NO_STDARG) */
901 struct mips_cl_insn insn
;
902 bfd_reloc_code_real_type r
;
906 va_start (args
, fmt
);
912 * If the macro is about to expand into a second instruction,
913 * print a warning if needed. We need to pass ip as a parameter
914 * to generate a better warning message here...
916 if (mips_warn_about_macros
&& *counter
== 1)
917 as_warn ("Macro instruction expanded into multiple instructions");
919 *counter
+= 1; /* bump instruction counter */
921 r
= BFD_RELOC_UNUSED
;
922 insn
.insn_mo
= (struct mips_opcode
*) hash_find (op_hash
, name
);
923 assert (insn
.insn_mo
);
924 assert (strcmp (name
, insn
.insn_mo
->name
) == 0);
926 while (strcmp (fmt
, insn
.insn_mo
->args
) != 0)
929 assert (insn
.insn_mo
->name
);
930 assert (strcmp (name
, insn
.insn_mo
->name
) == 0);
932 assert (insn
.insn_mo
->pinfo
!= INSN_MACRO
);
933 insn
.insn_opcode
= insn
.insn_mo
->match
;
949 insn
.insn_opcode
|= va_arg (args
, int) << 16;
955 insn
.insn_opcode
|= va_arg (args
, int) << 16;
960 insn
.insn_opcode
|= va_arg (args
, int) << 11;
965 insn
.insn_opcode
|= va_arg (args
, int) << 11;
969 insn
.insn_opcode
|= va_arg (args
, int) << 6;
973 insn
.insn_opcode
|= va_arg (args
, int) << 6;
977 insn
.insn_opcode
|= va_arg (args
, int) << 6;
984 insn
.insn_opcode
|= va_arg (args
, int) << 21;
996 * This allows macro() to pass an immediate expression for
997 * creating short branches without creating a symbol.
998 * Note that the expression still might come from the assembly
999 * input, in which case the value is not checked for range nor
1000 * is a relocation entry generated (yuck).
1002 if (ep
->X_op
== O_constant
)
1004 insn
.insn_opcode
|= (ep
->X_add_number
>> 2) & 0xffff;
1008 r
= BFD_RELOC_16_PCREL_S2
;
1017 assert (r
== BFD_RELOC_UNUSED
? ep
== NULL
: ep
!= NULL
);
1019 /* Use GP relative addressing if possible. */
1020 if (r
== BFD_RELOC_LO16
1021 && gp_reference (ep
))
1022 r
= BFD_RELOC_MIPS_GPREL
;
1024 append_insn (&insn
, ep
, r
);
1028 * Generate a "lui" instruction.
1031 macro_build_lui (counter
, ep
, regnum
)
1036 expressionS high_expr
;
1037 struct mips_cl_insn insn
;
1038 bfd_reloc_code_real_type r
;
1039 CONST
char *name
= "lui";
1040 CONST
char *fmt
= "t,u";
1044 if (high_expr
.X_op
== O_constant
)
1046 /* we can compute the instruction now without a relocation entry */
1047 if (high_expr
.X_add_number
& 0x8000)
1048 high_expr
.X_add_number
+= 0x10000;
1049 high_expr
.X_add_number
=
1050 ((unsigned long) high_expr
.X_add_number
>> 16) & 0xffff;
1051 r
= BFD_RELOC_UNUSED
;
1054 r
= BFD_RELOC_HI16_S
;
1057 * If the macro is about to expand into a second instruction,
1058 * print a warning if needed. We need to pass ip as a parameter
1059 * to generate a better warning message here...
1061 if (mips_warn_about_macros
&& *counter
== 1)
1062 as_warn ("Macro instruction expanded into multiple instructions");
1064 *counter
+= 1; /* bump instruction counter */
1066 insn
.insn_mo
= (struct mips_opcode
*) hash_find (op_hash
, name
);
1067 assert (insn
.insn_mo
);
1068 assert (strcmp (name
, insn
.insn_mo
->name
) == 0);
1069 assert (strcmp (fmt
, insn
.insn_mo
->args
) == 0);
1071 insn
.insn_opcode
= insn
.insn_mo
->match
| (regnum
<< 16);
1072 if (r
== BFD_RELOC_UNUSED
)
1074 insn
.insn_opcode
|= high_expr
.X_add_number
;
1075 append_insn (&insn
, NULL
, r
);
1078 append_insn (&insn
, &high_expr
, r
);
1082 * Generates code to set the $at register to true (one)
1083 * if reg is less than the immediate expression.
1086 set_at (counter
, reg
)
1091 switch (imm_expr
.X_add_number
& 0xffff8000)
1095 macro_build (counter
, &imm_expr
, "slti", "t,r,j", AT
, reg
);
1099 macro_build (counter
, &imm_expr
, "ori", "t,r,i", AT
, 0);
1103 macro_build_lui (counter
, &imm_expr
, AT
);
1104 if (imm_expr
.X_add_number
& 0xffff)
1105 macro_build (counter
, &imm_expr
, "addiu", "t,r,j", AT
, AT
);
1107 macro_build (counter
, NULL
, "slt", "d,v,t", AT
, reg
, AT
);
1110 /* set_at_unsigned()
1111 * Generates code to set the $at register to true (one)
1112 * if reg is less than the immediate expression.
1113 * Unsigned comparison is perfomed.
1116 set_at_unsigned (counter
, reg
)
1121 switch (imm_expr
.X_add_number
& 0xffff8000)
1125 macro_build (counter
, &imm_expr
, "sltiu", "t,r,j", AT
, reg
);
1129 macro_build (counter
, &imm_expr
, "ori", "t,r,i", AT
, 0);
1133 macro_build_lui (counter
, &imm_expr
, AT
);
1134 if (imm_expr
.X_add_number
& 0xffff)
1135 macro_build (counter
, &imm_expr
, "addiu", "t,r,j", AT
, AT
);
1137 macro_build (counter
, NULL
, "sltu", "d,v,t", AT
, reg
, AT
);
1141 check_absolute_expr (ip
, expr
)
1142 struct mips_cl_insn
*ip
;
1146 if (expr
->X_op
!= O_constant
)
1147 as_warn ("Instruction %s requires absolute expression", ip
->insn_mo
->name
);
1151 * This routine generates the least number of instructions neccessary to load
1152 * an absolute expression value into a register.
1155 load_register (counter
, ip
, reg
, ep
)
1157 struct mips_cl_insn
*ip
;
1161 switch (ep
->X_add_number
& 0xffff8000)
1165 macro_build (counter
, ep
, "addiu", "t,r,j", reg
, 0);
1169 macro_build (counter
, ep
, "ori", "t,r,i", reg
, 0);
1173 macro_build_lui (counter
, ep
, reg
);
1174 if (ep
->X_add_number
& 0xffff)
1175 macro_build (counter
, ep
, "addiu", "t,r,j", reg
, reg
);
1182 * This routine implements the seemingly endless macro or synthesized
1183 * instructions and addressing modes in the mips assembly language. Many
1184 * of these macros are simple and are similar to each other. These could
1185 * probably be handled by some kind of table or grammer aproach instead of
1186 * this verbose method. Others are not simple macros but are more like
1187 * optimizing code generation.
1188 * One interesting optimization is when several store macros appear
1189 * consecutivly that would load AT with the upper half of the same address.
1190 * The ensuing load upper instructions are ommited. This implies some kind
1191 * of global optimization. We currently only optimize within a single macro.
1192 * For many of the load and store macros if the address is specified as a
1193 * constant expression in the first 64k of memory (ie ld $2,0x4000c) we
1194 * first load register 'at' with zero and use it as the base register. The
1195 * mips assembler simply uses register $zero. Just one tiny optimization
1200 struct mips_cl_insn
*ip
;
1202 register int treg
, sreg
, dreg
, breg
;
1211 treg
= (ip
->insn_opcode
>> 16) & 0x1f;
1212 dreg
= (ip
->insn_opcode
>> 11) & 0x1f;
1213 sreg
= breg
= (ip
->insn_opcode
>> 21) & 0x1f;
1214 mask
= ip
->insn_mo
->mask
;
1216 expr1
.X_op
= O_constant
;
1217 expr1
.X_op_symbol
= NULL
;
1218 expr1
.X_add_symbol
= NULL
;
1219 expr1
.X_add_number
= 1;
1226 Note: mips algorithm requires the move in the delay slot.
1227 <main>: bgez $a0,0x4001bc <main+12>
1228 <main+4>: move v0,$a0
1229 <main+8>: sub v0,$zero,$a0
1233 mips_emit_delays ();
1236 expr1
.X_add_number
= 8;
1237 macro_build (&icnt
, &expr1
, "bgez", "s,p", sreg
);
1238 macro_build (&icnt
, NULL
, "move", "d,s", dreg
, sreg
, 0);
1239 macro_build (&icnt
, NULL
, mask
== M_ABS
? "sub" : "subu", "d,v,t",
1247 switch (imm_expr
.X_add_number
& 0xffff8000)
1251 macro_build (&icnt
, &imm_expr
,
1252 mask
== M_ADD_I
? "addi" : "addiu", "t,r,j", treg
, sreg
);
1256 macro_build (&icnt
, &imm_expr
, "ori", "t,r,i", AT
, 0);
1260 macro_build_lui (&icnt
, &imm_expr
, AT
);
1261 if (imm_expr
.X_add_number
& 0xffff)
1262 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", AT
, AT
);
1265 macro_build (&icnt
, NULL
,
1266 mask
== M_ADD_I
? "add" : "addu", "d,v,t", treg
, sreg
, AT
);
1273 switch (imm_expr
.X_add_number
& 0xffff8000)
1280 macro_build (&icnt
, &imm_expr
, "andi", "t,r,i", treg
, sreg
);
1283 macro_build (&icnt
, &imm_expr
, "ori", "t,r,i", treg
, sreg
);
1286 macro_build (&icnt
, &imm_expr
, "ori", "t,r,i", treg
, sreg
);
1287 macro_build (&icnt
, &imm_expr
, "nor", "d,v,t", treg
, treg
, 0);
1290 macro_build (&icnt
, &imm_expr
, "xori", "t,r,i", treg
, sreg
);
1297 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", AT
, 0);
1301 macro_build_lui (&icnt
, &imm_expr
, AT
);
1302 if (imm_expr
.X_add_number
& 0xffff)
1303 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", AT
, AT
);
1308 macro_build (&icnt
, NULL
, "and", "d,v,t", treg
, sreg
, AT
);
1311 macro_build (&icnt
, NULL
, "or", "d,v,t", treg
, sreg
, AT
);
1314 macro_build (&icnt
, NULL
, "nor", "d,v,t", treg
, sreg
, AT
);
1317 macro_build (&icnt
, NULL
, "xor", "d,v,t", treg
, sreg
, AT
);
1326 if (imm_expr
.X_add_number
== 0)
1328 macro_build (&icnt
, &offset_expr
, mask
== M_BEQ_I
? "beq" : "bne",
1332 load_register (&icnt
, ip
, AT
, &imm_expr
);
1333 macro_build (&icnt
, &offset_expr
, mask
== M_BEQ_I
? "beq" : "bne",
1340 macro_build (&icnt
, &offset_expr
, "bgez", "s,p", sreg
);
1345 macro_build (&icnt
, &offset_expr
, "blez", "s,p", treg
);
1348 macro_build (&icnt
, NULL
, "slt", "d,v,t", AT
, sreg
, treg
);
1349 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", AT
, 0);
1353 /* check for > max integer */
1354 if (imm_expr
.X_add_number
== 0x7fffffff)
1357 /* result is always false */
1358 as_warn ("Branch %s is always false (nop)", ip
->insn_mo
->name
);
1359 macro_build (&icnt
, NULL
, "nop", "", 0);
1362 imm_expr
.X_add_number
++;
1366 if (imm_expr
.X_add_number
== 0)
1368 macro_build (&icnt
, &offset_expr
, "bgez", "s,p", sreg
);
1371 if (imm_expr
.X_add_number
== 1)
1373 macro_build (&icnt
, &offset_expr
, "bgtz", "s,p", sreg
);
1376 if (imm_expr
.X_add_number
== 0x80000000)
1379 /* result is always true */
1380 as_warn ("Branch %s is always true", ip
->insn_mo
->name
);
1381 macro_build (&icnt
, &offset_expr
, "b", "p");
1384 set_at (&icnt
, sreg
);
1385 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", AT
, 0);
1393 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", 0, treg
);
1396 macro_build (&icnt
, NULL
, "sltu", "d,v,t", AT
, sreg
, treg
);
1397 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", AT
, 0);
1401 if (sreg
== 0 || imm_expr
.X_add_number
== 0xffffffff)
1403 imm_expr
.X_add_number
++;
1407 if (imm_expr
.X_add_number
== 0)
1409 if (imm_expr
.X_add_number
== 1)
1411 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", sreg
, 0);
1414 set_at_unsigned (&icnt
, sreg
);
1415 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", AT
, 0);
1421 macro_build (&icnt
, &offset_expr
, "bgtz", "s,p", sreg
);
1426 macro_build (&icnt
, &offset_expr
, "bltz", "s,p", treg
);
1429 macro_build (&icnt
, NULL
, "slt", "d,v,t", AT
, treg
, sreg
);
1430 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", AT
, 0);
1436 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", sreg
, 0);
1441 macro_build (&icnt
, NULL
, "sltu", "d,v,t", AT
, treg
, sreg
);
1442 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", AT
, 0);
1448 macro_build (&icnt
, &offset_expr
, "blez", "s,p", sreg
);
1453 macro_build (&icnt
, &offset_expr
, "bgez", "s,p", treg
);
1456 macro_build (&icnt
, NULL
, "slt", "d,v,t", AT
, treg
, sreg
);
1457 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", AT
, 0);
1461 if (imm_expr
.X_add_number
== 0x7fffffff)
1463 imm_expr
.X_add_number
++;
1467 if (imm_expr
.X_add_number
== 0)
1469 macro_build (&icnt
, &offset_expr
, "bltz", "s,p", sreg
);
1472 if (imm_expr
.X_add_number
== 1)
1474 macro_build (&icnt
, &offset_expr
, "blez", "s,p", sreg
);
1477 set_at (&icnt
, sreg
);
1478 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", AT
, 0);
1484 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", sreg
, 0);
1489 macro_build (&icnt
, NULL
, "sltu", "d,v,t", AT
, treg
, sreg
);
1490 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", AT
, 0);
1494 if (sreg
== 0 || imm_expr
.X_add_number
== 0xffffffff)
1496 imm_expr
.X_add_number
++;
1500 if (imm_expr
.X_add_number
== 0)
1502 if (imm_expr
.X_add_number
== 1)
1504 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", sreg
, 0);
1507 set_at_unsigned (&icnt
, sreg
);
1508 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", AT
, 0);
1514 macro_build (&icnt
, &offset_expr
, "bltz", "s,p", sreg
);
1519 macro_build (&icnt
, &offset_expr
, "bgtz", "s,p", treg
);
1522 macro_build (&icnt
, NULL
, "slt", "d,v,t", AT
, sreg
, treg
);
1523 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", AT
, 0);
1531 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", 0, treg
);
1534 macro_build (&icnt
, NULL
, "sltu", "d,v,t", AT
, sreg
, treg
);
1535 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", AT
, 0);
1542 as_warn ("Divide by zero.");
1543 macro_build (&icnt
, NULL
, "break", "c", 7);
1547 mips_emit_delays ();
1549 macro_build (&icnt
, NULL
, "div", "s,t", sreg
, treg
);
1550 expr1
.X_add_number
= 8;
1551 macro_build (&icnt
, &expr1
, "bne", "s,t,p", treg
, 0);
1552 macro_build (&icnt
, NULL
, "nop", "", 0);
1553 macro_build (&icnt
, NULL
, "break", "c", 7);
1554 expr1
.X_add_number
= -1;
1555 macro_build (&icnt
, &expr1
, "addiu", "t,r,j", AT
, 0);
1556 expr1
.X_add_number
= 16;
1557 macro_build (&icnt
, &expr1
, "bne", "s,t,p", treg
, AT
);
1558 expr1
.X_add_number
= 0x80000000;
1559 macro_build_lui (&icnt
, &expr1
, AT
);
1560 expr1
.X_add_number
= 8;
1561 macro_build (&icnt
, &expr1
, "bne", "s,t,p", sreg
, AT
);
1562 macro_build (&icnt
, NULL
, "nop", "", 0);
1563 macro_build (&icnt
, NULL
, "break", "c", 6);
1565 macro_build (&icnt
, NULL
, mask
== M_DIV_3
? "mflo" : "mfhi", "d", dreg
);
1566 /* with reorder on there will be two implicit nop instructions here. */
1573 if (imm_expr
.X_add_number
== 0)
1575 as_warn ("Divide by zero.");
1576 macro_build (&icnt
, NULL
, "break", "c", 7);
1579 if (imm_expr
.X_add_number
== 1)
1581 if (mask
== (int) M_DIV_3I
|| mask
== (int) M_DIVU_3I
)
1582 macro_build (&icnt
, NULL
, "move", "d,s", dreg
, sreg
);
1584 macro_build (&icnt
, NULL
, "move", "d,s", dreg
, 0);
1588 load_register (&icnt
, ip
, AT
, &imm_expr
);
1589 if (mask
== (int) M_DIV_3I
|| mask
== (int) M_REM_3I
)
1590 macro_build (&icnt
, NULL
, "div", "s,t", sreg
, AT
);
1592 macro_build (&icnt
, NULL
, "divu", "s,t", sreg
, AT
);
1594 if (mask
== (int) M_DIV_3I
|| mask
== (int) M_DIVU_3I
)
1595 macro_build (&icnt
, NULL
, "mflo", "d", dreg
);
1597 macro_build (&icnt
, NULL
, "mfhi", "d", dreg
);
1598 /* two implicit nop's required for mflo or mfhi */
1603 mips_emit_delays ();
1605 macro_build (&icnt
, NULL
, "divu", "s,t", sreg
, treg
);
1606 expr1
.X_add_number
= 8;
1607 macro_build (&icnt
, &expr1
, "bne", "s,t,p", treg
, 0);
1608 macro_build (&icnt
, NULL
, "nop", "", 0);
1609 macro_build (&icnt
, NULL
, "break", "c", 7);
1611 macro_build (&icnt
, NULL
, mask
== M_DIVU_3
? "mflo" : "mfhi", "d", dreg
);
1612 /* with reorder on there will be two implicit nop instructions here. */
1616 if (offset_expr
.X_op
== O_constant
)
1618 load_register (&icnt
, ip
, treg
, &offset_expr
);
1621 if (gp_reference (&offset_expr
))
1622 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", treg
, GP
);
1625 macro_build_lui (&icnt
, &offset_expr
, treg
);
1626 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", treg
, treg
);
1631 tempreg
= (breg
== treg
) ? AT
: treg
;
1632 if (offset_expr
.X_op
== O_constant
)
1633 load_register (&icnt
, ip
, tempreg
, &offset_expr
);
1634 else if (gp_reference (&offset_expr
))
1635 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", tempreg
, GP
);
1638 macro_build_lui (&icnt
, &offset_expr
, tempreg
);
1639 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", tempreg
, tempreg
);
1642 macro_build (&icnt
, NULL
, "addu", "d,v,t", treg
, tempreg
, breg
);
1680 if (breg
== treg
|| mask
== M_LWC1_AB
)
1721 if (mask
== M_LWC1_AB
|| mask
== M_SWC1_AB
)
1725 if (gp_reference (&offset_expr
))
1729 macro_build (&icnt
, &offset_expr
, s
, fmt
, treg
, GP
);
1732 macro_build (&icnt
, (expressionS
*) NULL
, "addu", "d,v,t",
1737 macro_build_lui (&icnt
, &offset_expr
, tempreg
);
1739 macro_build (&icnt
, NULL
, "addu", "d,v,t", tempreg
, tempreg
, breg
);
1741 macro_build (&icnt
, &offset_expr
, s
, fmt
, treg
, tempreg
);
1747 load_register (&icnt
, ip
, treg
, &imm_expr
);
1752 0x400370 <main>: lui $at,%hi(foo)
1753 0x400374 <main+4>: lw $v0,%lo(foo)($at)
1754 0x400378 <main+8>: lw $v1,%lo(foo+4)($at)
1759 /* FIXME: I don't think this is used at present, because the 'F'
1760 format character is not supported. When this is supported,
1761 it should use the GP register. */
1762 macro_build_lui (&icnt
, &offset_expr
, AT
);
1763 macro_build (&icnt
, &offset_expr
, "lw", "t,o(b)", treg
, AT
);
1764 offset_expr
.X_add_number
= 4;
1765 macro_build (&icnt
, &offset_expr
, "lw", "t,o(b)", treg
+ 1, AT
);
1770 0x4003a0 <main>: lwc1 $f0,-32752($gp)
1771 0x4003a4 <main+4>: lwc1 $f1,-32748($gp)
1772 0x4003a8 <main+8>: nop
1774 /* FIXME: This is nonsense. It isn't used anyhow. */
1775 sreg
= (ip
->insn_opcode
>> 11) & 0x1f; /* Fs reg */
1776 macro_build (&icnt
, &offset_expr
, "lwc1", "T,o(b)", treg
, AT
);
1777 offset_expr
.X_add_number
= 4;
1778 macro_build (&icnt
, &offset_expr
, "lwc1", "T,o(b)", treg
+ 1, AT
);
1782 /* Even on a big endian machine $fn comes before $fn+1. We have
1783 to adjust when loading from memory. */
1784 macro_build (&icnt
, &offset_expr
, "lwc1", "T,o(b)",
1785 byte_order
== LITTLE_ENDIAN
? treg
: treg
+ 1,
1787 offset_expr
.X_add_number
+= 4;
1788 macro_build (&icnt
, &offset_expr
, "lwc1", "T,o(b)",
1789 byte_order
== LITTLE_ENDIAN
? treg
+ 1 : treg
,
1795 * The MIPS assembler seems to check for X_add_number not
1796 * being double aligned and generating:
1799 * addiu at,at,%lo(foo+1)
1802 * But, the resulting address is the same after relocation so why
1803 * generate the extra instruction?
1805 if (gp_reference (&offset_expr
))
1811 macro_build (&icnt
, &offset_expr
, "addu", "d,v,t", AT
, breg
, GP
);
1817 macro_build_lui (&icnt
, &offset_expr
, AT
);
1819 macro_build (&icnt
, NULL
, "addu", "d,v,t", AT
, AT
, breg
);
1822 /* Even on a big endian machine $fn comes before $fn+1. We have
1823 to adjust when loading from memory. */
1824 macro_build (&icnt
, &offset_expr
, "lwc1", "T,o(b)",
1825 byte_order
== LITTLE_ENDIAN
? treg
: treg
+ 1,
1827 offset_expr
.X_add_number
+= 4;
1828 macro_build (&icnt
, &offset_expr
, "lwc1", "T,o(b)",
1829 byte_order
== LITTLE_ENDIAN
? treg
+ 1 : treg
,
1841 macro_build (&icnt
, &offset_expr
, s
, "t,o(b)", treg
, breg
);
1842 offset_expr
.X_add_number
= 4;
1843 macro_build (&icnt
, &offset_expr
, s
, "t,o(b)", treg
+ 1, breg
);
1864 if (gp_reference (&offset_expr
))
1872 macro_build (&icnt
, (expressionS
*) NULL
, "addu", "d,v,t",
1877 macro_build_lui (&icnt
, &offset_expr
, tempreg
);
1879 macro_build (&icnt
, NULL
, "addu", "d,v,t", tempreg
, tempreg
, breg
);
1881 macro_build (&icnt
, &offset_expr
, s
, "t,o(b)", treg
, tempreg
);
1882 offset_expr
.X_add_number
+= 4;
1883 macro_build (&icnt
, &offset_expr
, s
, "t,o(b)", treg
+ 1, tempreg
);
1889 macro_build (&icnt
, NULL
, "multu", "s,t", sreg
, treg
);
1890 macro_build (&icnt
, NULL
, "mflo", "d", dreg
);
1891 /* two implicit nop's required for mflo */
1896 * The mips assembler some times generates shifts and adds.
1897 * Im not trying to be that fancy. GCC should do this for us
1900 load_register (&icnt
, ip
, AT
, &imm_expr
);
1901 macro_build (&icnt
, NULL
, "mult", "s,t", sreg
, AT
);
1902 macro_build (&icnt
, NULL
, "mflo", "d", dreg
);
1903 /* two implicit nop's required for mflo */
1907 macro_build (&icnt
, NULL
, "subu", "d,v,t", AT
, 0, treg
);
1908 macro_build (&icnt
, NULL
, "srlv", "d,t,s", AT
, sreg
, AT
);
1909 macro_build (&icnt
, NULL
, "sllv", "d,t,s", dreg
, sreg
, treg
);
1910 macro_build (&icnt
, NULL
, "or", "d,v,t", dreg
, dreg
, AT
);
1914 macro_build (&icnt
, NULL
, "sll", "d,w,<", AT
, sreg
,
1915 imm_expr
.X_add_number
& 0x1f);
1916 macro_build (&icnt
, NULL
, "srl", "d,w,<", dreg
, sreg
,
1917 (0 - imm_expr
.X_add_number
) & 0x1f);
1918 macro_build (&icnt
, NULL
, "or", "d,v,t", dreg
, dreg
, AT
);
1922 macro_build (&icnt
, NULL
, "subu", "d,v,t", AT
, 0, treg
);
1923 macro_build (&icnt
, NULL
, "sllv", "d,t,s", AT
, sreg
, AT
);
1924 macro_build (&icnt
, NULL
, "srlv", "d,t,s", dreg
, sreg
, treg
);
1925 macro_build (&icnt
, NULL
, "or", "d,v,t", dreg
, dreg
, AT
);
1929 macro_build (&icnt
, NULL
, "srl", "d,w,<", AT
, sreg
,
1930 imm_expr
.X_add_number
& 0x1f);
1931 macro_build (&icnt
, NULL
, "sll", "d,w,<", dreg
, sreg
,
1932 (0 - imm_expr
.X_add_number
) & 0x1f);
1933 macro_build (&icnt
, NULL
, "or", "d,v,t", dreg
, dreg
, AT
);
1937 /* Even on a big endian machine $fn comes before $fn+1. We have
1938 to adjust when storing to memory. */
1939 macro_build (&icnt
, &offset_expr
, "swc1", "T,o(b)",
1940 byte_order
== LITTLE_ENDIAN
? treg
: treg
+ 1,
1942 offset_expr
.X_add_number
+= 4;
1943 macro_build (&icnt
, &offset_expr
, "swc1", "T,o(b)",
1944 byte_order
== LITTLE_ENDIAN
? treg
+ 1 : treg
,
1949 if (gp_reference (&offset_expr
))
1955 macro_build (&icnt
, (expressionS
*) NULL
, "addu", "d,v,t",
1962 macro_build_lui (&icnt
, &offset_expr
, AT
);
1964 macro_build (&icnt
, NULL
, "addu", "d,v,t", AT
, AT
, breg
);
1967 /* Even on a big endian machine $fn comes before $fn+1. We have
1968 to adjust when storing to memory. */
1969 macro_build (&icnt
, &offset_expr
, "swc1", "T,o(b)",
1970 byte_order
== LITTLE_ENDIAN
? treg
: treg
+ 1,
1972 offset_expr
.X_add_number
+= 4;
1973 macro_build (&icnt
, &offset_expr
, "swc1", "T,o(b)",
1974 byte_order
== LITTLE_ENDIAN
? treg
+ 1 : treg
,
1982 macro_build (&icnt
, &expr1
, "sltiu", "t,r,j", dreg
, treg
);
1984 macro_build (&icnt
, &expr1
, "sltiu", "t,r,j", dreg
, sreg
);
1987 macro_build (&icnt
, NULL
, "xor", "d,v,t", dreg
, sreg
, treg
);
1988 macro_build (&icnt
, &expr1
, "sltiu", "t,r,j", dreg
, dreg
);
1993 if (imm_expr
.X_add_number
== 0)
1995 macro_build (&icnt
, &expr1
, "sltiu", "t,r,j", dreg
, sreg
);
2000 as_warn ("Instruction %s: result is always false",
2002 macro_build (&icnt
, NULL
, "move", "d,s", dreg
, 0);
2005 switch (imm_expr
.X_add_number
& 0xffff8000)
2009 macro_build (&icnt
, &imm_expr
, "xori", "t,r,i", dreg
, sreg
);
2014 if (imm_expr
.X_add_number
!= -32768)
2016 imm_expr
.X_add_number
= -imm_expr
.X_add_number
;
2017 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", dreg
, sreg
);
2024 macro_build_lui (&icnt
, &imm_expr
, AT
);
2025 if (imm_expr
.X_add_number
& 0xffff)
2026 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", AT
, AT
);
2027 macro_build (&icnt
, NULL
, "xor", "d,v,t", dreg
, sreg
, AT
);
2030 macro_build (&icnt
, &expr1
, "sltiu", "t,r,j", dreg
, dreg
);
2035 case M_SGE
: /* sreg >= treg <==> not (sreg < treg) */
2041 macro_build (&icnt
, NULL
, s
, "d,v,t", dreg
, sreg
, treg
);
2042 macro_build (&icnt
, &expr1
, "xori", "t,r,i", dreg
, dreg
);
2045 case M_SGE_I
: /* sreg >= I <==> not (sreg < I) */
2047 if (imm_expr
.X_add_number
< 32768 && imm_expr
.X_add_number
> -32769)
2049 macro_build (&icnt
, &expr1
,
2050 mask
== M_SGE_I
? "slti" : "sltiu", "t,r,j", dreg
, sreg
);
2055 load_register (&icnt
, ip
, AT
, &imm_expr
);
2056 macro_build (&icnt
, NULL
,
2057 mask
== M_SGE_I
? "slt" : "sltu", "d,v,t", dreg
, sreg
, AT
);
2060 macro_build (&icnt
, &expr1
, "xori", "t,r,i", dreg
, dreg
);
2065 case M_SGT
: /* sreg > treg <==> treg < sreg */
2071 macro_build (&icnt
, NULL
, s
, "d,v,t", dreg
, treg
, sreg
);
2074 case M_SGT_I
: /* sreg > I <==> I < sreg */
2080 load_register (&icnt
, ip
, AT
, &imm_expr
);
2081 macro_build (&icnt
, NULL
, s
, "d,v,t", dreg
, AT
, sreg
);
2084 case M_SLE
: /* sreg <= treg <==> treg >= sreg <==> not (treg < sreg) */
2090 macro_build (&icnt
, NULL
, s
, "d,v,t", dreg
, treg
, sreg
);
2091 macro_build (&icnt
, &expr1
, "xori", "t,r,i", dreg
, dreg
);
2094 case M_SLE_I
: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */
2100 load_register (&icnt
, ip
, AT
, &imm_expr
);
2101 macro_build (&icnt
, NULL
, s
, "d,v,t", dreg
, AT
, sreg
);
2102 macro_build (&icnt
, &expr1
, "xori", "t,r,i", dreg
, dreg
);
2106 if (imm_expr
.X_add_number
< 32768 && imm_expr
.X_add_number
> -32769)
2108 macro_build (&icnt
, &imm_expr
, "slti", "t,r,j", dreg
, sreg
);
2111 load_register (&icnt
, ip
, AT
, &imm_expr
);
2112 macro_build (&icnt
, NULL
, "slt", "d,v,t", dreg
, sreg
, AT
);
2116 if (imm_expr
.X_add_number
< 32768 && imm_expr
.X_add_number
> -32769)
2118 macro_build (&icnt
, &imm_expr
, "sltiu", "t,r,j", dreg
, sreg
);
2121 load_register (&icnt
, ip
, AT
, &imm_expr
);
2122 macro_build (&icnt
, NULL
, "sltu", "d,v,t", dreg
, sreg
, AT
);
2127 macro_build (&icnt
, NULL
, "sltu", "d,v,t", dreg
, 0, treg
);
2129 macro_build (&icnt
, NULL
, "sltu", "d,v,t", dreg
, 0, sreg
);
2132 macro_build (&icnt
, NULL
, "xor", "d,v,t", dreg
, sreg
, treg
);
2133 macro_build (&icnt
, NULL
, "sltu", "d,v,t", dreg
, 0, dreg
);
2138 if (imm_expr
.X_add_number
== 0)
2140 macro_build (&icnt
, NULL
, "sltu", "d,v,t", dreg
, 0, sreg
);
2145 as_warn ("Instruction %s: result is always true",
2147 macro_build (&icnt
, &expr1
, "addiu", "t,r,j", dreg
, 0);
2150 switch (imm_expr
.X_add_number
& 0xffff8000)
2154 macro_build (&icnt
, &imm_expr
, "xori", "t,r,i", dreg
, sreg
);
2159 if (imm_expr
.X_add_number
!= -32768)
2161 imm_expr
.X_add_number
= -imm_expr
.X_add_number
;
2162 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", dreg
, sreg
);
2169 macro_build_lui (&icnt
, &imm_expr
, AT
);
2170 if (imm_expr
.X_add_number
& 0xffff)
2171 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", AT
, AT
);
2172 macro_build (&icnt
, NULL
, "xor", "d,v,t", dreg
, sreg
, AT
);
2175 macro_build (&icnt
, NULL
, "sltu", "d,v,t", dreg
, 0, dreg
);
2181 if (imm_expr
.X_add_number
< 32768 && imm_expr
.X_add_number
> -32768)
2183 imm_expr
.X_add_number
= -imm_expr
.X_add_number
;
2184 macro_build (&icnt
, &imm_expr
, "addi", "t,r,j", dreg
, sreg
);
2187 load_register (&icnt
, ip
, AT
, &imm_expr
);
2188 macro_build (&icnt
, NULL
, "sub", "d,v,t", dreg
, sreg
, AT
);
2192 if (imm_expr
.X_add_number
< 32768 && imm_expr
.X_add_number
> -32768)
2194 imm_expr
.X_add_number
= -imm_expr
.X_add_number
;
2195 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", dreg
, sreg
);
2198 load_register (&icnt
, ip
, AT
, &imm_expr
);
2199 macro_build (&icnt
, NULL
, "subu", "d,v,t", dreg
, sreg
, AT
);
2204 sreg
= (ip
->insn_opcode
>> 11) & 0x1f; /* floating reg */
2205 dreg
= (ip
->insn_opcode
>> 06) & 0x1f; /* floating reg */
2208 * Is the double cfc1 instruction a bug in the mips assembler;
2209 * or is there a reason for it?
2211 mips_emit_delays ();
2213 macro_build (&icnt
, NULL
, "cfc1", "t,G", treg
, 31);
2214 macro_build (&icnt
, NULL
, "cfc1", "t,G", treg
, 31);
2215 macro_build (&icnt
, NULL
, "nop", "");
2216 expr1
.X_add_number
= 3;
2217 macro_build (&icnt
, &expr1
, "ori", "t,r,i", AT
, treg
);
2218 expr1
.X_add_number
= 2;
2219 macro_build (&icnt
, &expr1
, "xori", "t,r,i", AT
, AT
);
2220 macro_build (&icnt
, NULL
, "ctc1", "t,G", AT
, 31);
2221 macro_build (&icnt
, NULL
, "nop", "");
2222 macro_build (&icnt
, NULL
,
2223 mask
== M_TRUNCWD
? "cvt.w.d" : "cvt.w.s", "D,S", dreg
, sreg
);
2224 macro_build (&icnt
, NULL
, "ctc1", "t,G", treg
, 31);
2225 macro_build (&icnt
, NULL
, "nop", "");
2235 /* avoid load delay */
2236 offset_expr
.X_add_number
+= 1;
2237 macro_build (&icnt
, &offset_expr
, s
, "t,o(b)", treg
, breg
);
2238 offset_expr
.X_add_number
-= 1;
2239 macro_build (&icnt
, &offset_expr
, "lbu", "t,o(b)", AT
, breg
);
2240 macro_build (&icnt
, NULL
, "sll", "d,w,<", treg
, treg
, 8);
2241 macro_build (&icnt
, NULL
, "or", "d,v,t", treg
, treg
, AT
);
2245 /* does this work on a big endian machine? */
2246 offset_expr
.X_add_number
+= 3;
2247 macro_build (&icnt
, &offset_expr
, "lwl", "t,o(b)", treg
, breg
);
2248 offset_expr
.X_add_number
-= 3;
2249 macro_build (&icnt
, &offset_expr
, "lwr", "t,o(b)", treg
, breg
);
2255 if (offset_expr
.X_op
== O_constant
)
2256 load_register (&icnt
, ip
, AT
, &offset_expr
);
2257 else if (gp_reference (&offset_expr
))
2258 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", AT
, GP
);
2261 macro_build_lui (&icnt
, &offset_expr
, AT
);
2262 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", AT
, AT
);
2264 if (mask
== M_ULW_A
)
2266 expr1
.X_add_number
= 3;
2267 macro_build (&icnt
, &expr1
, "lwl", "t,o(b)", treg
, AT
);
2268 imm_expr
.X_add_number
= 0;
2269 macro_build (&icnt
, &expr1
, "lwr", "t,o(b)", treg
, AT
);
2273 macro_build (&icnt
, &expr1
,
2274 mask
== M_ULH_A
? "lb" : "lbu", "t,o(b)", treg
, AT
);
2275 imm_expr
.X_add_number
= 0;
2276 macro_build (&icnt
, &expr1
, "lbu", "t,o(b)", AT
, AT
);
2277 macro_build (&icnt
, NULL
, "sll", "d,w,<", treg
, treg
, 8);
2278 macro_build (&icnt
, NULL
, "or", "d,v,t", treg
, treg
, AT
);
2283 macro_build (&icnt
, &offset_expr
, "sb", "t,o(b)", treg
, breg
);
2284 macro_build (&icnt
, NULL
, "srl", "d,w,<", AT
, treg
, 8);
2285 offset_expr
.X_add_number
+= 1;
2286 macro_build (&icnt
, &offset_expr
, "sb", "t,o(b)", AT
, breg
);
2290 offset_expr
.X_add_number
+= 3;
2291 macro_build (&icnt
, &offset_expr
, "swl", "t,o(b)", treg
, breg
);
2292 offset_expr
.X_add_number
-= 3;
2293 macro_build (&icnt
, &offset_expr
, "swr", "t,o(b)", treg
, breg
);
2298 if (offset_expr
.X_op
== O_constant
)
2299 load_register (&icnt
, ip
, AT
, &offset_expr
);
2300 else if (gp_reference (&offset_expr
))
2301 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", AT
, GP
);
2304 macro_build_lui (&icnt
, &offset_expr
, AT
);
2305 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", AT
, AT
);
2307 if (mask
== M_USW_A
)
2309 expr1
.X_add_number
= 3;
2310 macro_build (&icnt
, &expr1
, "swl", "t,o(b)", treg
, AT
);
2311 expr1
.X_add_number
= 0;
2312 macro_build (&icnt
, &expr1
, "swr", "t,o(b)", treg
, AT
);
2316 expr1
.X_add_number
= 0;
2317 macro_build (&icnt
, &expr1
, "sb", "t,o(b)", treg
, AT
);
2318 macro_build (&icnt
, NULL
, "srl", "d,w,<", treg
, treg
, 8);
2319 expr1
.X_add_number
= 1;
2320 macro_build (&icnt
, &expr1
, "sb", "t,o(b)", treg
, AT
);
2321 expr1
.X_add_number
= 0;
2322 macro_build (&icnt
, &expr1
, "lbu", "t,o(b)", AT
, AT
);
2323 macro_build (&icnt
, NULL
, "sll", "d,w,<", treg
, treg
, 8);
2324 macro_build (&icnt
, NULL
, "or", "d,v,t", treg
, treg
, AT
);
2329 as_bad ("Macro %s not implemented yet", ip
->insn_mo
->name
);
2332 as_warn ("Macro used $at after \".set noat\"");
2337 This routine assembles an instruction into its binary format. As a side
2338 effect it sets one of the global variables imm_reloc or offset_reloc to the
2339 type of relocation to do if one of the operands is an address expression.
2344 struct mips_cl_insn
*ip
;
2349 struct mips_opcode
*insn
;
2352 unsigned int lastregno
= 0;
2357 for (s
= str
; islower (*s
) || (*s
>= '0' && *s
<= '3') || *s
== '.'; ++s
)
2369 as_warn ("Unknown opcode: `%s'", str
);
2372 if ((insn
= (struct mips_opcode
*) hash_find (op_hash
, str
)) == NULL
)
2374 as_warn ("`%s' not in hash table.", str
);
2375 insn_error
= "ERROR: Unrecognized opcode";
2381 assert (strcmp (insn
->name
, str
) == 0);
2383 ip
->insn_opcode
= insn
->match
;
2384 for (args
= insn
->args
;; ++args
)
2390 case '\0': /* end of args */
2403 ip
->insn_opcode
|= lastregno
<< 21;
2408 ip
->insn_opcode
|= lastregno
<< 16;
2412 ip
->insn_opcode
|= lastregno
<< 11;
2418 /* handle optional base register.
2419 Either the base register is omitted or
2420 we must have a left paren. */
2421 /* this is dependent on the next operand specifier
2422 is a 'b' for base register */
2423 assert (args
[1] == 'b');
2427 case ')': /* these must match exactly */
2432 case '<': /* must be at least one digit */
2434 * According to the manual, if the shift amount is greater
2435 * than 31 or less than 0 the the shift amount should be
2436 * mod 32. In reality the mips assembler issues an error.
2437 * We issue a warning and do the mod.
2439 my_getExpression (&imm_expr
, s
);
2440 check_absolute_expr (ip
, &imm_expr
);
2441 if ((unsigned long) imm_expr
.X_add_number
> 31)
2443 as_warn ("Improper shift amount (%d)",
2444 imm_expr
.X_add_number
);
2445 imm_expr
.X_add_number
= imm_expr
.X_add_number
% 32;
2447 ip
->insn_opcode
|= imm_expr
.X_add_number
<< 6;
2448 imm_expr
.X_op
= O_absent
;
2452 case 'c': /* break code */
2453 my_getExpression (&imm_expr
, s
);
2454 check_absolute_expr (ip
, &imm_expr
);
2455 if ((unsigned) imm_expr
.X_add_number
> 1023)
2456 as_warn ("Illegal break code (%d)", imm_expr
.X_add_number
);
2457 ip
->insn_opcode
|= imm_expr
.X_add_number
<< 16;
2458 imm_expr
.X_op
= O_absent
;
2462 case 'B': /* syscall code */
2463 my_getExpression (&imm_expr
, s
);
2464 check_absolute_expr (ip
, &imm_expr
);
2465 if ((unsigned) imm_expr
.X_add_number
> 0xfffff)
2466 as_warn ("Illegal syscall code (%d)", imm_expr
.X_add_number
);
2467 ip
->insn_opcode
|= imm_expr
.X_add_number
<< 6;
2468 imm_expr
.X_op
= O_absent
;
2472 case 'b': /* base register */
2473 case 'd': /* destination register */
2474 case 's': /* source register */
2475 case 't': /* target register */
2476 case 'r': /* both target and source */
2477 case 'v': /* both dest and source */
2478 case 'w': /* both dest and target */
2479 case 'E': /* coprocessor target register */
2480 case 'G': /* coprocessor destination register */
2494 while (isdigit (*s
));
2496 else if (s
[1] == 'f' && s
[2] == 'p')
2501 else if (s
[1] == 's' && s
[2] == 'p')
2506 else if (s
[1] == 'g' && s
[2] == 'p')
2511 else if (s
[1] == 'a' && s
[2] == 't')
2519 as_bad ("Invalid register number (%d)", regno
);
2520 if (regno
== AT
&& !mips_noat
)
2521 as_warn ("Used $at without \".set noat\"");
2527 if (c
== 'r' || c
== 'v' || c
== 'w')
2540 ip
->insn_opcode
|= regno
<< 21;
2544 ip
->insn_opcode
|= regno
<< 11;
2549 ip
->insn_opcode
|= regno
<< 16;
2559 ip
->insn_opcode
|= lastregno
<< 21;
2562 ip
->insn_opcode
|= lastregno
<< 16;
2567 case 'D': /* floating point destination register */
2568 case 'S': /* floating point source register */
2569 case 'T': /* floating point target register */
2573 if (s
[0] == '$' && s
[1] == 'f' && isdigit (s
[2]))
2583 while (isdigit (*s
));
2586 as_bad ("Invalid float register number (%d)", regno
);
2589 !(strcmp (str
, "mtc1") == 0 ||
2590 strcmp (str
, "mfc1") == 0 ||
2591 strcmp (str
, "lwc1") == 0 ||
2592 strcmp (str
, "swc1") == 0))
2593 as_warn ("Float register should be even, was %d",
2601 if (c
== 'V' || c
== 'W')
2611 ip
->insn_opcode
|= regno
<< 6;
2615 ip
->insn_opcode
|= regno
<< 11;
2619 ip
->insn_opcode
|= regno
<< 16;
2627 ip
->insn_opcode
|= lastregno
<< 11;
2630 ip
->insn_opcode
|= lastregno
<< 16;
2636 my_getExpression (&imm_expr
, s
);
2637 check_absolute_expr (ip
, &imm_expr
);
2642 my_getExpression (&offset_expr
, s
);
2643 imm_reloc
= BFD_RELOC_32
;
2648 as_bad ("Floating point constants only implemented for pseudo ops.");
2651 case 'i': /* 16 bit unsigned immediate */
2652 case 'j': /* 16 bit signed immediate */
2653 imm_reloc
= BFD_RELOC_LO16
;
2654 c
= my_getSmallExpression (&imm_expr
, s
);
2659 if (imm_expr
.X_op
== O_constant
)
2660 imm_expr
.X_add_number
=
2661 (imm_expr
.X_add_number
>> 16) & 0xffff;
2663 imm_reloc
= BFD_RELOC_HI16_S
;
2665 imm_reloc
= BFD_RELOC_HI16
;
2669 check_absolute_expr (ip
, &imm_expr
);
2672 if ((unsigned long) imm_expr
.X_add_number
> 65535)
2674 if (insn
+ 1 < &mips_opcodes
[NUMOPCODES
] &&
2675 !strcmp (insn
->name
, insn
[1].name
))
2677 as_bad ("16 bit expression not in range 0..65535");
2682 if (imm_expr
.X_add_number
< -32768 ||
2683 imm_expr
.X_add_number
> 32767)
2685 if (insn
+ 1 < &mips_opcodes
[NUMOPCODES
] &&
2686 !strcmp (insn
->name
, insn
[1].name
))
2688 as_bad ("16 bit expression not in range -32768..32767");
2694 case 'o': /* 16 bit offset */
2695 c
= my_getSmallExpression (&offset_expr
, s
);
2697 * If this value won't fit into a 16 bit offset, then
2698 * go find a macro that will generate the 32 bit offset
2701 if ((offset_expr
.X_add_symbol
2702 && offset_expr
.X_op
!= O_constant
)
2703 || offset_expr
.X_op_symbol
2704 || offset_expr
.X_add_number
> 32767
2705 || offset_expr
.X_add_number
< -32768)
2708 offset_reloc
= BFD_RELOC_LO16
;
2709 if (c
== 'h' || c
== 'H')
2710 offset_expr
.X_add_number
=
2711 (offset_expr
.X_add_number
>> 16) & 0xffff;
2715 case 'p': /* pc relative offset */
2716 offset_reloc
= BFD_RELOC_16_PCREL_S2
;
2717 my_getExpression (&offset_expr
, s
);
2721 case 'u': /* upper 16 bits */
2722 c
= my_getSmallExpression (&imm_expr
, s
);
2723 if ((unsigned long) imm_expr
.X_add_number
> 65535)
2724 as_bad ("lui expression not in range 0..65535");
2725 imm_reloc
= BFD_RELOC_LO16
;
2730 if (imm_expr
.X_op
== O_constant
)
2731 imm_expr
.X_add_number
=
2732 (imm_expr
.X_add_number
>> 16) & 0xffff;
2734 imm_reloc
= BFD_RELOC_HI16_S
;
2736 imm_reloc
= BFD_RELOC_HI16
;
2742 case 'a': /* 26 bit address */
2743 my_getExpression (&offset_expr
, s
);
2745 offset_reloc
= BFD_RELOC_MIPS_JMP
;
2749 fprintf (stderr
, "bad char = '%c'\n", *args
);
2754 /* Args don't match. */
2755 if (insn
+ 1 < &mips_opcodes
[NUMOPCODES
] &&
2756 !strcmp (insn
->name
, insn
[1].name
))
2762 insn_error
= "ERROR: Illegal operands";
2771 my_getSmallExpression (ep
, str
)
2782 ((str
[1] == 'h' && str
[2] == 'i')
2783 || (str
[1] == 'H' && str
[2] == 'I')
2784 || (str
[1] == 'l' && str
[2] == 'o'))
2796 * A small expression may be followed by a base register.
2797 * Scan to the end of this operand, and then back over a possible
2798 * base register. Then scan the small expression up to that
2799 * point. (Based on code in sparc.c...)
2801 for (sp
= str
; *sp
&& *sp
!= ','; sp
++)
2803 if (sp
- 4 >= str
&& sp
[-1] == RP
)
2805 if (isdigit (sp
[-2]))
2807 for (sp
-= 3; sp
>= str
&& isdigit (*sp
); sp
--)
2809 if (*sp
== '$' && sp
> str
&& sp
[-1] == LP
)
2815 else if (sp
- 5 >= str
2818 && ((sp
[-3] == 'f' && sp
[-2] == 'p')
2819 || (sp
[-3] == 's' && sp
[-2] == 'p')
2820 || (sp
[-3] == 'g' && sp
[-2] == 'p')
2821 || (sp
[-3] == 'a' && sp
[-2] == 't')))
2827 /* no expression means zero offset */
2830 /* %xx(reg) is an error */
2831 ep
->X_op
= O_absent
;
2836 ep
->X_op
= O_absent
;
2839 ep
->X_add_symbol
= NULL
;
2840 ep
->X_op_symbol
= NULL
;
2841 ep
->X_add_number
= 0;
2846 my_getExpression (ep
, str
);
2853 my_getExpression (ep
, str
);
2854 return c
; /* => %hi or %lo encountered */
2858 my_getExpression (ep
, str
)
2864 save_in
= input_line_pointer
;
2865 input_line_pointer
= str
;
2867 expr_end
= input_line_pointer
;
2868 input_line_pointer
= save_in
;
2871 /* Turn a string in input_line_pointer into a floating point constant
2872 of type type, and store the appropriate bytes in *litP. The number
2873 of LITTLENUMS emitted is stored in *sizeP . An error message is
2874 returned, or NULL on OK. */
2877 md_atof (type
, litP
, sizeP
)
2883 LITTLENUM_TYPE words
[4];
2899 return "bad call to md_atof";
2902 t
= atof_ieee (input_line_pointer
, type
, words
);
2904 input_line_pointer
= t
;
2908 if (byte_order
== LITTLE_ENDIAN
)
2910 for (i
= prec
- 1; i
>= 0; i
--)
2912 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
2918 for (i
= 0; i
< prec
; i
++)
2920 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
2929 md_number_to_chars (buf
, val
, n
)
2981 md_parse_option (argP
, cntP
, vecP
)
2986 /* Accept -nocpp but ignore it. */
2987 if (!strcmp (*argP
, "nocpp"))
2993 if (strcmp (*argP
, "EL") == 0
2994 || strcmp (*argP
, "EB") == 0)
2996 /* FIXME: This breaks -L -EL. */
3004 mips_optimize
= (*argP
)[1] != '0';
3011 if ((*argP
)[1] != '\0')
3012 g_switch_value
= atoi (*argP
+ 1);
3015 **vecP
= (char *) NULL
;
3018 g_switch_value
= atoi (**vecP
);
3021 as_warn ("Number expected after -G");
3027 return 1; /* pretend you parsed the character */
3031 md_pcrel_from (fixP
)
3034 /* return the address of the delay slot */
3035 return fixP
->fx_size
+ fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
3039 md_apply_fix (fixP
, valueP
)
3046 assert (fixP
->fx_size
== 4);
3049 fixP
->fx_addnumber
= value
; /* Remember value for tc_gen_reloc */
3051 switch (fixP
->fx_r_type
)
3054 case BFD_RELOC_MIPS_JMP
:
3055 case BFD_RELOC_HI16
:
3056 case BFD_RELOC_HI16_S
:
3057 case BFD_RELOC_LO16
:
3058 case BFD_RELOC_MIPS_GPREL
:
3059 /* Nothing needed to do. The value comes from the reloc entry */
3062 case BFD_RELOC_16_PCREL_S2
:
3064 * We need to save the bits in the instruction since fixup_segment()
3065 * might be deleting the relocation entry (i.e., a branch within
3066 * the current segment).
3069 as_warn ("Branch to odd address (%x)", value
);
3071 if ((value
& ~0xFFFF) && (value
& ~0xFFFF) != (-1 & ~0xFFFF))
3072 as_bad ("Relocation overflow");
3074 /* update old instruction data */
3075 buf
= (unsigned char *) (fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
);
3079 insn
= (buf
[3] << 24) | (buf
[2] << 16) | (buf
[1] << 8) | buf
[0];
3083 insn
= (buf
[0] << 24) | (buf
[1] << 16) | (buf
[2] << 8) | buf
[3];
3090 insn
|= value
& 0xFFFF;
3091 md_number_to_chars ((char *) buf
, insn
, 4);
3105 const struct mips_opcode
*p
;
3106 int treg
, sreg
, dreg
, shamt
;
3111 for (i
= 0; i
< NUMOPCODES
; ++i
)
3113 p
= &mips_opcodes
[i
];
3114 if (((oc
& p
->mask
) == p
->match
) && (p
->pinfo
!= INSN_MACRO
))
3116 printf ("%08lx %s\t", oc
, p
->name
);
3117 treg
= (oc
>> 16) & 0x1f;
3118 sreg
= (oc
>> 21) & 0x1f;
3119 dreg
= (oc
>> 11) & 0x1f;
3120 shamt
= (oc
>> 6) & 0x1f;
3122 for (args
= p
->args
;; ++args
)
3133 printf ("%c", *args
);
3137 assert (treg
== sreg
);
3138 printf ("$%d,$%d", treg
, sreg
);
3143 printf ("$%d", dreg
);
3148 printf ("$%d", treg
);
3153 printf ("$%d", sreg
);
3157 printf ("0x%08lx", oc
& 0x1ffffff);
3168 printf ("$%d", shamt
);
3179 printf ("%08lx UNDEFINED\n", oc
);
3190 name
= input_line_pointer
;
3191 c
= get_symbol_end ();
3192 p
= (symbolS
*) symbol_find_or_make (name
);
3193 *input_line_pointer
= c
;
3197 /* Align the current frag to a given power of two. The MIPS assembler
3198 also automatically adjusts any preceding label. */
3201 mips_align (to
, fill
)
3205 mips_emit_delays ();
3206 frag_align (to
, fill
);
3207 record_alignment (now_seg
, to
);
3208 if (insn_label
!= NULL
)
3210 assert (S_GET_SEGMENT (insn_label
) == now_seg
);
3211 insn_label
->sy_frag
= frag_now
;
3212 S_SET_VALUE (insn_label
, frag_now_fix ());
3216 /* Align to a given power of two. .align 0 turns off the automatic
3217 alignment used by the data creating pseudo-ops. */
3224 register long temp_fill
;
3225 long max_alignment
= 15;
3229 o Note that the assembler pulls down any immediately preceeding label
3230 to the aligned address.
3231 o It's not documented but auto alignment is reinstated by
3232 a .align pseudo instruction.
3233 o Note also that after auto alignment is turned off the mips assembler
3234 issues an error on attempt to assemble an improperly aligned data item.
3239 temp
= get_absolute_expression ();
3240 if (temp
> max_alignment
)
3241 as_bad ("Alignment too large: %d. assumed.", temp
= max_alignment
);
3244 as_warn ("Alignment negative: 0 assumed.");
3247 if (*input_line_pointer
== ',')
3249 input_line_pointer
++;
3250 temp_fill
= get_absolute_expression ();
3257 mips_align (temp
, (int) temp_fill
);
3264 demand_empty_rest_of_line ();
3267 /* Handle .ascii and .asciiz. This just calls stringer and forgets
3268 that there was a previous instruction. */
3271 s_stringer (append_zero
)
3274 mips_emit_delays ();
3275 stringer (append_zero
);
3284 mips_emit_delays ();
3293 subseg_new (".rdata", (subsegT
) get_absolute_expression ());
3294 demand_empty_rest_of_line ();
3303 #ifdef BFD_ASSEMBLER
3304 subseg_set (bss_section
, (subsegT
) get_absolute_expression ());
3306 subseg_new (bss_section
, (subsegT
) get_absolute_expression ());
3308 demand_empty_rest_of_line ();
3312 subseg_new (".sdata", (subsegT
) get_absolute_expression ());
3313 demand_empty_rest_of_line ();
3316 as_bad ("Global pointers not supported; recompile -G 0");
3317 demand_empty_rest_of_line ();
3328 mips_emit_delays ();
3329 if (log_size
> 0 && auto_align
)
3330 mips_align (log_size
, 0);
3331 cons (1 << log_size
);
3338 as_fatal ("Encountered `.err', aborting assembly");
3348 symbolP
= get_symbol ();
3349 if (*input_line_pointer
== ',')
3350 input_line_pointer
++;
3351 size
= get_absolute_expression ();
3352 S_SET_VALUE (symbolP
, size
);
3353 S_SET_EXTERNAL (symbolP
);
3356 /* ECOFF needs to distinguish a .comm symbol from a .extern symbol,
3357 so we use an additional ECOFF specific field. */
3358 symbolP
->ecoff_undefined
= 1;
3366 mips_emit_delays ();
3381 if (strcmp (input_line_pointer
, "O1") != 0
3382 && strcmp (input_line_pointer
, "O2") != 0)
3383 as_warn ("Unrecognized option");
3384 demand_empty_rest_of_line ();
3391 char *name
= input_line_pointer
, ch
;
3393 while (!is_end_of_line
[(unsigned char) *input_line_pointer
])
3394 input_line_pointer
++;
3395 ch
= *input_line_pointer
;
3396 *input_line_pointer
= '\0';
3398 if (strcmp (name
, "reorder") == 0)
3402 prev_insn_unreordered
= 1;
3403 prev_prev_insn_unreordered
= 1;
3407 else if (strcmp (name
, "noreorder") == 0)
3409 mips_emit_delays ();
3412 else if (strcmp (name
, "at") == 0)
3416 else if (strcmp (name
, "noat") == 0)
3420 else if (strcmp (name
, "macro") == 0)
3422 mips_warn_about_macros
= 0;
3424 else if (strcmp (name
, "nomacro") == 0)
3426 if (mips_noreorder
== 0)
3427 as_bad ("`noreorder' must be set before `nomacro'");
3428 mips_warn_about_macros
= 1;
3430 else if (strcmp (name
, "move") == 0 || strcmp (name
, "novolatile") == 0)
3434 else if (strcmp (name
, "nomove") == 0 || strcmp (name
, "volatile") == 0)
3438 else if (strcmp (name
, "bopt") == 0)
3442 else if (strcmp (name
, "nobopt") == 0)
3448 as_warn ("Tried to set unrecognized symbol: %s\n", name
);
3450 *input_line_pointer
= ch
;
3451 demand_empty_rest_of_line ();
3454 /* The same as the usual .space directive, except that we have to
3455 forget about any previous instruction. */
3458 s_mips_space (param
)
3461 mips_emit_delays ();
3471 if (*input_line_pointer
++ != '$')
3473 as_warn ("expected `$'");
3476 if (isdigit ((unsigned char) *input_line_pointer
))
3478 reg
= get_absolute_expression ();
3479 if (reg
< 0 || reg
>= 32)
3481 as_warn ("Bad register number");
3487 if (strncmp (input_line_pointer
, "fp", 2) == 0)
3489 else if (strncmp (input_line_pointer
, "sp", 2) == 0)
3491 else if (strncmp (input_line_pointer
, "gp", 2) == 0)
3493 else if (strncmp (input_line_pointer
, "at", 2) == 0)
3497 as_warn ("Unrecognized register name");
3500 input_line_pointer
+= 2;
3506 * Translate internal representation of relocation info to BFD target format.
3509 tc_gen_reloc (section
, fixp
)
3515 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
3516 assert (reloc
!= 0);
3518 reloc
->sym_ptr_ptr
= &fixp
->fx_addsy
->bsym
;
3519 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
3520 if (fixp
->fx_pcrel
== 0)
3521 reloc
->addend
= fixp
->fx_addnumber
;
3526 reloc
->addend
= -reloc
->address
;
3528 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
3529 assert (reloc
->howto
!= 0);
3534 /* should never be called */
3536 md_section_align (seg
, addr
)
3540 int align
= bfd_get_section_alignment (stdoutput
, seg
);
3542 return ((addr
+ (1 << align
) - 1) & (-1 << align
));
3546 md_estimate_size_before_relax (fragP
, segtype
)
3550 as_fatal ("md_estimate_size_before_relax");
3552 } /* md_estimate_size_before_relax() */
3554 /* This function is called whenever a label is defined. It is used
3555 when handling branch delays; if a branch has a label, we assume we
3559 mips_define_label (sym
)
3567 /* These functions should really be defined by the object file format,
3568 since they are related to debugging information. However, this
3569 code has to work for the a.out format, which does not define them,
3570 so we provide simple versions here. These don't actually generate
3571 any debugging information, but they do simple checking and someday
3572 somebody may make them useful. */
3576 struct loc
*loc_next
;
3577 unsigned long loc_fileno
;
3578 unsigned long loc_lineno
;
3579 unsigned long loc_offset
;
3580 unsigned short loc_delta
;
3581 unsigned short loc_count
;
3590 struct proc
*proc_next
;
3591 struct symbol
*proc_isym
;
3592 struct symbol
*proc_end
;
3593 unsigned long proc_reg_mask
;
3594 unsigned long proc_reg_offset
;
3595 unsigned long proc_fpreg_mask
;
3596 unsigned long proc_fpreg_offset
;
3597 unsigned long proc_frameoffset
;
3598 unsigned long proc_framereg
;
3599 unsigned long proc_pcreg
;
3601 struct file
*proc_file
;
3608 struct file
*file_next
;
3609 unsigned long file_fileno
;
3610 struct symbol
*file_symbol
;
3611 struct symbol
*file_end
;
3612 struct proc
*file_proc
;
3617 static struct obstack proc_frags
;
3618 static procS
*proc_lastP
;
3619 static procS
*proc_rootP
;
3620 static int numprocs
;
3625 obstack_begin (&proc_frags
, 0x2000);
3631 /* check for premature end, nesting errors, etc */
3632 if (proc_lastP
&& proc_lastP
->proc_end
== NULL
)
3633 as_warn ("missing `.end' at end of assembly");
3636 extern char hex_value
[];
3644 if (*input_line_pointer
== '-')
3646 ++input_line_pointer
;
3649 if (!isdigit (*input_line_pointer
))
3650 as_bad ("Expected simple number.");
3651 if (input_line_pointer
[0] == '0')
3653 if (input_line_pointer
[1] == 'x')
3655 input_line_pointer
+= 2;
3656 while (isxdigit (*input_line_pointer
))
3659 val
|= hex_value
[(int) *input_line_pointer
++];
3661 return negative
? -val
: val
;
3665 ++input_line_pointer
;
3666 while (isdigit (*input_line_pointer
))
3669 val
|= *input_line_pointer
++ - '0';
3671 return negative
? -val
: val
;
3674 if (!isdigit (*input_line_pointer
))
3676 printf (" *input_line_pointer == '%c' 0x%02x\n",
3677 *input_line_pointer
, *input_line_pointer
);
3678 as_warn ("Invalid number");
3681 while (isdigit (*input_line_pointer
))
3684 val
+= *input_line_pointer
++ - '0';
3686 return negative
? -val
: val
;
3689 /* The .file directive; just like the usual .file directive, but there
3690 is an initial number which is the ECOFF file index. */
3698 line
= get_number ();
3703 /* The .end directive. */
3711 if (!is_end_of_line
[(unsigned char) *input_line_pointer
])
3714 demand_empty_rest_of_line ();
3718 if (now_seg
!= text_section
)
3719 as_warn (".end not in text section");
3722 as_warn (".end and no .ent seen yet.");
3728 assert (S_GET_NAME (p
));
3729 if (strcmp (S_GET_NAME (p
), S_GET_NAME (proc_lastP
->proc_isym
)))
3730 as_warn (".end symbol does not match .ent symbol.");
3733 proc_lastP
->proc_end
= (symbolS
*) 1;
3736 /* The .aent and .ent directives. */
3746 symbolP
= get_symbol ();
3747 if (*input_line_pointer
== ',')
3748 input_line_pointer
++;
3749 if (isdigit (*input_line_pointer
) || *input_line_pointer
== '-')
3750 number
= get_number ();
3751 if (now_seg
!= text_section
)
3752 as_warn (".ent or .aent not in text section.");
3754 if (!aent
&& proc_lastP
&& proc_lastP
->proc_end
== NULL
)
3755 as_warn ("missing `.end'");
3759 procP
= (procS
*) obstack_alloc (&proc_frags
, sizeof (*procP
));
3760 procP
->proc_isym
= symbolP
;
3761 procP
->proc_reg_mask
= 0;
3762 procP
->proc_reg_offset
= 0;
3763 procP
->proc_fpreg_mask
= 0;
3764 procP
->proc_fpreg_offset
= 0;
3765 procP
->proc_frameoffset
= 0;
3766 procP
->proc_framereg
= 0;
3767 procP
->proc_pcreg
= 0;
3768 procP
->proc_end
= NULL
;
3769 procP
->proc_next
= NULL
;
3771 proc_lastP
->proc_next
= procP
;
3777 demand_empty_rest_of_line ();
3780 /* The .frame directive. */
3793 frame_reg
= tc_get_register ();
3794 if (*input_line_pointer
== ',')
3795 input_line_pointer
++;
3796 frame_off
= get_absolute_expression ();
3797 if (*input_line_pointer
== ',')
3798 input_line_pointer
++;
3799 pcreg
= tc_get_register ();
3802 assert (proc_rootP
);
3803 proc_rootP
->proc_framereg
= frame_reg
;
3804 proc_rootP
->proc_frameoffset
= frame_off
;
3805 proc_rootP
->proc_pcreg
= pcreg
;
3806 /* bob macho .frame */
3808 /* We don't have to write out a frame stab for unoptimized code. */
3809 if (!(frame_reg
== 30 && frame_off
== 0))
3812 as_warn ("No .ent for .frame to use.");
3813 (void) sprintf (str
, "R%d;%d", frame_reg
, frame_off
);
3814 symP
= symbol_new (str
, N_VFP
, 0, frag_now
);
3815 S_SET_TYPE (symP
, N_RMASK
);
3816 S_SET_OTHER (symP
, 0);
3817 S_SET_DESC (symP
, 0);
3818 symP
->sy_forward
= proc_lastP
->proc_isym
;
3819 /* bob perhaps I should have used pseudo set */
3821 demand_empty_rest_of_line ();
3825 /* The .fmask and .mask directives. */
3832 char str
[100], *strP
;
3838 mask
= get_number ();
3839 if (*input_line_pointer
== ',')
3840 input_line_pointer
++;
3841 off
= get_absolute_expression ();
3843 /* bob only for coff */
3844 assert (proc_rootP
);
3845 if (reg_type
== 'F')
3847 proc_rootP
->proc_fpreg_mask
= mask
;
3848 proc_rootP
->proc_fpreg_offset
= off
;
3852 proc_rootP
->proc_reg_mask
= mask
;
3853 proc_rootP
->proc_reg_offset
= off
;
3856 /* bob macho .mask + .fmask */
3858 /* We don't have to write out a mask stab if no saved regs. */
3862 as_warn ("No .ent for .mask to use.");
3864 for (i
= 0; i
< 32; i
++)
3868 sprintf (strP
, "%c%d,", reg_type
, i
);
3869 strP
+= strlen (strP
);
3873 sprintf (strP
, ";%d,", off
);
3874 symP
= symbol_new (str
, N_RMASK
, 0, frag_now
);
3875 S_SET_TYPE (symP
, N_RMASK
);
3876 S_SET_OTHER (symP
, 0);
3877 S_SET_DESC (symP
, 0);
3878 symP
->sy_forward
= proc_lastP
->proc_isym
;
3879 /* bob perhaps I should have used pseudo set */
3884 /* The .loc directive. */
3895 assert (now_seg
== text_section
);
3897 lineno
= get_number ();
3898 addroff
= obstack_next_free (&frags
) - frag_now
->fr_literal
;
3900 symbolP
= symbol_new ("", N_SLINE
, addroff
, frag_now
);
3901 S_SET_TYPE (symbolP
, N_SLINE
);
3902 S_SET_OTHER (symbolP
, 0);
3903 S_SET_DESC (symbolP
, lineno
);
3904 symbolP
->sy_segment
= now_seg
;
3908 #endif /* ! defined (OBJ_ECOFF) */