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. The default value of 2 means to remove
106 unneeded NOPs and swap branch instructions when possible. A value
107 of 1 means to not swap branches. A value of 0 means to always
109 static int mips_optimize
= 2;
111 /* The previous instruction. */
112 static struct mips_cl_insn prev_insn
;
114 /* The instruction before prev_insn. */
115 static struct mips_cl_insn prev_prev_insn
;
117 /* If we don't want information for prev_insn or prev_prev_insn, we
118 point the insn_mo field at this dummy integer. */
119 static const struct mips_opcode dummy_opcode
= { 0 };
121 /* Non-zero if prev_insn is valid. */
122 static int prev_insn_valid
;
124 /* The frag for the previous instruction. */
125 static struct frag
*prev_insn_frag
;
127 /* The offset into prev_insn_frag for the previous instruction. */
128 static long prev_insn_where
;
130 /* The reloc for the previous instruction, if any. */
131 static fixS
*prev_insn_fixp
;
133 /* Non-zero if the previous instruction was in a delay slot. */
134 static int prev_insn_is_delay_slot
;
136 /* Non-zero if the previous instruction was in a .set noreorder. */
137 static int prev_insn_unreordered
;
139 /* Non-zero if the previous previous instruction was in a .set
141 static int prev_prev_insn_unreordered
;
143 /* Prototypes for static functions. */
146 #define internalError() \
147 as_fatal ("internal Error, line %d, %s", __LINE__, __FILE__)
149 #define internalError() as_fatal ("MIPS internal Error");
152 static int insn_uses_reg
PARAMS ((struct mips_cl_insn
*ip
,
154 static void append_insn
PARAMS ((struct mips_cl_insn
* ip
,
156 bfd_reloc_code_real_type r
));
157 static void mips_no_prev_insn
PARAMS ((void));
158 static void mips_emit_delays
PARAMS ((void));
159 static int gp_reference
PARAMS ((expressionS
* ep
));
160 static void macro_build
PARAMS ((int *counter
, expressionS
* ep
,
161 const char *name
, const char *fmt
,
163 static void macro_build_lui
PARAMS ((int *counter
, expressionS
* ep
,
165 static void set_at
PARAMS ((int *counter
, int reg
));
166 static void set_at_unsigned
PARAMS ((int *counter
, int reg
));
167 static void check_absolute_expr
PARAMS ((struct mips_cl_insn
* ip
,
168 expressionS
* expr
));
169 static void load_register
PARAMS ((int *counter
,
170 struct mips_cl_insn
* ip
,
171 int reg
, expressionS
* ep
));
172 static void macro
PARAMS ((struct mips_cl_insn
* ip
));
173 static void mips_ip
PARAMS ((char *str
, struct mips_cl_insn
* ip
));
174 static int my_getSmallExpression
PARAMS ((expressionS
* ep
, char *str
));
175 static void my_getExpression
PARAMS ((expressionS
* ep
, char *str
));
176 static symbolS
*get_symbol
PARAMS ((void));
177 static void mips_align
PARAMS ((int to
, int fill
));
178 static void s_align
PARAMS ((int));
179 static void s_stringer
PARAMS ((int));
180 static void s_change_sec
PARAMS ((int));
181 static void s_cons
PARAMS ((int));
182 static void s_err
PARAMS ((int));
183 static void s_extern
PARAMS ((int));
184 static void s_float_cons
PARAMS ((int));
185 static void s_option
PARAMS ((int));
186 static void s_mipsset
PARAMS ((int));
187 static void s_mips_space
PARAMS ((int));
189 static void md_obj_begin
PARAMS ((void));
190 static void md_obj_end
PARAMS ((void));
191 static long get_number
PARAMS ((void));
192 static void s_ent
PARAMS ((int));
193 static void s_mipsend
PARAMS ((int));
194 static void s_file
PARAMS ((int));
195 static void s_frame
PARAMS ((int));
196 static void s_loc
PARAMS ((int));
197 static void s_mask
PARAMS ((char));
202 The following pseudo-ops from the Kane and Heinrich MIPS book
203 should be defined here, but are currently unsupported: .alias,
204 .galive, .gjaldef, .gjrlive, .livereg, .noalias.
206 The following pseudo-ops from the Kane and Heinrich MIPS book are
207 specific to the type of debugging information being generated, and
208 should be defined by the object format: .aent, .begin, .bend,
209 .bgnb, .end, .endb, .ent, .fmask, .frame, .loc, .mask, .verstamp,
212 The following pseudo-ops from the Kane and Heinrich MIPS book are
213 not MIPS CPU specific, but are also not specific to the object file
214 format. This file is probably the best place to define them, but
215 they are not currently supported: .asm0, .endr, .lab, .repeat,
216 .struct, .weakext. */
218 const pseudo_typeS md_pseudo_table
[] =
220 /* MIPS specific pseudo-ops. */
221 {"option", s_option
, 0},
222 {"set", s_mipsset
, 0},
223 {"rdata", s_change_sec
, 'r',},
224 {"sdata", s_change_sec
, 's',},
226 /* Relatively generic pseudo-ops that happen to be used on MIPS
228 {"asciiz", s_stringer
, 1},
229 {"bss", s_change_sec
, 'b'},
233 /* These pseudo-ops are defined in read.c, but must be overridden
234 here for one reason or another. */
235 {"align", s_align
, 0},
236 {"ascii", s_stringer
, 0},
237 {"asciz", s_stringer
, 1},
239 {"data", s_change_sec
, 'd'},
240 {"double", s_float_cons
, 'd'},
241 {"extern", s_extern
, 0},
242 {"float", s_float_cons
, 'f'},
243 {"space", s_mips_space
, 0},
244 {"text", s_change_sec
, 't'},
248 /* These pseudo-ops should be defined by the object file format.
249 However, ECOFF is the only format which currently defines them,
250 so we have versions here for a.out. */
252 {"end", s_mipsend
, 0},
255 {"fmask", s_ignore
, 'F'},
256 {"frame", s_ignore
, 0},
257 {"loc", s_ignore
, 0},
258 {"mask", s_ignore
, 'R'},
259 {"verstamp", s_ignore
, 0},
266 const relax_typeS md_relax_table
[] =
272 static char *expr_end
;
274 static expressionS imm_expr
;
275 static expressionS offset_expr
;
276 static bfd_reloc_code_real_type imm_reloc
;
277 static bfd_reloc_code_real_type offset_reloc
;
280 * This function is called once, at assembler startup time. It should
281 * set up all the tables, etc. that the MD part of the assembler will need.
286 register char *retval
= NULL
;
287 register unsigned int i
= 0;
289 if ((op_hash
= hash_new ()) == NULL
)
291 as_fatal ("Virtual memory exhausted");
293 for (i
= 0; i
< NUMOPCODES
;)
295 const char *name
= mips_opcodes
[i
].name
;
297 retval
= hash_insert (op_hash
, name
, &mips_opcodes
[i
]);
298 if (retval
!= NULL
&& *retval
!= '\0')
300 fprintf (stderr
, "internal error: can't hash `%s': %s\n",
301 mips_opcodes
[i
].name
, retval
);
302 as_fatal ("Broken assembler. No assembly attempted.");
306 if ((mips_opcodes
[i
].match
& mips_opcodes
[i
].mask
) !=
307 mips_opcodes
[i
].match
)
309 fprintf (stderr
, "internal error: bad opcode: `%s' \"%s\"\n",
310 mips_opcodes
[i
].name
, mips_opcodes
[i
].args
);
311 as_fatal ("Broken assembler. No assembly attempted.");
315 while ((i
< NUMOPCODES
) && !strcmp (mips_opcodes
[i
].name
, name
));
318 mips_no_prev_insn ();
337 struct mips_cl_insn insn
;
342 /* set the default alignment for the text section (2**2) */
343 /* This should go in md_begin but text_section isn't initialized then */
344 record_alignment (text_section
, 2);
346 bfd_set_gp_size (stdoutput
, g_switch_value
);
351 imm_expr
.X_op
= O_absent
;
352 offset_expr
.X_op
= O_absent
;
354 mips_ip (str
, &insn
);
357 as_bad ("%s `%s'", insn_error
, str
);
360 if (insn
.insn_mo
->pinfo
== INSN_MACRO
)
366 if (imm_expr
.X_op
!= O_absent
)
367 append_insn (&insn
, &imm_expr
, imm_reloc
);
368 else if (offset_expr
.X_op
!= O_absent
)
369 append_insn (&insn
, &offset_expr
, offset_reloc
);
371 append_insn (&insn
, NULL
, BFD_RELOC_UNUSED
);
375 /* See whether instruction IP reads register REG. If FPR is non-zero,
376 REG is a floating point register. */
379 insn_uses_reg (ip
, reg
, fpr
)
380 struct mips_cl_insn
*ip
;
384 /* Don't report on general register 0, since it never changes. */
385 if (! fpr
&& reg
== 0)
390 /* If we are called with either $f0 or $f1, we must check $f0.
391 This is not optimal, because it will introduce an unnecessary
392 NOP between "lwc1 $f0" and "swc1 $f1". To fix this we would
393 need to distinguish reading both $f0 and $f1 or just one of
394 them. Note that we don't have to check the other way,
395 because there is no instruction that sets both $f0 and $f1
396 and requires a delay. */
397 if ((ip
->insn_mo
->pinfo
& INSN_READ_FPR_S
)
398 && ((ip
->insn_opcode
>> OP_SH_FS
) & OP_MASK_FS
) == (reg
&~ 1))
400 if ((ip
->insn_mo
->pinfo
& INSN_READ_FPR_T
)
401 && ((ip
->insn_opcode
>> OP_SH_FT
) & OP_MASK_FT
) == (reg
&~ 1))
406 if ((ip
->insn_mo
->pinfo
& INSN_READ_GPR_S
)
407 && ((ip
->insn_opcode
>> OP_SH_RS
) & OP_MASK_RS
) == reg
)
409 if ((ip
->insn_mo
->pinfo
& INSN_READ_GPR_T
)
410 && ((ip
->insn_opcode
>> OP_SH_RT
) & OP_MASK_RT
) == reg
)
417 #define ALIGN_ERR "Attempt to assemble instruction onto non word boundary."
418 #define ALIGN_ERR2 "GAS doesn't do implicit alignment; use .align directive."
422 * Output an instruction.
425 append_insn (ip
, address_expr
, reloc_type
)
426 struct mips_cl_insn
*ip
;
427 expressionS
*address_expr
;
428 bfd_reloc_code_real_type reloc_type
;
434 if (! mips_noreorder
)
436 /* If the previous insn required any delay slots, see if we need
437 to insert a NOP or two. There are six kinds of possible
438 hazards, of which an instruction can have at most one type.
440 (2) an unconditional branch delay
441 (3) a conditional branch delay
442 (4) a generic coprocessor delay
443 (5) a coprocessor condition code delay
444 (6) a HI/LO special register delay
446 There are a lot of optimizations we could do that we don't.
447 In particular, we do not, in general, reorder instructions.
448 If you use gcc with optimization, it will reorder
449 instructions and generally do much more optimization then we
450 do here; repeating all that work in the assembler would only
451 benefit hand written assembly code, and does not seem worth
454 /* This is how a NOP is emitted. */
455 #define emit_nop() md_number_to_chars (frag_more (4), 0, 4)
457 /* The previous insn might require a delay slot, depending upon
458 the contents of the current insn. */
459 if (prev_insn
.insn_mo
->pinfo
& INSN_LOAD_DELAY
)
461 /* A load delay. All load delays delay the use of general
462 register rt for one instruction. */
463 know (prev_insn
.insn_mo
->pinfo
& INSN_WRITE_GPR_T
);
464 if (mips_optimize
== 0
465 || insn_uses_reg (ip
,
466 ((prev_insn
.insn_opcode
>> OP_SH_RT
)
471 else if (prev_insn
.insn_mo
->pinfo
& INSN_COPROC_DELAY
)
473 /* A generic coprocessor delay. The previous instruction
474 modified a coprocessor general or control register. If
475 it modified a control register, we need to avoid any
476 coprocessor instruction (this is probably not always
477 required, but it sometimes is). If it modified a general
478 register, we avoid using that register.
480 This case is not handled very well. There is no special
481 knowledge of CP0 handling, and the coprocessors other
482 than the floating point unit are not distinguished at
484 if (prev_insn
.insn_mo
->pinfo
& INSN_WRITE_FPR_T
)
486 if (mips_optimize
== 0
487 || insn_uses_reg (ip
,
488 ((prev_insn
.insn_opcode
>> OP_SH_RT
)
493 else if (prev_insn
.insn_mo
->pinfo
& INSN_WRITE_FPR_D
)
495 if (mips_optimize
== 0
496 || insn_uses_reg (ip
,
497 ((prev_insn
.insn_opcode
>> OP_SH_RD
)
504 /* We don't know exactly what the previous instruction
505 does. If the current instruction uses a coprocessor
506 register, we must insert a NOP. If previous
507 instruction may set the condition codes, and the
508 current instruction uses them, we must insert two
510 if (mips_optimize
== 0
511 || ((prev_insn
.insn_mo
->pinfo
& INSN_WRITE_COND_CODE
)
512 && (ip
->insn_mo
->pinfo
& INSN_READ_COND_CODE
)))
514 else if (ip
->insn_mo
->pinfo
& INSN_COP
)
518 else if (prev_insn
.insn_mo
->pinfo
& INSN_WRITE_COND_CODE
)
520 /* The previous instruction sets the coprocessor condition
521 codes, but does not require a general coprocessor delay
522 (this means it is a floating point comparison
523 instruction). If this instruction uses the condition
524 codes, we need to insert a single NOP. */
525 if (mips_optimize
== 0
526 || ip
->insn_mo
->pinfo
& INSN_READ_COND_CODE
)
529 else if (prev_insn
.insn_mo
->pinfo
& INSN_READ_LO
)
531 /* The previous instruction reads the LO register; if the
532 current instruction writes to the LO register, we must
534 if (mips_optimize
== 0
535 || ip
->insn_mo
->pinfo
& INSN_WRITE_LO
)
538 else if (prev_insn
.insn_mo
->pinfo
& INSN_READ_HI
)
540 /* The previous instruction reads the HI register; if the
541 current instruction writes to the HI register, we must
543 if (mips_optimize
== 0
544 || ip
->insn_mo
->pinfo
& INSN_WRITE_HI
)
548 /* There are two cases which require two intervening
549 instructions: 1) setting the condition codes using a move to
550 coprocessor instruction which requires a general coprocessor
551 delay and then reading the condition codes 2) reading the HI
552 or LO register and then writing to it. If we are not already
553 emitting a NOP instruction, we must check for these cases
554 compared to the instruction previous to the previous
557 && (((prev_prev_insn
.insn_mo
->pinfo
& INSN_COPROC_DELAY
)
558 && (prev_prev_insn
.insn_mo
->pinfo
& INSN_WRITE_COND_CODE
)
559 && (ip
->insn_mo
->pinfo
& INSN_READ_COND_CODE
))
560 || ((prev_prev_insn
.insn_mo
->pinfo
& INSN_READ_LO
)
561 && (ip
->insn_mo
->pinfo
& INSN_WRITE_LO
))
562 || ((prev_prev_insn
.insn_mo
->pinfo
& INSN_READ_HI
)
563 && (ip
->insn_mo
->pinfo
& INSN_WRITE_HI
))))
566 /* Now emit the right number of NOP instructions. */
572 if (insn_label
!= NULL
)
574 assert (S_GET_SEGMENT (insn_label
) == now_seg
);
575 insn_label
->sy_frag
= frag_now
;
576 S_SET_VALUE (insn_label
, frag_now_fix ());
583 /* This is testing the address of the frag, not the alignment of
584 the instruction in the current section. */
592 if (address_expr
!= NULL
)
594 if (address_expr
->X_op
== O_constant
)
599 ip
->insn_opcode
|= address_expr
->X_add_number
;
603 ip
->insn_opcode
|= address_expr
->X_add_number
& 0xffff;
606 case BFD_RELOC_MIPS_JMP
:
607 case BFD_RELOC_16_PCREL_S2
:
616 assert (reloc_type
!= BFD_RELOC_UNUSED
);
618 fixp
= fix_new_exp (frag_now
, f
- frag_now
->fr_literal
, 4,
620 reloc_type
== BFD_RELOC_16_PCREL_S2
,
625 md_number_to_chars (f
, ip
->insn_opcode
, 4);
627 if (! mips_noreorder
)
629 /* Filling the branch delay slot is more complex. We try to
630 switch the branch with the previous instruction, which we can
631 do if the previous instruction does not set up a condition
632 that the branch tests and if the branch is not itself the
633 target of any branch. */
634 if ((ip
->insn_mo
->pinfo
& INSN_UNCOND_BRANCH_DELAY
)
635 || (ip
->insn_mo
->pinfo
& INSN_COND_BRANCH_DELAY
))
637 if (mips_optimize
< 2
638 /* If we had to emit any NOP instructions, then we
639 already know we can not swap. */
641 /* If we don't even know the previous insn, we can not
644 /* If the previous insn is already in a branch delay
645 slot, then we can not swap. */
646 || prev_insn_is_delay_slot
647 /* If the previous previous insn was in a .set
648 noreorder, we can't swap. Actually, the MIPS
649 assembler will swap in this situation. However, gcc
650 configured -with-gnu-as will generate code like
656 in which we can not swap the bne and INSN. If gcc is
657 not configured -with-gnu-as, it does not output the
658 .set pseudo-ops. We don't have to check
659 prev_insn_unreordered, because prev_insn_valid will
660 be 0 in that case. We don't want to use
661 prev_prev_insn_valid, because we do want to be able
662 to swap at the start of a function. */
663 || prev_prev_insn_unreordered
664 /* If the branch is itself the target of a branch, we
665 can not swap. We cheat on this; all we check for is
666 whether there is a label on this instruction. If
667 there are any branches to anything other than a
668 label, users must use .set noreorder. */
669 || insn_label
!= NULL
670 /* If the branch reads the condition codes, we don't
671 even try to swap, because in the sequence
676 we can not swap, and I don't feel like handling that
678 || (ip
->insn_mo
->pinfo
& INSN_READ_COND_CODE
)
679 /* We can not swap with an instruction that requires a
680 delay slot, becase the target of the branch might
681 interfere with that instruction. */
682 || (prev_insn
.insn_mo
->pinfo
685 | INSN_WRITE_COND_CODE
688 /* We can not swap with a branch instruction. */
689 || (prev_insn
.insn_mo
->pinfo
690 & (INSN_UNCOND_BRANCH_DELAY
| INSN_COND_BRANCH_DELAY
))
691 /* If the branch reads a register that the previous
692 instruction sets, we can not swap. */
693 || ((prev_insn
.insn_mo
->pinfo
& INSN_WRITE_GPR_T
)
694 && insn_uses_reg (ip
,
695 ((prev_insn
.insn_opcode
>> OP_SH_RT
)
698 || ((prev_insn
.insn_mo
->pinfo
& INSN_WRITE_GPR_D
)
699 && insn_uses_reg (ip
,
700 ((prev_insn
.insn_opcode
>> OP_SH_RD
)
703 /* If the branch writes a register that the previous
704 instruction reads, we can not swap (we know that
705 branches only write to RD or to $31). */
706 || ((ip
->insn_mo
->pinfo
& INSN_WRITE_GPR_D
)
707 && insn_uses_reg (&prev_insn
,
708 ((ip
->insn_opcode
>> OP_SH_RD
)
711 || ((ip
->insn_mo
->pinfo
& INSN_WRITE_GPR_31
)
712 && insn_uses_reg (&prev_insn
, 31, 0))
713 /* If the previous previous instruction has a load
714 delay, and sets a register that the branch reads, we
716 || ((prev_prev_insn
.insn_mo
->pinfo
& INSN_LOAD_DELAY
)
717 && insn_uses_reg (ip
,
718 ((prev_prev_insn
.insn_opcode
>> OP_SH_RT
)
722 /* We could do even better for unconditional branches to
723 portions of this object file; we could pick up the
724 instruction at the destination, put it in the delay
725 slot, and bump the destination address. */
727 /* Update the previous insn information. */
728 prev_prev_insn
= *ip
;
729 prev_insn
.insn_mo
= &dummy_opcode
;
736 /* It looks like we can actually do the swap. */
737 prev_f
= prev_insn_frag
->fr_literal
+ prev_insn_where
;
738 memcpy (temp
, prev_f
, 4);
739 memcpy (prev_f
, f
, 4);
743 prev_insn_fixp
->fx_frag
= frag_now
;
744 prev_insn_fixp
->fx_where
= f
- frag_now
->fr_literal
;
748 fixp
->fx_frag
= prev_insn_frag
;
749 fixp
->fx_where
= prev_insn_where
;
751 /* Update the previous insn information; leave prev_insn
753 prev_prev_insn
= *ip
;
755 prev_insn_is_delay_slot
= 1;
757 /* If that was an unconditional branch, forget the previous
759 if (ip
->insn_mo
->pinfo
& INSN_UNCOND_BRANCH_DELAY
)
761 prev_prev_insn
.insn_mo
= &dummy_opcode
;
762 prev_insn
.insn_mo
= &dummy_opcode
;
767 /* Update the previous insn information. */
769 prev_prev_insn
.insn_mo
= &dummy_opcode
;
771 prev_prev_insn
= prev_insn
;
774 /* Any time we see a branch, we always fill the delay slot
775 immediately; since this insn is not a branch, we know it
776 is not in a delay slot. */
777 prev_insn_is_delay_slot
= 0;
780 prev_prev_insn_unreordered
= prev_insn_unreordered
;
781 prev_insn_unreordered
= 0;
782 prev_insn_frag
= frag_now
;
783 prev_insn_where
= f
- frag_now
->fr_literal
;
784 prev_insn_fixp
= fixp
;
788 /* We just output an insn, so the next one doesn't have a label. */
792 /* This function forgets that there was any previous instruction or
798 prev_insn
.insn_mo
= &dummy_opcode
;
799 prev_prev_insn
.insn_mo
= &dummy_opcode
;
801 prev_insn_is_delay_slot
= 0;
802 prev_insn_unreordered
= 0;
803 prev_prev_insn_unreordered
= 0;
807 /* This function must be called whenever we turn on noreorder or emit
808 something other than instructions. It inserts any NOPS which might
809 be needed by the previous instruction, and clears the information
810 kept for the previous instructions. */
815 if (! mips_noreorder
)
820 if (prev_insn
.insn_mo
->pinfo
& ANY_DELAY
)
823 if ((prev_insn
.insn_mo
->pinfo
& INSN_WRITE_COND_CODE
)
824 || (prev_insn
.insn_mo
->pinfo
& INSN_READ_HI
)
825 || (prev_insn
.insn_mo
->pinfo
& INSN_READ_LO
))
828 else if ((prev_prev_insn
.insn_mo
->pinfo
& INSN_WRITE_COND_CODE
)
829 || (prev_prev_insn
.insn_mo
->pinfo
& INSN_READ_HI
)
830 || (prev_prev_insn
.insn_mo
->pinfo
& INSN_READ_LO
))
835 if (insn_label
!= NULL
)
837 assert (S_GET_SEGMENT (insn_label
) == now_seg
);
838 insn_label
->sy_frag
= frag_now
;
839 S_SET_VALUE (insn_label
, frag_now_fix ());
842 mips_no_prev_insn ();
846 /* Return 1 if an expression can be accessed via the GP register. */
857 sym
= ep
->X_add_symbol
;
858 if (sym
== (symbolS
*) NULL
859 || ep
->X_op_symbol
!= (symbolS
*) NULL
)
862 /* Certain symbols can not be referenced off the GP, although it
863 appears as though they can. */
864 symname
= S_GET_NAME (sym
);
865 if (symname
!= (const char *) NULL
866 && (strcmp (symname
, "eprol") == 0
867 || strcmp (symname
, "etext") == 0
868 || strcmp (symname
, "_gp") == 0
869 || strcmp (symname
, "edata") == 0
870 || strcmp (symname
, "_fbss") == 0
871 || strcmp (symname
, "_fdata") == 0
872 || strcmp (symname
, "_ftext") == 0
873 || strcmp (symname
, "end") == 0))
875 if (! S_IS_DEFINED (sym
)
876 && S_GET_VALUE (sym
) != 0
877 && S_GET_VALUE (sym
) <= g_switch_value
)
879 segname
= segment_name (S_GET_SEGMENT (ep
->X_add_symbol
));
880 return (strcmp (segname
, ".sdata") == 0
881 || strcmp (segname
, ".sbss") == 0);
882 #else /* ! defined (OBJ_ECOFF) */
883 /* The GP register is only used for ECOFF. */
885 #endif /* ! defined (OBJ_ECOFF) */
888 /* Build an instruction created by a macro expansion. This is passed
889 a pointer to the count of instructions created so far, an
890 expression, the name of the instruction to build, an operand format
891 string, and corresponding arguments. */
895 macro_build (int *counter
,
900 #else /* ! defined (NO_STDARG) */
902 macro_build (counter
, ep
, name
, fmt
, va_alist
)
908 #endif /* ! defined (NO_STDARG) */
910 struct mips_cl_insn insn
;
911 bfd_reloc_code_real_type r
;
915 va_start (args
, fmt
);
921 * If the macro is about to expand into a second instruction,
922 * print a warning if needed. We need to pass ip as a parameter
923 * to generate a better warning message here...
925 if (mips_warn_about_macros
&& *counter
== 1)
926 as_warn ("Macro instruction expanded into multiple instructions");
928 *counter
+= 1; /* bump instruction counter */
930 r
= BFD_RELOC_UNUSED
;
931 insn
.insn_mo
= (struct mips_opcode
*) hash_find (op_hash
, name
);
932 assert (insn
.insn_mo
);
933 assert (strcmp (name
, insn
.insn_mo
->name
) == 0);
935 while (strcmp (fmt
, insn
.insn_mo
->args
) != 0)
938 assert (insn
.insn_mo
->name
);
939 assert (strcmp (name
, insn
.insn_mo
->name
) == 0);
941 assert (insn
.insn_mo
->pinfo
!= INSN_MACRO
);
942 insn
.insn_opcode
= insn
.insn_mo
->match
;
958 insn
.insn_opcode
|= va_arg (args
, int) << 16;
964 insn
.insn_opcode
|= va_arg (args
, int) << 16;
969 insn
.insn_opcode
|= va_arg (args
, int) << 11;
974 insn
.insn_opcode
|= va_arg (args
, int) << 11;
978 insn
.insn_opcode
|= va_arg (args
, int) << 6;
982 insn
.insn_opcode
|= va_arg (args
, int) << 6;
986 insn
.insn_opcode
|= va_arg (args
, int) << 6;
993 insn
.insn_opcode
|= va_arg (args
, int) << 21;
1003 assert (ep
!= NULL
);
1005 * This allows macro() to pass an immediate expression for
1006 * creating short branches without creating a symbol.
1007 * Note that the expression still might come from the assembly
1008 * input, in which case the value is not checked for range nor
1009 * is a relocation entry generated (yuck).
1011 if (ep
->X_op
== O_constant
)
1013 insn
.insn_opcode
|= (ep
->X_add_number
>> 2) & 0xffff;
1017 r
= BFD_RELOC_16_PCREL_S2
;
1026 assert (r
== BFD_RELOC_UNUSED
? ep
== NULL
: ep
!= NULL
);
1028 /* Use GP relative addressing if possible. */
1029 if (r
== BFD_RELOC_LO16
1030 && gp_reference (ep
))
1031 r
= BFD_RELOC_MIPS_GPREL
;
1033 append_insn (&insn
, ep
, r
);
1037 * Generate a "lui" instruction.
1040 macro_build_lui (counter
, ep
, regnum
)
1045 expressionS high_expr
;
1046 struct mips_cl_insn insn
;
1047 bfd_reloc_code_real_type r
;
1048 CONST
char *name
= "lui";
1049 CONST
char *fmt
= "t,u";
1053 if (high_expr
.X_op
== O_constant
)
1055 /* we can compute the instruction now without a relocation entry */
1056 if (high_expr
.X_add_number
& 0x8000)
1057 high_expr
.X_add_number
+= 0x10000;
1058 high_expr
.X_add_number
=
1059 ((unsigned long) high_expr
.X_add_number
>> 16) & 0xffff;
1060 r
= BFD_RELOC_UNUSED
;
1063 r
= BFD_RELOC_HI16_S
;
1066 * If the macro is about to expand into a second instruction,
1067 * print a warning if needed. We need to pass ip as a parameter
1068 * to generate a better warning message here...
1070 if (mips_warn_about_macros
&& *counter
== 1)
1071 as_warn ("Macro instruction expanded into multiple instructions");
1073 *counter
+= 1; /* bump instruction counter */
1075 insn
.insn_mo
= (struct mips_opcode
*) hash_find (op_hash
, name
);
1076 assert (insn
.insn_mo
);
1077 assert (strcmp (name
, insn
.insn_mo
->name
) == 0);
1078 assert (strcmp (fmt
, insn
.insn_mo
->args
) == 0);
1080 insn
.insn_opcode
= insn
.insn_mo
->match
| (regnum
<< 16);
1081 if (r
== BFD_RELOC_UNUSED
)
1083 insn
.insn_opcode
|= high_expr
.X_add_number
;
1084 append_insn (&insn
, NULL
, r
);
1087 append_insn (&insn
, &high_expr
, r
);
1091 * Generates code to set the $at register to true (one)
1092 * if reg is less than the immediate expression.
1095 set_at (counter
, reg
)
1100 switch (imm_expr
.X_add_number
& 0xffff8000)
1104 macro_build (counter
, &imm_expr
, "slti", "t,r,j", AT
, reg
);
1108 macro_build (counter
, &imm_expr
, "ori", "t,r,i", AT
, 0);
1112 macro_build_lui (counter
, &imm_expr
, AT
);
1113 if (imm_expr
.X_add_number
& 0xffff)
1114 macro_build (counter
, &imm_expr
, "addiu", "t,r,j", AT
, AT
);
1116 macro_build (counter
, NULL
, "slt", "d,v,t", AT
, reg
, AT
);
1119 /* set_at_unsigned()
1120 * Generates code to set the $at register to true (one)
1121 * if reg is less than the immediate expression.
1122 * Unsigned comparison is perfomed.
1125 set_at_unsigned (counter
, reg
)
1130 switch (imm_expr
.X_add_number
& 0xffff8000)
1134 macro_build (counter
, &imm_expr
, "sltiu", "t,r,j", AT
, reg
);
1138 macro_build (counter
, &imm_expr
, "ori", "t,r,i", AT
, 0);
1142 macro_build_lui (counter
, &imm_expr
, AT
);
1143 if (imm_expr
.X_add_number
& 0xffff)
1144 macro_build (counter
, &imm_expr
, "addiu", "t,r,j", AT
, AT
);
1146 macro_build (counter
, NULL
, "sltu", "d,v,t", AT
, reg
, AT
);
1150 check_absolute_expr (ip
, expr
)
1151 struct mips_cl_insn
*ip
;
1155 if (expr
->X_op
!= O_constant
)
1156 as_warn ("Instruction %s requires absolute expression", ip
->insn_mo
->name
);
1160 * This routine generates the least number of instructions neccessary to load
1161 * an absolute expression value into a register.
1164 load_register (counter
, ip
, reg
, ep
)
1166 struct mips_cl_insn
*ip
;
1170 switch (ep
->X_add_number
& 0xffff8000)
1174 macro_build (counter
, ep
, "addiu", "t,r,j", reg
, 0);
1178 macro_build (counter
, ep
, "ori", "t,r,i", reg
, 0);
1182 macro_build_lui (counter
, ep
, reg
);
1183 if (ep
->X_add_number
& 0xffff)
1184 macro_build (counter
, ep
, "addiu", "t,r,j", reg
, reg
);
1191 * This routine implements the seemingly endless macro or synthesized
1192 * instructions and addressing modes in the mips assembly language. Many
1193 * of these macros are simple and are similar to each other. These could
1194 * probably be handled by some kind of table or grammer aproach instead of
1195 * this verbose method. Others are not simple macros but are more like
1196 * optimizing code generation.
1197 * One interesting optimization is when several store macros appear
1198 * consecutivly that would load AT with the upper half of the same address.
1199 * The ensuing load upper instructions are ommited. This implies some kind
1200 * of global optimization. We currently only optimize within a single macro.
1201 * For many of the load and store macros if the address is specified as a
1202 * constant expression in the first 64k of memory (ie ld $2,0x4000c) we
1203 * first load register 'at' with zero and use it as the base register. The
1204 * mips assembler simply uses register $zero. Just one tiny optimization
1209 struct mips_cl_insn
*ip
;
1211 register int treg
, sreg
, dreg
, breg
;
1220 treg
= (ip
->insn_opcode
>> 16) & 0x1f;
1221 dreg
= (ip
->insn_opcode
>> 11) & 0x1f;
1222 sreg
= breg
= (ip
->insn_opcode
>> 21) & 0x1f;
1223 mask
= ip
->insn_mo
->mask
;
1225 expr1
.X_op
= O_constant
;
1226 expr1
.X_op_symbol
= NULL
;
1227 expr1
.X_add_symbol
= NULL
;
1228 expr1
.X_add_number
= 1;
1235 Note: mips algorithm requires the move in the delay slot.
1236 <main>: bgez $a0,0x4001bc <main+12>
1237 <main+4>: move v0,$a0
1238 <main+8>: sub v0,$zero,$a0
1242 mips_emit_delays ();
1245 expr1
.X_add_number
= 8;
1246 macro_build (&icnt
, &expr1
, "bgez", "s,p", sreg
);
1247 macro_build (&icnt
, NULL
, "move", "d,s", dreg
, sreg
, 0);
1248 macro_build (&icnt
, NULL
, mask
== M_ABS
? "sub" : "subu", "d,v,t",
1256 switch (imm_expr
.X_add_number
& 0xffff8000)
1260 macro_build (&icnt
, &imm_expr
,
1261 mask
== M_ADD_I
? "addi" : "addiu", "t,r,j", treg
, sreg
);
1265 macro_build (&icnt
, &imm_expr
, "ori", "t,r,i", AT
, 0);
1269 macro_build_lui (&icnt
, &imm_expr
, AT
);
1270 if (imm_expr
.X_add_number
& 0xffff)
1271 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", AT
, AT
);
1274 macro_build (&icnt
, NULL
,
1275 mask
== M_ADD_I
? "add" : "addu", "d,v,t", treg
, sreg
, AT
);
1282 switch (imm_expr
.X_add_number
& 0xffff8000)
1289 macro_build (&icnt
, &imm_expr
, "andi", "t,r,i", treg
, sreg
);
1292 macro_build (&icnt
, &imm_expr
, "ori", "t,r,i", treg
, sreg
);
1295 macro_build (&icnt
, &imm_expr
, "ori", "t,r,i", treg
, sreg
);
1296 macro_build (&icnt
, &imm_expr
, "nor", "d,v,t", treg
, treg
, 0);
1299 macro_build (&icnt
, &imm_expr
, "xori", "t,r,i", treg
, sreg
);
1306 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", AT
, 0);
1310 macro_build_lui (&icnt
, &imm_expr
, AT
);
1311 if (imm_expr
.X_add_number
& 0xffff)
1312 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", AT
, AT
);
1317 macro_build (&icnt
, NULL
, "and", "d,v,t", treg
, sreg
, AT
);
1320 macro_build (&icnt
, NULL
, "or", "d,v,t", treg
, sreg
, AT
);
1323 macro_build (&icnt
, NULL
, "nor", "d,v,t", treg
, sreg
, AT
);
1326 macro_build (&icnt
, NULL
, "xor", "d,v,t", treg
, sreg
, AT
);
1335 if (imm_expr
.X_add_number
== 0)
1337 macro_build (&icnt
, &offset_expr
, mask
== M_BEQ_I
? "beq" : "bne",
1341 load_register (&icnt
, ip
, AT
, &imm_expr
);
1342 macro_build (&icnt
, &offset_expr
, mask
== M_BEQ_I
? "beq" : "bne",
1349 macro_build (&icnt
, &offset_expr
, "bgez", "s,p", sreg
);
1354 macro_build (&icnt
, &offset_expr
, "blez", "s,p", treg
);
1357 macro_build (&icnt
, NULL
, "slt", "d,v,t", AT
, sreg
, treg
);
1358 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", AT
, 0);
1362 /* check for > max integer */
1363 if (imm_expr
.X_add_number
== 0x7fffffff)
1366 /* result is always false */
1367 as_warn ("Branch %s is always false (nop)", ip
->insn_mo
->name
);
1368 macro_build (&icnt
, NULL
, "nop", "", 0);
1371 imm_expr
.X_add_number
++;
1375 if (imm_expr
.X_add_number
== 0)
1377 macro_build (&icnt
, &offset_expr
, "bgez", "s,p", sreg
);
1380 if (imm_expr
.X_add_number
== 1)
1382 macro_build (&icnt
, &offset_expr
, "bgtz", "s,p", sreg
);
1385 if (imm_expr
.X_add_number
== 0x80000000)
1388 /* result is always true */
1389 as_warn ("Branch %s is always true", ip
->insn_mo
->name
);
1390 macro_build (&icnt
, &offset_expr
, "b", "p");
1393 set_at (&icnt
, sreg
);
1394 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", AT
, 0);
1402 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", 0, treg
);
1405 macro_build (&icnt
, NULL
, "sltu", "d,v,t", AT
, sreg
, treg
);
1406 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", AT
, 0);
1410 if (sreg
== 0 || imm_expr
.X_add_number
== 0xffffffff)
1412 imm_expr
.X_add_number
++;
1416 if (imm_expr
.X_add_number
== 0)
1418 if (imm_expr
.X_add_number
== 1)
1420 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", sreg
, 0);
1423 set_at_unsigned (&icnt
, sreg
);
1424 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", AT
, 0);
1430 macro_build (&icnt
, &offset_expr
, "bgtz", "s,p", sreg
);
1435 macro_build (&icnt
, &offset_expr
, "bltz", "s,p", treg
);
1438 macro_build (&icnt
, NULL
, "slt", "d,v,t", AT
, treg
, sreg
);
1439 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", AT
, 0);
1445 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", sreg
, 0);
1450 macro_build (&icnt
, NULL
, "sltu", "d,v,t", AT
, treg
, sreg
);
1451 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", AT
, 0);
1457 macro_build (&icnt
, &offset_expr
, "blez", "s,p", sreg
);
1462 macro_build (&icnt
, &offset_expr
, "bgez", "s,p", treg
);
1465 macro_build (&icnt
, NULL
, "slt", "d,v,t", AT
, treg
, sreg
);
1466 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", AT
, 0);
1470 if (imm_expr
.X_add_number
== 0x7fffffff)
1472 imm_expr
.X_add_number
++;
1476 if (imm_expr
.X_add_number
== 0)
1478 macro_build (&icnt
, &offset_expr
, "bltz", "s,p", sreg
);
1481 if (imm_expr
.X_add_number
== 1)
1483 macro_build (&icnt
, &offset_expr
, "blez", "s,p", sreg
);
1486 set_at (&icnt
, sreg
);
1487 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", AT
, 0);
1493 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", sreg
, 0);
1498 macro_build (&icnt
, NULL
, "sltu", "d,v,t", AT
, treg
, sreg
);
1499 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", AT
, 0);
1503 if (sreg
== 0 || imm_expr
.X_add_number
== 0xffffffff)
1505 imm_expr
.X_add_number
++;
1509 if (imm_expr
.X_add_number
== 0)
1511 if (imm_expr
.X_add_number
== 1)
1513 macro_build (&icnt
, &offset_expr
, "beq", "s,t,p", sreg
, 0);
1516 set_at_unsigned (&icnt
, sreg
);
1517 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", AT
, 0);
1523 macro_build (&icnt
, &offset_expr
, "bltz", "s,p", sreg
);
1528 macro_build (&icnt
, &offset_expr
, "bgtz", "s,p", treg
);
1531 macro_build (&icnt
, NULL
, "slt", "d,v,t", AT
, sreg
, treg
);
1532 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", AT
, 0);
1540 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", 0, treg
);
1543 macro_build (&icnt
, NULL
, "sltu", "d,v,t", AT
, sreg
, treg
);
1544 macro_build (&icnt
, &offset_expr
, "bne", "s,t,p", AT
, 0);
1551 as_warn ("Divide by zero.");
1552 macro_build (&icnt
, NULL
, "break", "c", 7);
1556 mips_emit_delays ();
1558 macro_build (&icnt
, NULL
, "div", "s,t", sreg
, treg
);
1559 expr1
.X_add_number
= 8;
1560 macro_build (&icnt
, &expr1
, "bne", "s,t,p", treg
, 0);
1561 macro_build (&icnt
, NULL
, "nop", "", 0);
1562 macro_build (&icnt
, NULL
, "break", "c", 7);
1563 expr1
.X_add_number
= -1;
1564 macro_build (&icnt
, &expr1
, "addiu", "t,r,j", AT
, 0);
1565 expr1
.X_add_number
= 16;
1566 macro_build (&icnt
, &expr1
, "bne", "s,t,p", treg
, AT
);
1567 expr1
.X_add_number
= 0x80000000;
1568 macro_build_lui (&icnt
, &expr1
, AT
);
1569 expr1
.X_add_number
= 8;
1570 macro_build (&icnt
, &expr1
, "bne", "s,t,p", sreg
, AT
);
1571 macro_build (&icnt
, NULL
, "nop", "", 0);
1572 macro_build (&icnt
, NULL
, "break", "c", 6);
1574 macro_build (&icnt
, NULL
, mask
== M_DIV_3
? "mflo" : "mfhi", "d", dreg
);
1575 /* with reorder on there will be two implicit nop instructions here. */
1582 if (imm_expr
.X_add_number
== 0)
1584 as_warn ("Divide by zero.");
1585 macro_build (&icnt
, NULL
, "break", "c", 7);
1588 if (imm_expr
.X_add_number
== 1)
1590 if (mask
== (int) M_DIV_3I
|| mask
== (int) M_DIVU_3I
)
1591 macro_build (&icnt
, NULL
, "move", "d,s", dreg
, sreg
);
1593 macro_build (&icnt
, NULL
, "move", "d,s", dreg
, 0);
1597 load_register (&icnt
, ip
, AT
, &imm_expr
);
1598 if (mask
== (int) M_DIV_3I
|| mask
== (int) M_REM_3I
)
1599 macro_build (&icnt
, NULL
, "div", "s,t", sreg
, AT
);
1601 macro_build (&icnt
, NULL
, "divu", "s,t", sreg
, AT
);
1603 if (mask
== (int) M_DIV_3I
|| mask
== (int) M_DIVU_3I
)
1604 macro_build (&icnt
, NULL
, "mflo", "d", dreg
);
1606 macro_build (&icnt
, NULL
, "mfhi", "d", dreg
);
1607 /* two implicit nop's required for mflo or mfhi */
1612 mips_emit_delays ();
1614 macro_build (&icnt
, NULL
, "divu", "s,t", sreg
, treg
);
1615 expr1
.X_add_number
= 8;
1616 macro_build (&icnt
, &expr1
, "bne", "s,t,p", treg
, 0);
1617 macro_build (&icnt
, NULL
, "nop", "", 0);
1618 macro_build (&icnt
, NULL
, "break", "c", 7);
1620 macro_build (&icnt
, NULL
, mask
== M_DIVU_3
? "mflo" : "mfhi", "d", dreg
);
1621 /* with reorder on there will be two implicit nop instructions here. */
1625 if (offset_expr
.X_op
== O_constant
)
1627 load_register (&icnt
, ip
, treg
, &offset_expr
);
1630 if (gp_reference (&offset_expr
))
1631 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", treg
, GP
);
1634 macro_build_lui (&icnt
, &offset_expr
, treg
);
1635 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", treg
, treg
);
1640 tempreg
= (breg
== treg
) ? AT
: treg
;
1641 if (offset_expr
.X_op
== O_constant
)
1642 load_register (&icnt
, ip
, tempreg
, &offset_expr
);
1643 else if (gp_reference (&offset_expr
))
1644 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", tempreg
, GP
);
1647 macro_build_lui (&icnt
, &offset_expr
, tempreg
);
1648 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", tempreg
, tempreg
);
1651 macro_build (&icnt
, NULL
, "addu", "d,v,t", treg
, tempreg
, breg
);
1689 if (breg
== treg
|| mask
== M_LWC1_AB
)
1730 if (mask
== M_LWC1_AB
|| mask
== M_SWC1_AB
)
1734 if (gp_reference (&offset_expr
))
1738 macro_build (&icnt
, &offset_expr
, s
, fmt
, treg
, GP
);
1741 macro_build (&icnt
, (expressionS
*) NULL
, "addu", "d,v,t",
1746 macro_build_lui (&icnt
, &offset_expr
, tempreg
);
1748 macro_build (&icnt
, NULL
, "addu", "d,v,t", tempreg
, tempreg
, breg
);
1750 macro_build (&icnt
, &offset_expr
, s
, fmt
, treg
, tempreg
);
1756 load_register (&icnt
, ip
, treg
, &imm_expr
);
1761 0x400370 <main>: lui $at,%hi(foo)
1762 0x400374 <main+4>: lw $v0,%lo(foo)($at)
1763 0x400378 <main+8>: lw $v1,%lo(foo+4)($at)
1768 /* FIXME: I don't think this is used at present, because the 'F'
1769 format character is not supported. When this is supported,
1770 it should use the GP register. */
1771 macro_build_lui (&icnt
, &offset_expr
, AT
);
1772 macro_build (&icnt
, &offset_expr
, "lw", "t,o(b)", treg
, AT
);
1773 offset_expr
.X_add_number
= 4;
1774 macro_build (&icnt
, &offset_expr
, "lw", "t,o(b)", treg
+ 1, AT
);
1779 0x4003a0 <main>: lwc1 $f0,-32752($gp)
1780 0x4003a4 <main+4>: lwc1 $f1,-32748($gp)
1781 0x4003a8 <main+8>: nop
1783 /* FIXME: This is nonsense. It isn't used anyhow. */
1784 sreg
= (ip
->insn_opcode
>> 11) & 0x1f; /* Fs reg */
1785 macro_build (&icnt
, &offset_expr
, "lwc1", "T,o(b)", treg
, AT
);
1786 offset_expr
.X_add_number
= 4;
1787 macro_build (&icnt
, &offset_expr
, "lwc1", "T,o(b)", treg
+ 1, AT
);
1791 /* Even on a big endian machine $fn comes before $fn+1. We have
1792 to adjust when loading from memory. */
1793 macro_build (&icnt
, &offset_expr
, "lwc1", "T,o(b)",
1794 byte_order
== LITTLE_ENDIAN
? treg
: treg
+ 1,
1796 offset_expr
.X_add_number
+= 4;
1797 macro_build (&icnt
, &offset_expr
, "lwc1", "T,o(b)",
1798 byte_order
== LITTLE_ENDIAN
? treg
+ 1 : treg
,
1804 * The MIPS assembler seems to check for X_add_number not
1805 * being double aligned and generating:
1808 * addiu at,at,%lo(foo+1)
1811 * But, the resulting address is the same after relocation so why
1812 * generate the extra instruction?
1814 if (gp_reference (&offset_expr
))
1820 macro_build (&icnt
, &offset_expr
, "addu", "d,v,t", AT
, breg
, GP
);
1826 macro_build_lui (&icnt
, &offset_expr
, AT
);
1828 macro_build (&icnt
, NULL
, "addu", "d,v,t", AT
, AT
, breg
);
1831 /* Even on a big endian machine $fn comes before $fn+1. We have
1832 to adjust when loading from memory. */
1833 macro_build (&icnt
, &offset_expr
, "lwc1", "T,o(b)",
1834 byte_order
== LITTLE_ENDIAN
? treg
: treg
+ 1,
1836 offset_expr
.X_add_number
+= 4;
1837 macro_build (&icnt
, &offset_expr
, "lwc1", "T,o(b)",
1838 byte_order
== LITTLE_ENDIAN
? treg
+ 1 : treg
,
1850 macro_build (&icnt
, &offset_expr
, s
, "t,o(b)", treg
, breg
);
1851 offset_expr
.X_add_number
= 4;
1852 macro_build (&icnt
, &offset_expr
, s
, "t,o(b)", treg
+ 1, breg
);
1873 if (gp_reference (&offset_expr
))
1881 macro_build (&icnt
, (expressionS
*) NULL
, "addu", "d,v,t",
1886 macro_build_lui (&icnt
, &offset_expr
, tempreg
);
1888 macro_build (&icnt
, NULL
, "addu", "d,v,t", tempreg
, tempreg
, breg
);
1890 macro_build (&icnt
, &offset_expr
, s
, "t,o(b)", treg
, tempreg
);
1891 offset_expr
.X_add_number
+= 4;
1892 macro_build (&icnt
, &offset_expr
, s
, "t,o(b)", treg
+ 1, tempreg
);
1898 macro_build (&icnt
, NULL
, "multu", "s,t", sreg
, treg
);
1899 macro_build (&icnt
, NULL
, "mflo", "d", dreg
);
1900 /* two implicit nop's required for mflo */
1905 * The mips assembler some times generates shifts and adds.
1906 * Im not trying to be that fancy. GCC should do this for us
1909 load_register (&icnt
, ip
, AT
, &imm_expr
);
1910 macro_build (&icnt
, NULL
, "mult", "s,t", sreg
, AT
);
1911 macro_build (&icnt
, NULL
, "mflo", "d", dreg
);
1912 /* two implicit nop's required for mflo */
1916 macro_build (&icnt
, NULL
, "subu", "d,v,t", AT
, 0, treg
);
1917 macro_build (&icnt
, NULL
, "srlv", "d,t,s", AT
, sreg
, AT
);
1918 macro_build (&icnt
, NULL
, "sllv", "d,t,s", dreg
, sreg
, treg
);
1919 macro_build (&icnt
, NULL
, "or", "d,v,t", dreg
, dreg
, AT
);
1923 macro_build (&icnt
, NULL
, "sll", "d,w,<", AT
, sreg
,
1924 imm_expr
.X_add_number
& 0x1f);
1925 macro_build (&icnt
, NULL
, "srl", "d,w,<", dreg
, sreg
,
1926 (0 - imm_expr
.X_add_number
) & 0x1f);
1927 macro_build (&icnt
, NULL
, "or", "d,v,t", dreg
, dreg
, AT
);
1931 macro_build (&icnt
, NULL
, "subu", "d,v,t", AT
, 0, treg
);
1932 macro_build (&icnt
, NULL
, "sllv", "d,t,s", AT
, sreg
, AT
);
1933 macro_build (&icnt
, NULL
, "srlv", "d,t,s", dreg
, sreg
, treg
);
1934 macro_build (&icnt
, NULL
, "or", "d,v,t", dreg
, dreg
, AT
);
1938 macro_build (&icnt
, NULL
, "srl", "d,w,<", AT
, sreg
,
1939 imm_expr
.X_add_number
& 0x1f);
1940 macro_build (&icnt
, NULL
, "sll", "d,w,<", dreg
, sreg
,
1941 (0 - imm_expr
.X_add_number
) & 0x1f);
1942 macro_build (&icnt
, NULL
, "or", "d,v,t", dreg
, dreg
, AT
);
1946 /* Even on a big endian machine $fn comes before $fn+1. We have
1947 to adjust when storing to memory. */
1948 macro_build (&icnt
, &offset_expr
, "swc1", "T,o(b)",
1949 byte_order
== LITTLE_ENDIAN
? treg
: treg
+ 1,
1951 offset_expr
.X_add_number
+= 4;
1952 macro_build (&icnt
, &offset_expr
, "swc1", "T,o(b)",
1953 byte_order
== LITTLE_ENDIAN
? treg
+ 1 : treg
,
1958 if (gp_reference (&offset_expr
))
1964 macro_build (&icnt
, (expressionS
*) NULL
, "addu", "d,v,t",
1971 macro_build_lui (&icnt
, &offset_expr
, AT
);
1973 macro_build (&icnt
, NULL
, "addu", "d,v,t", AT
, AT
, breg
);
1976 /* Even on a big endian machine $fn comes before $fn+1. We have
1977 to adjust when storing to memory. */
1978 macro_build (&icnt
, &offset_expr
, "swc1", "T,o(b)",
1979 byte_order
== LITTLE_ENDIAN
? treg
: treg
+ 1,
1981 offset_expr
.X_add_number
+= 4;
1982 macro_build (&icnt
, &offset_expr
, "swc1", "T,o(b)",
1983 byte_order
== LITTLE_ENDIAN
? treg
+ 1 : treg
,
1991 macro_build (&icnt
, &expr1
, "sltiu", "t,r,j", dreg
, treg
);
1993 macro_build (&icnt
, &expr1
, "sltiu", "t,r,j", dreg
, sreg
);
1996 macro_build (&icnt
, NULL
, "xor", "d,v,t", dreg
, sreg
, treg
);
1997 macro_build (&icnt
, &expr1
, "sltiu", "t,r,j", dreg
, dreg
);
2002 if (imm_expr
.X_add_number
== 0)
2004 macro_build (&icnt
, &expr1
, "sltiu", "t,r,j", dreg
, sreg
);
2009 as_warn ("Instruction %s: result is always false",
2011 macro_build (&icnt
, NULL
, "move", "d,s", dreg
, 0);
2014 switch (imm_expr
.X_add_number
& 0xffff8000)
2018 macro_build (&icnt
, &imm_expr
, "xori", "t,r,i", dreg
, sreg
);
2023 if (imm_expr
.X_add_number
!= -32768)
2025 imm_expr
.X_add_number
= -imm_expr
.X_add_number
;
2026 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", dreg
, sreg
);
2033 macro_build_lui (&icnt
, &imm_expr
, AT
);
2034 if (imm_expr
.X_add_number
& 0xffff)
2035 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", AT
, AT
);
2036 macro_build (&icnt
, NULL
, "xor", "d,v,t", dreg
, sreg
, AT
);
2039 macro_build (&icnt
, &expr1
, "sltiu", "t,r,j", dreg
, dreg
);
2044 case M_SGE
: /* sreg >= treg <==> not (sreg < treg) */
2050 macro_build (&icnt
, NULL
, s
, "d,v,t", dreg
, sreg
, treg
);
2051 macro_build (&icnt
, &expr1
, "xori", "t,r,i", dreg
, dreg
);
2054 case M_SGE_I
: /* sreg >= I <==> not (sreg < I) */
2056 if (imm_expr
.X_add_number
< 32768 && imm_expr
.X_add_number
> -32769)
2058 macro_build (&icnt
, &expr1
,
2059 mask
== M_SGE_I
? "slti" : "sltiu", "t,r,j", dreg
, sreg
);
2064 load_register (&icnt
, ip
, AT
, &imm_expr
);
2065 macro_build (&icnt
, NULL
,
2066 mask
== M_SGE_I
? "slt" : "sltu", "d,v,t", dreg
, sreg
, AT
);
2069 macro_build (&icnt
, &expr1
, "xori", "t,r,i", dreg
, dreg
);
2074 case M_SGT
: /* sreg > treg <==> treg < sreg */
2080 macro_build (&icnt
, NULL
, s
, "d,v,t", dreg
, treg
, sreg
);
2083 case M_SGT_I
: /* sreg > I <==> I < sreg */
2089 load_register (&icnt
, ip
, AT
, &imm_expr
);
2090 macro_build (&icnt
, NULL
, s
, "d,v,t", dreg
, AT
, sreg
);
2093 case M_SLE
: /* sreg <= treg <==> treg >= sreg <==> not (treg < sreg) */
2099 macro_build (&icnt
, NULL
, s
, "d,v,t", dreg
, treg
, sreg
);
2100 macro_build (&icnt
, &expr1
, "xori", "t,r,i", dreg
, dreg
);
2103 case M_SLE_I
: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */
2109 load_register (&icnt
, ip
, AT
, &imm_expr
);
2110 macro_build (&icnt
, NULL
, s
, "d,v,t", dreg
, AT
, sreg
);
2111 macro_build (&icnt
, &expr1
, "xori", "t,r,i", dreg
, dreg
);
2115 if (imm_expr
.X_add_number
< 32768 && imm_expr
.X_add_number
> -32769)
2117 macro_build (&icnt
, &imm_expr
, "slti", "t,r,j", dreg
, sreg
);
2120 load_register (&icnt
, ip
, AT
, &imm_expr
);
2121 macro_build (&icnt
, NULL
, "slt", "d,v,t", dreg
, sreg
, AT
);
2125 if (imm_expr
.X_add_number
< 32768 && imm_expr
.X_add_number
> -32769)
2127 macro_build (&icnt
, &imm_expr
, "sltiu", "t,r,j", dreg
, sreg
);
2130 load_register (&icnt
, ip
, AT
, &imm_expr
);
2131 macro_build (&icnt
, NULL
, "sltu", "d,v,t", dreg
, sreg
, AT
);
2136 macro_build (&icnt
, NULL
, "sltu", "d,v,t", dreg
, 0, treg
);
2138 macro_build (&icnt
, NULL
, "sltu", "d,v,t", dreg
, 0, sreg
);
2141 macro_build (&icnt
, NULL
, "xor", "d,v,t", dreg
, sreg
, treg
);
2142 macro_build (&icnt
, NULL
, "sltu", "d,v,t", dreg
, 0, dreg
);
2147 if (imm_expr
.X_add_number
== 0)
2149 macro_build (&icnt
, NULL
, "sltu", "d,v,t", dreg
, 0, sreg
);
2154 as_warn ("Instruction %s: result is always true",
2156 macro_build (&icnt
, &expr1
, "addiu", "t,r,j", dreg
, 0);
2159 switch (imm_expr
.X_add_number
& 0xffff8000)
2163 macro_build (&icnt
, &imm_expr
, "xori", "t,r,i", dreg
, sreg
);
2168 if (imm_expr
.X_add_number
!= -32768)
2170 imm_expr
.X_add_number
= -imm_expr
.X_add_number
;
2171 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", dreg
, sreg
);
2178 macro_build_lui (&icnt
, &imm_expr
, AT
);
2179 if (imm_expr
.X_add_number
& 0xffff)
2180 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", AT
, AT
);
2181 macro_build (&icnt
, NULL
, "xor", "d,v,t", dreg
, sreg
, AT
);
2184 macro_build (&icnt
, NULL
, "sltu", "d,v,t", dreg
, 0, dreg
);
2190 if (imm_expr
.X_add_number
< 32768 && imm_expr
.X_add_number
> -32768)
2192 imm_expr
.X_add_number
= -imm_expr
.X_add_number
;
2193 macro_build (&icnt
, &imm_expr
, "addi", "t,r,j", dreg
, sreg
);
2196 load_register (&icnt
, ip
, AT
, &imm_expr
);
2197 macro_build (&icnt
, NULL
, "sub", "d,v,t", dreg
, sreg
, AT
);
2201 if (imm_expr
.X_add_number
< 32768 && imm_expr
.X_add_number
> -32768)
2203 imm_expr
.X_add_number
= -imm_expr
.X_add_number
;
2204 macro_build (&icnt
, &imm_expr
, "addiu", "t,r,j", dreg
, sreg
);
2207 load_register (&icnt
, ip
, AT
, &imm_expr
);
2208 macro_build (&icnt
, NULL
, "subu", "d,v,t", dreg
, sreg
, AT
);
2213 sreg
= (ip
->insn_opcode
>> 11) & 0x1f; /* floating reg */
2214 dreg
= (ip
->insn_opcode
>> 06) & 0x1f; /* floating reg */
2217 * Is the double cfc1 instruction a bug in the mips assembler;
2218 * or is there a reason for it?
2220 mips_emit_delays ();
2222 macro_build (&icnt
, NULL
, "cfc1", "t,G", treg
, 31);
2223 macro_build (&icnt
, NULL
, "cfc1", "t,G", treg
, 31);
2224 macro_build (&icnt
, NULL
, "nop", "");
2225 expr1
.X_add_number
= 3;
2226 macro_build (&icnt
, &expr1
, "ori", "t,r,i", AT
, treg
);
2227 expr1
.X_add_number
= 2;
2228 macro_build (&icnt
, &expr1
, "xori", "t,r,i", AT
, AT
);
2229 macro_build (&icnt
, NULL
, "ctc1", "t,G", AT
, 31);
2230 macro_build (&icnt
, NULL
, "nop", "");
2231 macro_build (&icnt
, NULL
,
2232 mask
== M_TRUNCWD
? "cvt.w.d" : "cvt.w.s", "D,S", dreg
, sreg
);
2233 macro_build (&icnt
, NULL
, "ctc1", "t,G", treg
, 31);
2234 macro_build (&icnt
, NULL
, "nop", "");
2244 /* avoid load delay */
2245 offset_expr
.X_add_number
+= 1;
2246 macro_build (&icnt
, &offset_expr
, s
, "t,o(b)", treg
, breg
);
2247 offset_expr
.X_add_number
-= 1;
2248 macro_build (&icnt
, &offset_expr
, "lbu", "t,o(b)", AT
, breg
);
2249 macro_build (&icnt
, NULL
, "sll", "d,w,<", treg
, treg
, 8);
2250 macro_build (&icnt
, NULL
, "or", "d,v,t", treg
, treg
, AT
);
2254 /* does this work on a big endian machine? */
2255 offset_expr
.X_add_number
+= 3;
2256 macro_build (&icnt
, &offset_expr
, "lwl", "t,o(b)", treg
, breg
);
2257 offset_expr
.X_add_number
-= 3;
2258 macro_build (&icnt
, &offset_expr
, "lwr", "t,o(b)", treg
, breg
);
2264 if (offset_expr
.X_op
== O_constant
)
2265 load_register (&icnt
, ip
, AT
, &offset_expr
);
2266 else if (gp_reference (&offset_expr
))
2267 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", AT
, GP
);
2270 macro_build_lui (&icnt
, &offset_expr
, AT
);
2271 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", AT
, AT
);
2273 if (mask
== M_ULW_A
)
2275 expr1
.X_add_number
= 3;
2276 macro_build (&icnt
, &expr1
, "lwl", "t,o(b)", treg
, AT
);
2277 imm_expr
.X_add_number
= 0;
2278 macro_build (&icnt
, &expr1
, "lwr", "t,o(b)", treg
, AT
);
2282 macro_build (&icnt
, &expr1
,
2283 mask
== M_ULH_A
? "lb" : "lbu", "t,o(b)", treg
, AT
);
2284 imm_expr
.X_add_number
= 0;
2285 macro_build (&icnt
, &expr1
, "lbu", "t,o(b)", AT
, AT
);
2286 macro_build (&icnt
, NULL
, "sll", "d,w,<", treg
, treg
, 8);
2287 macro_build (&icnt
, NULL
, "or", "d,v,t", treg
, treg
, AT
);
2292 macro_build (&icnt
, &offset_expr
, "sb", "t,o(b)", treg
, breg
);
2293 macro_build (&icnt
, NULL
, "srl", "d,w,<", AT
, treg
, 8);
2294 offset_expr
.X_add_number
+= 1;
2295 macro_build (&icnt
, &offset_expr
, "sb", "t,o(b)", AT
, breg
);
2299 offset_expr
.X_add_number
+= 3;
2300 macro_build (&icnt
, &offset_expr
, "swl", "t,o(b)", treg
, breg
);
2301 offset_expr
.X_add_number
-= 3;
2302 macro_build (&icnt
, &offset_expr
, "swr", "t,o(b)", treg
, breg
);
2307 if (offset_expr
.X_op
== O_constant
)
2308 load_register (&icnt
, ip
, AT
, &offset_expr
);
2309 else if (gp_reference (&offset_expr
))
2310 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", AT
, GP
);
2313 macro_build_lui (&icnt
, &offset_expr
, AT
);
2314 macro_build (&icnt
, &offset_expr
, "addiu", "t,r,j", AT
, AT
);
2316 if (mask
== M_USW_A
)
2318 expr1
.X_add_number
= 3;
2319 macro_build (&icnt
, &expr1
, "swl", "t,o(b)", treg
, AT
);
2320 expr1
.X_add_number
= 0;
2321 macro_build (&icnt
, &expr1
, "swr", "t,o(b)", treg
, AT
);
2325 expr1
.X_add_number
= 0;
2326 macro_build (&icnt
, &expr1
, "sb", "t,o(b)", treg
, AT
);
2327 macro_build (&icnt
, NULL
, "srl", "d,w,<", treg
, treg
, 8);
2328 expr1
.X_add_number
= 1;
2329 macro_build (&icnt
, &expr1
, "sb", "t,o(b)", treg
, AT
);
2330 expr1
.X_add_number
= 0;
2331 macro_build (&icnt
, &expr1
, "lbu", "t,o(b)", AT
, AT
);
2332 macro_build (&icnt
, NULL
, "sll", "d,w,<", treg
, treg
, 8);
2333 macro_build (&icnt
, NULL
, "or", "d,v,t", treg
, treg
, AT
);
2338 as_bad ("Macro %s not implemented yet", ip
->insn_mo
->name
);
2341 as_warn ("Macro used $at after \".set noat\"");
2346 This routine assembles an instruction into its binary format. As a side
2347 effect it sets one of the global variables imm_reloc or offset_reloc to the
2348 type of relocation to do if one of the operands is an address expression.
2353 struct mips_cl_insn
*ip
;
2358 struct mips_opcode
*insn
;
2361 unsigned int lastregno
= 0;
2366 for (s
= str
; islower (*s
) || (*s
>= '0' && *s
<= '3') || *s
== '.'; ++s
)
2378 as_warn ("Unknown opcode: `%s'", str
);
2381 if ((insn
= (struct mips_opcode
*) hash_find (op_hash
, str
)) == NULL
)
2383 as_warn ("`%s' not in hash table.", str
);
2384 insn_error
= "ERROR: Unrecognized opcode";
2390 assert (strcmp (insn
->name
, str
) == 0);
2392 ip
->insn_opcode
= insn
->match
;
2393 for (args
= insn
->args
;; ++args
)
2399 case '\0': /* end of args */
2412 ip
->insn_opcode
|= lastregno
<< 21;
2417 ip
->insn_opcode
|= lastregno
<< 16;
2421 ip
->insn_opcode
|= lastregno
<< 11;
2427 /* handle optional base register.
2428 Either the base register is omitted or
2429 we must have a left paren. */
2430 /* this is dependent on the next operand specifier
2431 is a 'b' for base register */
2432 assert (args
[1] == 'b');
2436 case ')': /* these must match exactly */
2441 case '<': /* must be at least one digit */
2443 * According to the manual, if the shift amount is greater
2444 * than 31 or less than 0 the the shift amount should be
2445 * mod 32. In reality the mips assembler issues an error.
2446 * We issue a warning and do the mod.
2448 my_getExpression (&imm_expr
, s
);
2449 check_absolute_expr (ip
, &imm_expr
);
2450 if ((unsigned long) imm_expr
.X_add_number
> 31)
2452 as_warn ("Improper shift amount (%d)",
2453 imm_expr
.X_add_number
);
2454 imm_expr
.X_add_number
= imm_expr
.X_add_number
% 32;
2456 ip
->insn_opcode
|= imm_expr
.X_add_number
<< 6;
2457 imm_expr
.X_op
= O_absent
;
2461 case 'c': /* break code */
2462 my_getExpression (&imm_expr
, s
);
2463 check_absolute_expr (ip
, &imm_expr
);
2464 if ((unsigned) imm_expr
.X_add_number
> 1023)
2465 as_warn ("Illegal break code (%d)", imm_expr
.X_add_number
);
2466 ip
->insn_opcode
|= imm_expr
.X_add_number
<< 16;
2467 imm_expr
.X_op
= O_absent
;
2471 case 'B': /* syscall code */
2472 my_getExpression (&imm_expr
, s
);
2473 check_absolute_expr (ip
, &imm_expr
);
2474 if ((unsigned) imm_expr
.X_add_number
> 0xfffff)
2475 as_warn ("Illegal syscall code (%d)", imm_expr
.X_add_number
);
2476 ip
->insn_opcode
|= imm_expr
.X_add_number
<< 6;
2477 imm_expr
.X_op
= O_absent
;
2481 case 'C': /* Coprocessor code */
2482 my_getExpression (&imm_expr
, s
);
2483 check_absolute_expr (ip
, &imm_expr
);
2484 if ((unsigned long) imm_expr
.X_add_number
>= (1<<25))
2486 as_warn ("Coproccesor code > 25 bits (%d)",
2487 imm_expr
.X_add_number
);
2488 imm_expr
.X_add_number
&= ((1<<25) - 1);
2490 ip
->insn_opcode
|= imm_expr
.X_add_number
;
2491 imm_expr
.X_op
= O_absent
;
2495 case 'b': /* base register */
2496 case 'd': /* destination register */
2497 case 's': /* source register */
2498 case 't': /* target register */
2499 case 'r': /* both target and source */
2500 case 'v': /* both dest and source */
2501 case 'w': /* both dest and target */
2502 case 'E': /* coprocessor target register */
2503 case 'G': /* coprocessor destination register */
2517 while (isdigit (*s
));
2519 as_bad ("Invalid register number (%d)", regno
);
2521 else if (*args
!= 'E' && *args
!= 'G')
2523 if (s
[1] == 'f' && s
[2] == 'p')
2528 else if (s
[1] == 's' && s
[2] == 'p')
2533 else if (s
[1] == 'g' && s
[2] == 'p')
2538 else if (s
[1] == 'a' && s
[2] == 't')
2545 if (regno
== AT
&& ! mips_noat
)
2546 as_warn ("Used $at without \".set noat\"");
2553 if (c
== 'r' || c
== 'v' || c
== 'w')
2566 ip
->insn_opcode
|= regno
<< 21;
2570 ip
->insn_opcode
|= regno
<< 11;
2575 ip
->insn_opcode
|= regno
<< 16;
2585 ip
->insn_opcode
|= lastregno
<< 21;
2588 ip
->insn_opcode
|= lastregno
<< 16;
2593 case 'D': /* floating point destination register */
2594 case 'S': /* floating point source register */
2595 case 'T': /* floating point target register */
2599 if (s
[0] == '$' && s
[1] == 'f' && isdigit (s
[2]))
2609 while (isdigit (*s
));
2612 as_bad ("Invalid float register number (%d)", regno
);
2615 !(strcmp (str
, "mtc1") == 0 ||
2616 strcmp (str
, "mfc1") == 0 ||
2617 strcmp (str
, "lwc1") == 0 ||
2618 strcmp (str
, "swc1") == 0))
2619 as_warn ("Float register should be even, was %d",
2627 if (c
== 'V' || c
== 'W')
2637 ip
->insn_opcode
|= regno
<< 6;
2641 ip
->insn_opcode
|= regno
<< 11;
2645 ip
->insn_opcode
|= regno
<< 16;
2653 ip
->insn_opcode
|= lastregno
<< 11;
2656 ip
->insn_opcode
|= lastregno
<< 16;
2662 my_getExpression (&imm_expr
, s
);
2663 check_absolute_expr (ip
, &imm_expr
);
2668 my_getExpression (&offset_expr
, s
);
2669 imm_reloc
= BFD_RELOC_32
;
2674 as_bad ("Floating point constants only implemented for pseudo ops.");
2677 case 'i': /* 16 bit unsigned immediate */
2678 case 'j': /* 16 bit signed immediate */
2679 imm_reloc
= BFD_RELOC_LO16
;
2680 c
= my_getSmallExpression (&imm_expr
, s
);
2685 if (imm_expr
.X_op
== O_constant
)
2686 imm_expr
.X_add_number
=
2687 (imm_expr
.X_add_number
>> 16) & 0xffff;
2689 imm_reloc
= BFD_RELOC_HI16_S
;
2691 imm_reloc
= BFD_RELOC_HI16
;
2695 check_absolute_expr (ip
, &imm_expr
);
2698 if ((unsigned long) imm_expr
.X_add_number
> 65535)
2700 if (insn
+ 1 < &mips_opcodes
[NUMOPCODES
] &&
2701 !strcmp (insn
->name
, insn
[1].name
))
2703 as_bad ("16 bit expression not in range 0..65535");
2708 if (imm_expr
.X_add_number
< -32768 ||
2709 imm_expr
.X_add_number
> 32767)
2711 if (insn
+ 1 < &mips_opcodes
[NUMOPCODES
] &&
2712 !strcmp (insn
->name
, insn
[1].name
))
2714 as_bad ("16 bit expression not in range -32768..32767");
2720 case 'o': /* 16 bit offset */
2721 c
= my_getSmallExpression (&offset_expr
, s
);
2723 * If this value won't fit into a 16 bit offset, then
2724 * go find a macro that will generate the 32 bit offset
2727 if ((offset_expr
.X_add_symbol
2728 && offset_expr
.X_op
!= O_constant
)
2729 || offset_expr
.X_op_symbol
2730 || offset_expr
.X_add_number
> 32767
2731 || offset_expr
.X_add_number
< -32768)
2734 offset_reloc
= BFD_RELOC_LO16
;
2735 if (c
== 'h' || c
== 'H')
2736 offset_expr
.X_add_number
=
2737 (offset_expr
.X_add_number
>> 16) & 0xffff;
2741 case 'p': /* pc relative offset */
2742 offset_reloc
= BFD_RELOC_16_PCREL_S2
;
2743 my_getExpression (&offset_expr
, s
);
2747 case 'u': /* upper 16 bits */
2748 c
= my_getSmallExpression (&imm_expr
, s
);
2749 if ((unsigned long) imm_expr
.X_add_number
> 65535)
2750 as_bad ("lui expression not in range 0..65535");
2751 imm_reloc
= BFD_RELOC_LO16
;
2756 if (imm_expr
.X_op
== O_constant
)
2757 imm_expr
.X_add_number
=
2758 (imm_expr
.X_add_number
>> 16) & 0xffff;
2760 imm_reloc
= BFD_RELOC_HI16_S
;
2762 imm_reloc
= BFD_RELOC_HI16
;
2768 case 'a': /* 26 bit address */
2769 my_getExpression (&offset_expr
, s
);
2771 offset_reloc
= BFD_RELOC_MIPS_JMP
;
2775 fprintf (stderr
, "bad char = '%c'\n", *args
);
2780 /* Args don't match. */
2781 if (insn
+ 1 < &mips_opcodes
[NUMOPCODES
] &&
2782 !strcmp (insn
->name
, insn
[1].name
))
2788 insn_error
= "ERROR: Illegal operands";
2797 my_getSmallExpression (ep
, str
)
2808 ((str
[1] == 'h' && str
[2] == 'i')
2809 || (str
[1] == 'H' && str
[2] == 'I')
2810 || (str
[1] == 'l' && str
[2] == 'o'))
2822 * A small expression may be followed by a base register.
2823 * Scan to the end of this operand, and then back over a possible
2824 * base register. Then scan the small expression up to that
2825 * point. (Based on code in sparc.c...)
2827 for (sp
= str
; *sp
&& *sp
!= ','; sp
++)
2829 if (sp
- 4 >= str
&& sp
[-1] == RP
)
2831 if (isdigit (sp
[-2]))
2833 for (sp
-= 3; sp
>= str
&& isdigit (*sp
); sp
--)
2835 if (*sp
== '$' && sp
> str
&& sp
[-1] == LP
)
2841 else if (sp
- 5 >= str
2844 && ((sp
[-3] == 'f' && sp
[-2] == 'p')
2845 || (sp
[-3] == 's' && sp
[-2] == 'p')
2846 || (sp
[-3] == 'g' && sp
[-2] == 'p')
2847 || (sp
[-3] == 'a' && sp
[-2] == 't')))
2853 /* no expression means zero offset */
2856 /* %xx(reg) is an error */
2857 ep
->X_op
= O_absent
;
2862 ep
->X_op
= O_absent
;
2865 ep
->X_add_symbol
= NULL
;
2866 ep
->X_op_symbol
= NULL
;
2867 ep
->X_add_number
= 0;
2872 my_getExpression (ep
, str
);
2879 my_getExpression (ep
, str
);
2880 return c
; /* => %hi or %lo encountered */
2884 my_getExpression (ep
, str
)
2890 save_in
= input_line_pointer
;
2891 input_line_pointer
= str
;
2893 expr_end
= input_line_pointer
;
2894 input_line_pointer
= save_in
;
2897 /* Turn a string in input_line_pointer into a floating point constant
2898 of type type, and store the appropriate bytes in *litP. The number
2899 of LITTLENUMS emitted is stored in *sizeP . An error message is
2900 returned, or NULL on OK. */
2903 md_atof (type
, litP
, sizeP
)
2909 LITTLENUM_TYPE words
[4];
2925 return "bad call to md_atof";
2928 t
= atof_ieee (input_line_pointer
, type
, words
);
2930 input_line_pointer
= t
;
2934 if (byte_order
== LITTLE_ENDIAN
)
2936 for (i
= prec
- 1; i
>= 0; i
--)
2938 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
2944 for (i
= 0; i
< prec
; i
++)
2946 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
2955 md_number_to_chars (buf
, val
, n
)
3007 md_parse_option (argP
, cntP
, vecP
)
3012 /* Accept -nocpp but ignore it. */
3013 if (!strcmp (*argP
, "nocpp"))
3019 if (strcmp (*argP
, "EL") == 0
3020 || strcmp (*argP
, "EB") == 0)
3022 /* FIXME: This breaks -L -EL. */
3030 if ((*argP
)[1] == '0')
3039 if ((*argP
)[1] == '\0' || (*argP
)[1] == '2')
3047 if ((*argP
)[1] != '\0')
3048 g_switch_value
= atoi (*argP
+ 1);
3051 **vecP
= (char *) NULL
;
3054 g_switch_value
= atoi (**vecP
);
3057 as_warn ("Number expected after -G");
3063 return 1; /* pretend you parsed the character */
3067 md_pcrel_from (fixP
)
3070 /* return the address of the delay slot */
3071 return fixP
->fx_size
+ fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
3075 md_apply_fix (fixP
, valueP
)
3082 assert (fixP
->fx_size
== 4);
3085 fixP
->fx_addnumber
= value
; /* Remember value for tc_gen_reloc */
3087 switch (fixP
->fx_r_type
)
3090 case BFD_RELOC_MIPS_JMP
:
3091 case BFD_RELOC_HI16
:
3092 case BFD_RELOC_HI16_S
:
3093 case BFD_RELOC_LO16
:
3094 case BFD_RELOC_MIPS_GPREL
:
3095 /* Nothing needed to do. The value comes from the reloc entry */
3098 case BFD_RELOC_16_PCREL_S2
:
3100 * We need to save the bits in the instruction since fixup_segment()
3101 * might be deleting the relocation entry (i.e., a branch within
3102 * the current segment).
3105 as_warn ("Branch to odd address (%x)", value
);
3107 if ((value
& ~0xFFFF) && (value
& ~0xFFFF) != (-1 & ~0xFFFF))
3108 as_bad ("Relocation overflow");
3110 /* update old instruction data */
3111 buf
= (unsigned char *) (fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
);
3115 insn
= (buf
[3] << 24) | (buf
[2] << 16) | (buf
[1] << 8) | buf
[0];
3119 insn
= (buf
[0] << 24) | (buf
[1] << 16) | (buf
[2] << 8) | buf
[3];
3126 insn
|= value
& 0xFFFF;
3127 md_number_to_chars ((char *) buf
, insn
, 4);
3141 const struct mips_opcode
*p
;
3142 int treg
, sreg
, dreg
, shamt
;
3147 for (i
= 0; i
< NUMOPCODES
; ++i
)
3149 p
= &mips_opcodes
[i
];
3150 if (((oc
& p
->mask
) == p
->match
) && (p
->pinfo
!= INSN_MACRO
))
3152 printf ("%08lx %s\t", oc
, p
->name
);
3153 treg
= (oc
>> 16) & 0x1f;
3154 sreg
= (oc
>> 21) & 0x1f;
3155 dreg
= (oc
>> 11) & 0x1f;
3156 shamt
= (oc
>> 6) & 0x1f;
3158 for (args
= p
->args
;; ++args
)
3169 printf ("%c", *args
);
3173 assert (treg
== sreg
);
3174 printf ("$%d,$%d", treg
, sreg
);
3179 printf ("$%d", dreg
);
3184 printf ("$%d", treg
);
3189 printf ("$%d", sreg
);
3193 printf ("0x%08lx", oc
& 0x1ffffff);
3204 printf ("$%d", shamt
);
3215 printf ("%08lx UNDEFINED\n", oc
);
3226 name
= input_line_pointer
;
3227 c
= get_symbol_end ();
3228 p
= (symbolS
*) symbol_find_or_make (name
);
3229 *input_line_pointer
= c
;
3233 /* Align the current frag to a given power of two. The MIPS assembler
3234 also automatically adjusts any preceding label. */
3237 mips_align (to
, fill
)
3241 mips_emit_delays ();
3242 frag_align (to
, fill
);
3243 record_alignment (now_seg
, to
);
3244 if (insn_label
!= NULL
)
3246 assert (S_GET_SEGMENT (insn_label
) == now_seg
);
3247 insn_label
->sy_frag
= frag_now
;
3248 S_SET_VALUE (insn_label
, frag_now_fix ());
3252 /* Align to a given power of two. .align 0 turns off the automatic
3253 alignment used by the data creating pseudo-ops. */
3260 register long temp_fill
;
3261 long max_alignment
= 15;
3265 o Note that the assembler pulls down any immediately preceeding label
3266 to the aligned address.
3267 o It's not documented but auto alignment is reinstated by
3268 a .align pseudo instruction.
3269 o Note also that after auto alignment is turned off the mips assembler
3270 issues an error on attempt to assemble an improperly aligned data item.
3275 temp
= get_absolute_expression ();
3276 if (temp
> max_alignment
)
3277 as_bad ("Alignment too large: %d. assumed.", temp
= max_alignment
);
3280 as_warn ("Alignment negative: 0 assumed.");
3283 if (*input_line_pointer
== ',')
3285 input_line_pointer
++;
3286 temp_fill
= get_absolute_expression ();
3293 mips_align (temp
, (int) temp_fill
);
3300 demand_empty_rest_of_line ();
3303 /* Handle .ascii and .asciiz. This just calls stringer and forgets
3304 that there was a previous instruction. */
3307 s_stringer (append_zero
)
3310 mips_emit_delays ();
3311 stringer (append_zero
);
3320 mips_emit_delays ();
3329 subseg_new (".rdata", (subsegT
) get_absolute_expression ());
3330 demand_empty_rest_of_line ();
3339 #ifdef BFD_ASSEMBLER
3340 subseg_set (bss_section
, (subsegT
) get_absolute_expression ());
3342 subseg_new (bss_section
, (subsegT
) get_absolute_expression ());
3344 demand_empty_rest_of_line ();
3348 subseg_new (".sdata", (subsegT
) get_absolute_expression ());
3349 demand_empty_rest_of_line ();
3352 as_bad ("Global pointers not supported; recompile -G 0");
3353 demand_empty_rest_of_line ();
3364 mips_emit_delays ();
3365 if (log_size
> 0 && auto_align
)
3366 mips_align (log_size
, 0);
3367 cons (1 << log_size
);
3374 as_fatal ("Encountered `.err', aborting assembly");
3384 symbolP
= get_symbol ();
3385 if (*input_line_pointer
== ',')
3386 input_line_pointer
++;
3387 size
= get_absolute_expression ();
3388 S_SET_VALUE (symbolP
, size
);
3389 S_SET_EXTERNAL (symbolP
);
3392 /* ECOFF needs to distinguish a .comm symbol from a .extern symbol,
3393 so we use an additional ECOFF specific field. */
3394 symbolP
->ecoff_undefined
= 1;
3402 mips_emit_delays ();
3417 if (strcmp (input_line_pointer
, "O1") != 0
3418 && strcmp (input_line_pointer
, "O2") != 0)
3419 as_warn ("Unrecognized option");
3420 demand_empty_rest_of_line ();
3427 char *name
= input_line_pointer
, ch
;
3429 while (!is_end_of_line
[(unsigned char) *input_line_pointer
])
3430 input_line_pointer
++;
3431 ch
= *input_line_pointer
;
3432 *input_line_pointer
= '\0';
3434 if (strcmp (name
, "reorder") == 0)
3438 prev_insn_unreordered
= 1;
3439 prev_prev_insn_unreordered
= 1;
3443 else if (strcmp (name
, "noreorder") == 0)
3445 mips_emit_delays ();
3448 else if (strcmp (name
, "at") == 0)
3452 else if (strcmp (name
, "noat") == 0)
3456 else if (strcmp (name
, "macro") == 0)
3458 mips_warn_about_macros
= 0;
3460 else if (strcmp (name
, "nomacro") == 0)
3462 if (mips_noreorder
== 0)
3463 as_bad ("`noreorder' must be set before `nomacro'");
3464 mips_warn_about_macros
= 1;
3466 else if (strcmp (name
, "move") == 0 || strcmp (name
, "novolatile") == 0)
3470 else if (strcmp (name
, "nomove") == 0 || strcmp (name
, "volatile") == 0)
3474 else if (strcmp (name
, "bopt") == 0)
3478 else if (strcmp (name
, "nobopt") == 0)
3484 as_warn ("Tried to set unrecognized symbol: %s\n", name
);
3486 *input_line_pointer
= ch
;
3487 demand_empty_rest_of_line ();
3490 /* The same as the usual .space directive, except that we have to
3491 forget about any previous instruction. */
3494 s_mips_space (param
)
3497 mips_emit_delays ();
3507 if (*input_line_pointer
++ != '$')
3509 as_warn ("expected `$'");
3512 if (isdigit ((unsigned char) *input_line_pointer
))
3514 reg
= get_absolute_expression ();
3515 if (reg
< 0 || reg
>= 32)
3517 as_warn ("Bad register number");
3523 if (strncmp (input_line_pointer
, "fp", 2) == 0)
3525 else if (strncmp (input_line_pointer
, "sp", 2) == 0)
3527 else if (strncmp (input_line_pointer
, "gp", 2) == 0)
3529 else if (strncmp (input_line_pointer
, "at", 2) == 0)
3533 as_warn ("Unrecognized register name");
3536 input_line_pointer
+= 2;
3542 * Translate internal representation of relocation info to BFD target format.
3545 tc_gen_reloc (section
, fixp
)
3551 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
3552 assert (reloc
!= 0);
3554 reloc
->sym_ptr_ptr
= &fixp
->fx_addsy
->bsym
;
3555 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
3556 if (fixp
->fx_pcrel
== 0)
3557 reloc
->addend
= fixp
->fx_addnumber
;
3562 reloc
->addend
= -reloc
->address
;
3564 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
3565 assert (reloc
->howto
!= 0);
3570 /* should never be called */
3572 md_section_align (seg
, addr
)
3576 int align
= bfd_get_section_alignment (stdoutput
, seg
);
3578 return ((addr
+ (1 << align
) - 1) & (-1 << align
));
3582 md_estimate_size_before_relax (fragP
, segtype
)
3586 as_fatal ("md_estimate_size_before_relax");
3588 } /* md_estimate_size_before_relax() */
3590 /* This function is called whenever a label is defined. It is used
3591 when handling branch delays; if a branch has a label, we assume we
3595 mips_define_label (sym
)
3603 /* These functions should really be defined by the object file format,
3604 since they are related to debugging information. However, this
3605 code has to work for the a.out format, which does not define them,
3606 so we provide simple versions here. These don't actually generate
3607 any debugging information, but they do simple checking and someday
3608 somebody may make them useful. */
3612 struct loc
*loc_next
;
3613 unsigned long loc_fileno
;
3614 unsigned long loc_lineno
;
3615 unsigned long loc_offset
;
3616 unsigned short loc_delta
;
3617 unsigned short loc_count
;
3626 struct proc
*proc_next
;
3627 struct symbol
*proc_isym
;
3628 struct symbol
*proc_end
;
3629 unsigned long proc_reg_mask
;
3630 unsigned long proc_reg_offset
;
3631 unsigned long proc_fpreg_mask
;
3632 unsigned long proc_fpreg_offset
;
3633 unsigned long proc_frameoffset
;
3634 unsigned long proc_framereg
;
3635 unsigned long proc_pcreg
;
3637 struct file
*proc_file
;
3644 struct file
*file_next
;
3645 unsigned long file_fileno
;
3646 struct symbol
*file_symbol
;
3647 struct symbol
*file_end
;
3648 struct proc
*file_proc
;
3653 static struct obstack proc_frags
;
3654 static procS
*proc_lastP
;
3655 static procS
*proc_rootP
;
3656 static int numprocs
;
3661 obstack_begin (&proc_frags
, 0x2000);
3667 /* check for premature end, nesting errors, etc */
3668 if (proc_lastP
&& proc_lastP
->proc_end
== NULL
)
3669 as_warn ("missing `.end' at end of assembly");
3672 extern char hex_value
[];
3680 if (*input_line_pointer
== '-')
3682 ++input_line_pointer
;
3685 if (!isdigit (*input_line_pointer
))
3686 as_bad ("Expected simple number.");
3687 if (input_line_pointer
[0] == '0')
3689 if (input_line_pointer
[1] == 'x')
3691 input_line_pointer
+= 2;
3692 while (isxdigit (*input_line_pointer
))
3695 val
|= hex_value
[(int) *input_line_pointer
++];
3697 return negative
? -val
: val
;
3701 ++input_line_pointer
;
3702 while (isdigit (*input_line_pointer
))
3705 val
|= *input_line_pointer
++ - '0';
3707 return negative
? -val
: val
;
3710 if (!isdigit (*input_line_pointer
))
3712 printf (" *input_line_pointer == '%c' 0x%02x\n",
3713 *input_line_pointer
, *input_line_pointer
);
3714 as_warn ("Invalid number");
3717 while (isdigit (*input_line_pointer
))
3720 val
+= *input_line_pointer
++ - '0';
3722 return negative
? -val
: val
;
3725 /* The .file directive; just like the usual .file directive, but there
3726 is an initial number which is the ECOFF file index. */
3734 line
= get_number ();
3739 /* The .end directive. */
3747 if (!is_end_of_line
[(unsigned char) *input_line_pointer
])
3750 demand_empty_rest_of_line ();
3754 if (now_seg
!= text_section
)
3755 as_warn (".end not in text section");
3758 as_warn (".end and no .ent seen yet.");
3764 assert (S_GET_NAME (p
));
3765 if (strcmp (S_GET_NAME (p
), S_GET_NAME (proc_lastP
->proc_isym
)))
3766 as_warn (".end symbol does not match .ent symbol.");
3769 proc_lastP
->proc_end
= (symbolS
*) 1;
3772 /* The .aent and .ent directives. */
3782 symbolP
= get_symbol ();
3783 if (*input_line_pointer
== ',')
3784 input_line_pointer
++;
3785 if (isdigit (*input_line_pointer
) || *input_line_pointer
== '-')
3786 number
= get_number ();
3787 if (now_seg
!= text_section
)
3788 as_warn (".ent or .aent not in text section.");
3790 if (!aent
&& proc_lastP
&& proc_lastP
->proc_end
== NULL
)
3791 as_warn ("missing `.end'");
3795 procP
= (procS
*) obstack_alloc (&proc_frags
, sizeof (*procP
));
3796 procP
->proc_isym
= symbolP
;
3797 procP
->proc_reg_mask
= 0;
3798 procP
->proc_reg_offset
= 0;
3799 procP
->proc_fpreg_mask
= 0;
3800 procP
->proc_fpreg_offset
= 0;
3801 procP
->proc_frameoffset
= 0;
3802 procP
->proc_framereg
= 0;
3803 procP
->proc_pcreg
= 0;
3804 procP
->proc_end
= NULL
;
3805 procP
->proc_next
= NULL
;
3807 proc_lastP
->proc_next
= procP
;
3813 demand_empty_rest_of_line ();
3816 /* The .frame directive. */
3829 frame_reg
= tc_get_register ();
3830 if (*input_line_pointer
== ',')
3831 input_line_pointer
++;
3832 frame_off
= get_absolute_expression ();
3833 if (*input_line_pointer
== ',')
3834 input_line_pointer
++;
3835 pcreg
= tc_get_register ();
3838 assert (proc_rootP
);
3839 proc_rootP
->proc_framereg
= frame_reg
;
3840 proc_rootP
->proc_frameoffset
= frame_off
;
3841 proc_rootP
->proc_pcreg
= pcreg
;
3842 /* bob macho .frame */
3844 /* We don't have to write out a frame stab for unoptimized code. */
3845 if (!(frame_reg
== 30 && frame_off
== 0))
3848 as_warn ("No .ent for .frame to use.");
3849 (void) sprintf (str
, "R%d;%d", frame_reg
, frame_off
);
3850 symP
= symbol_new (str
, N_VFP
, 0, frag_now
);
3851 S_SET_TYPE (symP
, N_RMASK
);
3852 S_SET_OTHER (symP
, 0);
3853 S_SET_DESC (symP
, 0);
3854 symP
->sy_forward
= proc_lastP
->proc_isym
;
3855 /* bob perhaps I should have used pseudo set */
3857 demand_empty_rest_of_line ();
3861 /* The .fmask and .mask directives. */
3868 char str
[100], *strP
;
3874 mask
= get_number ();
3875 if (*input_line_pointer
== ',')
3876 input_line_pointer
++;
3877 off
= get_absolute_expression ();
3879 /* bob only for coff */
3880 assert (proc_rootP
);
3881 if (reg_type
== 'F')
3883 proc_rootP
->proc_fpreg_mask
= mask
;
3884 proc_rootP
->proc_fpreg_offset
= off
;
3888 proc_rootP
->proc_reg_mask
= mask
;
3889 proc_rootP
->proc_reg_offset
= off
;
3892 /* bob macho .mask + .fmask */
3894 /* We don't have to write out a mask stab if no saved regs. */
3898 as_warn ("No .ent for .mask to use.");
3900 for (i
= 0; i
< 32; i
++)
3904 sprintf (strP
, "%c%d,", reg_type
, i
);
3905 strP
+= strlen (strP
);
3909 sprintf (strP
, ";%d,", off
);
3910 symP
= symbol_new (str
, N_RMASK
, 0, frag_now
);
3911 S_SET_TYPE (symP
, N_RMASK
);
3912 S_SET_OTHER (symP
, 0);
3913 S_SET_DESC (symP
, 0);
3914 symP
->sy_forward
= proc_lastP
->proc_isym
;
3915 /* bob perhaps I should have used pseudo set */
3920 /* The .loc directive. */
3931 assert (now_seg
== text_section
);
3933 lineno
= get_number ();
3934 addroff
= obstack_next_free (&frags
) - frag_now
->fr_literal
;
3936 symbolP
= symbol_new ("", N_SLINE
, addroff
, frag_now
);
3937 S_SET_TYPE (symbolP
, N_SLINE
);
3938 S_SET_OTHER (symbolP
, 0);
3939 S_SET_DESC (symbolP
, lineno
);
3940 symbolP
->sy_segment
= now_seg
;
3944 #endif /* ! defined (OBJ_ECOFF) */