]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-mips.c
* mips-opc.c: li.d uses "T,L", not "S,F". Added li.s.
[thirdparty/binutils-gdb.git] / gas / config / tc-mips.c
CommitLineData
3d3c5039
ILT
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.
6
7 This file is part of GAS.
8
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)
12 any later version.
13
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.
18
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. */
22
23#include "as.h"
24
25#include <ctype.h>
26
27#ifndef __STDC__
28#ifndef NO_STDARG
29#define NO_STDARG
30#endif
31#endif
32
33#ifndef NO_STDARG
34#include <stdarg.h>
35#else
36#ifndef NO_VARARGS
37#include <varargs.h>
38#endif /* NO_VARARGS */
39#endif /* NO_STDARG */
40
918692a5 41#include "opcode/mips.h"
3d3c5039
ILT
42
43#define AT 1
670a50eb 44#define GP 28
3d3c5039
ILT
45#define RA 31
46
47static int mips_warn_about_macros;
48static int mips_noreorder;
49static int mips_nomove;
50static int mips_noat;
51static int mips_nobopt;
52
670a50eb
ILT
53#ifdef OBJ_ECOFF
54/* The size of the small data section. */
55static int g_switch_value = 8;
56#endif
57
3d3c5039
ILT
58#define N_RMASK 0xc4
59#define N_VFP 0xd4
60
61/* handle of the OPCODE hash table */
62static struct hash_control *op_hash = NULL;
63
64/* This array holds the chars that always start a comment. If the
65 pre-processor is disabled, these aren't very useful */
66const char comment_chars[] = "#";
67
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. */
75const char line_comment_chars[] = "#";
76
77/* This array holds machine specific line separator characters. */
78const char line_separator_chars[] = "";
79
80/* Chars that can be used to separate mant from exp in floating point nums */
81const char EXP_CHARS[] = "eE";
82
83/* Chars that mean this number is a floating point constant */
84/* As in 0f12.456 */
85/* or 0d1.2345e12 */
86const char FLT_CHARS[] = "rRsSfFdDxXpP";
87
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.
91 */
92
670a50eb 93static char *insn_error;
3d3c5039
ILT
94
95static int byte_order = BYTE_ORDER;
96
97static int auto_align = 1;
becfe05e
ILT
98
99/* Symbol labelling the current insn. */
100static symbolS *insn_label;
101
102/* To output NOP instructions correctly, we need to keep information
103 about the previous two instructions. */
104
0aa07269
ILT
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
108 insert NOPs. */
109static int mips_optimize = 2;
4e95866e 110
becfe05e
ILT
111/* The previous instruction. */
112static struct mips_cl_insn prev_insn;
113
114/* The instruction before prev_insn. */
115static struct mips_cl_insn prev_prev_insn;
116
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. */
119static const struct mips_opcode dummy_opcode = { 0 };
120
121/* Non-zero if prev_insn is valid. */
122static int prev_insn_valid;
123
124/* The frag for the previous instruction. */
125static struct frag *prev_insn_frag;
126
127/* The offset into prev_insn_frag for the previous instruction. */
128static long prev_insn_where;
129
130/* The reloc for the previous instruction, if any. */
131static fixS *prev_insn_fixp;
132
133/* Non-zero if the previous instruction was in a delay slot. */
134static int prev_insn_is_delay_slot;
4e95866e
ILT
135
136/* Non-zero if the previous instruction was in a .set noreorder. */
137static int prev_insn_unreordered;
138
139/* Non-zero if the previous previous instruction was in a .set
140 noreorder. */
141static int prev_prev_insn_unreordered;
3d3c5039
ILT
142\f
143/* Prototypes for static functions. */
144
145#ifdef __STDC__
146#define internalError() \
147 as_fatal ("internal Error, line %d, %s", __LINE__, __FILE__)
148#else
149#define internalError() as_fatal ("MIPS internal Error");
150#endif
151
becfe05e
ILT
152static int insn_uses_reg PARAMS ((struct mips_cl_insn *ip,
153 int reg, int fpr));
670a50eb
ILT
154static void append_insn PARAMS ((struct mips_cl_insn * ip,
155 expressionS * p,
3d3c5039 156 bfd_reloc_code_real_type r));
becfe05e
ILT
157static void mips_no_prev_insn PARAMS ((void));
158static void mips_emit_delays PARAMS ((void));
670a50eb
ILT
159static int gp_reference PARAMS ((expressionS * ep));
160static void macro_build PARAMS ((int *counter, expressionS * ep,
3d3c5039
ILT
161 const char *name, const char *fmt,
162 ...));
670a50eb 163static void macro_build_lui PARAMS ((int *counter, expressionS * ep,
3d3c5039
ILT
164 int regnum));
165static void set_at PARAMS ((int *counter, int reg));
166static void set_at_unsigned PARAMS ((int *counter, int reg));
670a50eb
ILT
167static void check_absolute_expr PARAMS ((struct mips_cl_insn * ip,
168 expressionS * expr));
3d3c5039 169static void load_register PARAMS ((int *counter,
670a50eb
ILT
170 struct mips_cl_insn * ip,
171 int reg, expressionS * ep));
172static void macro PARAMS ((struct mips_cl_insn * ip));
173static void mips_ip PARAMS ((char *str, struct mips_cl_insn * ip));
174static int my_getSmallExpression PARAMS ((expressionS * ep, char *str));
175static void my_getExpression PARAMS ((expressionS * ep, char *str));
3d3c5039 176static symbolS *get_symbol PARAMS ((void));
becfe05e 177static void mips_align PARAMS ((int to, int fill));
3d3c5039 178static void s_align PARAMS ((int));
becfe05e 179static void s_stringer PARAMS ((int));
3d3c5039
ILT
180static void s_change_sec PARAMS ((int));
181static void s_cons PARAMS ((int));
182static void s_err PARAMS ((int));
183static void s_extern PARAMS ((int));
184static void s_float_cons PARAMS ((int));
185static void s_option PARAMS ((int));
186static void s_mipsset PARAMS ((int));
becfe05e 187static void s_mips_space PARAMS ((int));
3d3c5039
ILT
188#ifndef OBJ_ECOFF
189static void md_obj_begin PARAMS ((void));
190static void md_obj_end PARAMS ((void));
191static long get_number PARAMS ((void));
192static void s_ent PARAMS ((int));
193static void s_mipsend PARAMS ((int));
194static void s_file PARAMS ((int));
195static void s_frame PARAMS ((int));
196static void s_loc PARAMS ((int));
197static void s_mask PARAMS ((char));
198#endif
199\f
200/* Pseudo-op table.
201
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.
205
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,
210 .vreg.
211
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. */
217
218const pseudo_typeS md_pseudo_table[] =
219{
670a50eb
ILT
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',},
3d3c5039 225
670a50eb 226 /* Relatively generic pseudo-ops that happen to be used on MIPS
3d3c5039 227 chips. */
becfe05e 228 {"asciiz", s_stringer, 1},
670a50eb
ILT
229 {"bss", s_change_sec, 'b'},
230 {"err", s_err, 0},
231 {"half", s_cons, 1},
3d3c5039 232
670a50eb 233 /* These pseudo-ops are defined in read.c, but must be overridden
3d3c5039 234 here for one reason or another. */
670a50eb 235 {"align", s_align, 0},
becfe05e
ILT
236 {"ascii", s_stringer, 0},
237 {"asciz", s_stringer, 1},
670a50eb
ILT
238 {"byte", s_cons, 0},
239 {"data", s_change_sec, 'd'},
becfe05e 240 {"double", s_float_cons, 'd'},
670a50eb 241 {"extern", s_extern, 0},
becfe05e
ILT
242 {"float", s_float_cons, 'f'},
243 {"space", s_mips_space, 0},
670a50eb
ILT
244 {"text", s_change_sec, 't'},
245 {"word", s_cons, 2},
3d3c5039
ILT
246
247#ifndef OBJ_ECOFF
670a50eb 248 /* These pseudo-ops should be defined by the object file format.
3d3c5039
ILT
249 However, ECOFF is the only format which currently defines them,
250 so we have versions here for a.out. */
670a50eb
ILT
251 {"aent", s_ent, 1},
252 {"end", s_mipsend, 0},
253 {"ent", s_ent, 0},
254 {"file", s_file, 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},
3d3c5039
ILT
260#endif
261
670a50eb
ILT
262 /* Sentinel. */
263 {NULL}
3d3c5039
ILT
264};
265\f
670a50eb
ILT
266const relax_typeS md_relax_table[] =
267{
918692a5 268 { 0 }
3d3c5039
ILT
269};
270
271
272static char *expr_end;
273
274static expressionS imm_expr;
275static expressionS offset_expr;
276static bfd_reloc_code_real_type imm_reloc;
277static bfd_reloc_code_real_type offset_reloc;
278
279/*
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.
282 */
283void
670a50eb 284md_begin ()
3d3c5039 285{
670a50eb
ILT
286 register char *retval = NULL;
287 register unsigned int i = 0;
3d3c5039 288
670a50eb
ILT
289 if ((op_hash = hash_new ()) == NULL)
290 {
291 as_fatal ("Virtual memory exhausted");
3d3c5039 292 }
670a50eb
ILT
293 for (i = 0; i < NUMOPCODES;)
294 {
295 const char *name = mips_opcodes[i].name;
296
297 retval = hash_insert (op_hash, name, &mips_opcodes[i]);
298 if (retval != NULL && *retval != '\0')
299 {
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.");
303 }
304 do
305 {
306 if ((mips_opcodes[i].match & mips_opcodes[i].mask) !=
307 mips_opcodes[i].match)
308 {
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.");
3d3c5039 312 }
670a50eb
ILT
313 ++i;
314 }
315 while ((i < NUMOPCODES) && !strcmp (mips_opcodes[i].name, name));
3d3c5039
ILT
316 }
317
becfe05e
ILT
318 mips_no_prev_insn ();
319
3d3c5039 320#ifndef OBJ_ECOFF
670a50eb 321 md_obj_begin ();
3d3c5039
ILT
322#endif
323}
324
325void
326md_end ()
327{
328#ifndef OBJ_ECOFF
329 md_obj_end ();
330#endif
331}
332
333void
670a50eb
ILT
334md_assemble (str)
335 char *str;
3d3c5039 336{
670a50eb
ILT
337 struct mips_cl_insn insn;
338 static int init;
339
340 if (!init)
341 {
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);
918692a5 345#ifdef OBJ_ECOFF
670a50eb 346 bfd_set_gp_size (stdoutput, g_switch_value);
918692a5 347#endif
670a50eb 348 init = 1;
3d3c5039
ILT
349 }
350
5ac34ac3
ILT
351 imm_expr.X_op = O_absent;
352 offset_expr.X_op = O_absent;
3d3c5039 353
670a50eb
ILT
354 mips_ip (str, &insn);
355 if (insn_error)
356 {
357 as_bad ("%s `%s'", insn_error, str);
358 return;
359 }
360 if (insn.insn_mo->pinfo == INSN_MACRO)
361 {
362 macro (&insn);
3d3c5039 363 }
670a50eb
ILT
364 else
365 {
5ac34ac3 366 if (imm_expr.X_op != O_absent)
670a50eb 367 append_insn (&insn, &imm_expr, imm_reloc);
5ac34ac3 368 else if (offset_expr.X_op != O_absent)
670a50eb
ILT
369 append_insn (&insn, &offset_expr, offset_reloc);
370 else
371 append_insn (&insn, NULL, BFD_RELOC_UNUSED);
3d3c5039
ILT
372 }
373}
374
becfe05e
ILT
375/* See whether instruction IP reads register REG. If FPR is non-zero,
376 REG is a floating point register. */
377
378static int
379insn_uses_reg (ip, reg, fpr)
380 struct mips_cl_insn *ip;
381 int reg;
382 int fpr;
383{
384 /* Don't report on general register 0, since it never changes. */
385 if (! fpr && reg == 0)
386 return 0;
387
388 if (fpr)
389 {
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))
399 return 1;
400 if ((ip->insn_mo->pinfo & INSN_READ_FPR_T)
401 && ((ip->insn_opcode >> OP_SH_FT) & OP_MASK_FT) == (reg &~ 1))
402 return 1;
403 }
404 else
405 {
406 if ((ip->insn_mo->pinfo & INSN_READ_GPR_S)
407 && ((ip->insn_opcode >> OP_SH_RS) & OP_MASK_RS) == reg)
408 return 1;
409 if ((ip->insn_mo->pinfo & INSN_READ_GPR_T)
410 && ((ip->insn_opcode >> OP_SH_RT) & OP_MASK_RT) == reg)
411 return 1;
412 }
413
414 return 0;
415}
416
3d3c5039
ILT
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."
419
420/*
421 * append insn
422 * Output an instruction.
423 */
424static void
670a50eb
ILT
425append_insn (ip, address_expr, reloc_type)
426 struct mips_cl_insn *ip;
427 expressionS *address_expr;
428 bfd_reloc_code_real_type reloc_type;
3d3c5039 429{
670a50eb 430 char *f;
becfe05e
ILT
431 fixS *fixp;
432 int nops = 0;
3d3c5039 433
becfe05e
ILT
434 if (! mips_noreorder)
435 {
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.
439 (1) a load delay
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
445
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
452 it. */
453
454 /* This is how a NOP is emitted. */
455#define emit_nop() md_number_to_chars (frag_more (4), 0, 4)
456
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)
460 {
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);
0aa07269
ILT
464 if (mips_optimize == 0
465 || insn_uses_reg (ip,
466 ((prev_insn.insn_opcode >> OP_SH_RT)
467 & OP_MASK_RT),
468 0))
becfe05e
ILT
469 ++nops;
470 }
471 else if (prev_insn.insn_mo->pinfo & INSN_COPROC_DELAY)
472 {
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.
479
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
483 all. */
484 if (prev_insn.insn_mo->pinfo & INSN_WRITE_FPR_T)
485 {
0aa07269
ILT
486 if (mips_optimize == 0
487 || insn_uses_reg (ip,
488 ((prev_insn.insn_opcode >> OP_SH_RT)
489 & OP_MASK_RT),
490 1))
becfe05e
ILT
491 ++nops;
492 }
493 else if (prev_insn.insn_mo->pinfo & INSN_WRITE_FPR_D)
494 {
0aa07269
ILT
495 if (mips_optimize == 0
496 || insn_uses_reg (ip,
497 ((prev_insn.insn_opcode >> OP_SH_RD)
498 & OP_MASK_RD),
499 1))
becfe05e
ILT
500 ++nops;
501 }
502 else
503 {
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
509 NOPS. */
0aa07269
ILT
510 if (mips_optimize == 0
511 || ((prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
512 && (ip->insn_mo->pinfo & INSN_READ_COND_CODE)))
becfe05e
ILT
513 nops += 2;
514 else if (ip->insn_mo->pinfo & INSN_COP)
515 ++nops;
516 }
517 }
518 else if (prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
519 {
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. */
0aa07269
ILT
525 if (mips_optimize == 0
526 || ip->insn_mo->pinfo & INSN_READ_COND_CODE)
becfe05e
ILT
527 ++nops;
528 }
529 else if (prev_insn.insn_mo->pinfo & INSN_READ_LO)
530 {
531 /* The previous instruction reads the LO register; if the
532 current instruction writes to the LO register, we must
533 insert two NOPS. */
0aa07269
ILT
534 if (mips_optimize == 0
535 || ip->insn_mo->pinfo & INSN_WRITE_LO)
becfe05e
ILT
536 nops += 2;
537 }
538 else if (prev_insn.insn_mo->pinfo & INSN_READ_HI)
539 {
540 /* The previous instruction reads the HI register; if the
541 current instruction writes to the HI register, we must
542 insert a NOP. */
0aa07269
ILT
543 if (mips_optimize == 0
544 || ip->insn_mo->pinfo & INSN_WRITE_HI)
becfe05e
ILT
545 nops += 2;
546 }
547
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
555 instruction. */
556 if (nops == 0
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))))
564 ++nops;
565
566 /* Now emit the right number of NOP instructions. */
567 if (nops > 0)
568 {
569 emit_nop ();
570 if (nops > 1)
571 emit_nop ();
572 if (insn_label != NULL)
573 {
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 ());
577 }
578 }
579 }
580
670a50eb 581 f = frag_more (4);
becfe05e
ILT
582#if 0
583 /* This is testing the address of the frag, not the alignment of
584 the instruction in the current section. */
670a50eb
ILT
585 if ((int) f & 3)
586 {
587 as_bad (ALIGN_ERR);
588 as_bad (ALIGN_ERR2);
3d3c5039
ILT
589 }
590#endif
becfe05e 591 fixp = NULL;
670a50eb
ILT
592 if (address_expr != NULL)
593 {
5ac34ac3 594 if (address_expr->X_op == O_constant)
670a50eb
ILT
595 {
596 switch (reloc_type)
597 {
3d3c5039 598 case BFD_RELOC_32:
670a50eb
ILT
599 ip->insn_opcode |= address_expr->X_add_number;
600 break;
3d3c5039
ILT
601
602 case BFD_RELOC_LO16:
670a50eb
ILT
603 ip->insn_opcode |= address_expr->X_add_number & 0xffff;
604 break;
3d3c5039
ILT
605
606 case BFD_RELOC_MIPS_JMP:
607 case BFD_RELOC_16_PCREL_S2:
670a50eb 608 goto need_reloc;
3d3c5039
ILT
609
610 default:
670a50eb 611 internalError ();
3d3c5039 612 }
670a50eb
ILT
613 }
614 else
615 {
616 assert (reloc_type != BFD_RELOC_UNUSED);
3d3c5039 617 need_reloc:
5ac34ac3
ILT
618 fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
619 address_expr,
620 reloc_type == BFD_RELOC_16_PCREL_S2,
621 reloc_type);
3d3c5039
ILT
622 }
623 }
becfe05e 624
670a50eb
ILT
625 md_number_to_chars (f, ip->insn_opcode, 4);
626
becfe05e 627 if (! mips_noreorder)
670a50eb 628 {
becfe05e
ILT
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))
636 {
0aa07269 637 if (mips_optimize < 2
4e95866e
ILT
638 /* If we had to emit any NOP instructions, then we
639 already know we can not swap. */
640 || nops != 0
becfe05e
ILT
641 /* If we don't even know the previous insn, we can not
642 swap. */
643 || ! prev_insn_valid
644 /* If the previous insn is already in a branch delay
645 slot, then we can not swap. */
646 || prev_insn_is_delay_slot
4e95866e
ILT
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
651 .set noreorder
652 lw $4,XXX
653 .set reorder
654 INSN
655 bne $4,$0,foo
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
becfe05e
ILT
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
672 ctc1 $X,$31
673 INSN
674 INSN
675 bc1t LABEL
676 we can not swap, and I don't feel like handling that
677 case. */
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
683 & (INSN_LOAD_DELAY
684 | INSN_COPROC_DELAY
685 | INSN_WRITE_COND_CODE
686 | INSN_READ_LO
687 | INSN_READ_HI))
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)
696 & OP_MASK_RT),
697 0))
698 || ((prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_D)
699 && insn_uses_reg (ip,
700 ((prev_insn.insn_opcode >> OP_SH_RD)
701 & OP_MASK_RD),
702 0))
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)
709 & OP_MASK_RD),
710 0))
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
715 can not swap. */
716 || ((prev_prev_insn.insn_mo->pinfo & INSN_LOAD_DELAY)
717 && insn_uses_reg (ip,
718 ((prev_prev_insn.insn_opcode >> OP_SH_RT)
719 & OP_MASK_RT),
720 0)))
721 {
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. */
726 emit_nop ();
727 /* Update the previous insn information. */
728 prev_prev_insn = *ip;
729 prev_insn.insn_mo = &dummy_opcode;
730 }
731 else
732 {
733 char *prev_f;
734 char temp[4];
735
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);
740 memcpy (f, temp, 4);
741 if (prev_insn_fixp)
742 {
743 prev_insn_fixp->fx_frag = frag_now;
744 prev_insn_fixp->fx_where = f - frag_now->fr_literal;
745 }
746 if (fixp)
747 {
748 fixp->fx_frag = prev_insn_frag;
749 fixp->fx_where = prev_insn_where;
750 }
751 /* Update the previous insn information; leave prev_insn
752 unchanged. */
753 prev_prev_insn = *ip;
754 }
755 prev_insn_is_delay_slot = 1;
756
757 /* If that was an unconditional branch, forget the previous
758 insn information. */
759 if (ip->insn_mo->pinfo & INSN_UNCOND_BRANCH_DELAY)
760 {
761 prev_prev_insn.insn_mo = &dummy_opcode;
762 prev_insn.insn_mo = &dummy_opcode;
763 }
764 }
765 else
670a50eb 766 {
becfe05e
ILT
767 /* Update the previous insn information. */
768 if (nops > 0)
769 prev_prev_insn.insn_mo = &dummy_opcode;
770 else
771 prev_prev_insn = prev_insn;
772 prev_insn = *ip;
773
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;
778 }
779
4e95866e
ILT
780 prev_prev_insn_unreordered = prev_insn_unreordered;
781 prev_insn_unreordered = 0;
becfe05e
ILT
782 prev_insn_frag = frag_now;
783 prev_insn_where = f - frag_now->fr_literal;
784 prev_insn_fixp = fixp;
785 prev_insn_valid = 1;
786 }
3d3c5039 787
becfe05e
ILT
788 /* We just output an insn, so the next one doesn't have a label. */
789 insn_label = NULL;
790}
791
792/* This function forgets that there was any previous instruction or
793 label. */
794
795static void
796mips_no_prev_insn ()
797{
798 prev_insn.insn_mo = &dummy_opcode;
799 prev_prev_insn.insn_mo = &dummy_opcode;
800 prev_insn_valid = 0;
801 prev_insn_is_delay_slot = 0;
4e95866e
ILT
802 prev_insn_unreordered = 0;
803 prev_prev_insn_unreordered = 0;
becfe05e
ILT
804 insn_label = NULL;
805}
806
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. */
811
812static void
813mips_emit_delays ()
814{
815 if (! mips_noreorder)
816 {
817 int nop;
818
819 nop = 0;
820 if (prev_insn.insn_mo->pinfo & ANY_DELAY)
821 {
822 nop = 1;
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))
826 emit_nop ();
827 }
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))
831 nop = 1;
832 if (nop)
670a50eb 833 {
becfe05e
ILT
834 emit_nop ();
835 if (insn_label != NULL)
836 {
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 ());
840 }
3d3c5039 841 }
becfe05e 842 mips_no_prev_insn ();
3d3c5039
ILT
843 }
844}
845
670a50eb
ILT
846/* Return 1 if an expression can be accessed via the GP register. */
847
848static int
849gp_reference (ep)
850 expressionS *ep;
851{
852#ifdef OBJ_ECOFF
853 symbolS *sym;
9a7d824a 854 const char *symname;
670a50eb
ILT
855 const char *segname;
856
857 sym = ep->X_add_symbol;
858 if (sym == (symbolS *) NULL
5ac34ac3 859 || ep->X_op_symbol != (symbolS *) NULL)
670a50eb 860 return 0;
9a7d824a
ILT
861
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))
874 return 0;
670a50eb
ILT
875 if (! S_IS_DEFINED (sym)
876 && S_GET_VALUE (sym) != 0
877 && S_GET_VALUE (sym) <= g_switch_value)
878 return 1;
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. */
884 return 0;
885#endif /* ! defined (OBJ_ECOFF) */
886}
887
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. */
892
3d3c5039
ILT
893#ifndef NO_STDARG
894static void
895macro_build (int *counter,
670a50eb 896 expressionS * ep,
3d3c5039
ILT
897 const char *name,
898 const char *fmt,
899 ...)
900#else /* ! defined (NO_STDARG) */
901static void
902macro_build (counter, ep, name, fmt, va_alist)
903 int *counter;
904 expressionS *ep;
905 const char *name;
906 const char *fmt;
907 va_dcl
908#endif /* ! defined (NO_STDARG) */
909{
670a50eb
ILT
910 struct mips_cl_insn insn;
911 bfd_reloc_code_real_type r;
912 va_list args;
3d3c5039
ILT
913
914#ifndef NO_STDARG
670a50eb 915 va_start (args, fmt);
3d3c5039 916#else
670a50eb 917 va_start (args);
3d3c5039
ILT
918#endif
919
670a50eb
ILT
920 /*
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...
924 */
925 if (mips_warn_about_macros && *counter == 1)
926 as_warn ("Macro instruction expanded into multiple instructions");
927
928 *counter += 1; /* bump instruction counter */
929
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);
934
935 while (strcmp (fmt, insn.insn_mo->args) != 0)
936 {
937 ++insn.insn_mo;
938 assert (insn.insn_mo->name);
939 assert (strcmp (name, insn.insn_mo->name) == 0);
3d3c5039 940 }
670a50eb
ILT
941 assert (insn.insn_mo->pinfo != INSN_MACRO);
942 insn.insn_opcode = insn.insn_mo->match;
943 for (;;)
944 {
945 switch (*fmt++)
946 {
3d3c5039 947 case '\0':
670a50eb 948 break;
3d3c5039
ILT
949
950 case ',':
951 case '(':
952 case ')':
670a50eb 953 continue;
3d3c5039
ILT
954
955 case 't':
956 case 'w':
918692a5 957 case 'E':
670a50eb
ILT
958 insn.insn_opcode |= va_arg (args, int) << 16;
959 continue;
3d3c5039
ILT
960
961 case 'c':
962 case 'T':
963 case 'W':
670a50eb
ILT
964 insn.insn_opcode |= va_arg (args, int) << 16;
965 continue;
3d3c5039
ILT
966
967 case 'd':
918692a5 968 case 'G':
670a50eb
ILT
969 insn.insn_opcode |= va_arg (args, int) << 11;
970 continue;
3d3c5039
ILT
971
972 case 'V':
973 case 'S':
670a50eb
ILT
974 insn.insn_opcode |= va_arg (args, int) << 11;
975 continue;
3d3c5039
ILT
976
977 case '<':
670a50eb
ILT
978 insn.insn_opcode |= va_arg (args, int) << 6;
979 continue;
3d3c5039
ILT
980
981 case 'D':
670a50eb
ILT
982 insn.insn_opcode |= va_arg (args, int) << 6;
983 continue;
3d3c5039 984
918692a5
ILT
985 case 'B':
986 insn.insn_opcode |= va_arg (args, int) << 6;
987 continue;
988
3d3c5039
ILT
989 case 'b':
990 case 's':
991 case 'r':
992 case 'v':
670a50eb
ILT
993 insn.insn_opcode |= va_arg (args, int) << 21;
994 continue;
3d3c5039
ILT
995
996 case 'i':
997 case 'j':
998 case 'o':
670a50eb
ILT
999 r = BFD_RELOC_LO16;
1000 continue;
3d3c5039
ILT
1001
1002 case 'p':
670a50eb
ILT
1003 assert (ep != NULL);
1004 /*
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).
1010 */
5ac34ac3 1011 if (ep->X_op == O_constant)
670a50eb
ILT
1012 {
1013 insn.insn_opcode |= (ep->X_add_number >> 2) & 0xffff;
1014 ep = NULL;
1015 }
1016 else
1017 r = BFD_RELOC_16_PCREL_S2;
1018 continue;
3d3c5039
ILT
1019
1020 default:
670a50eb 1021 internalError ();
3d3c5039 1022 }
670a50eb 1023 break;
3d3c5039 1024 }
670a50eb
ILT
1025 va_end (args);
1026 assert (r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
1027
1028 /* Use GP relative addressing if possible. */
1029 if (r == BFD_RELOC_LO16
1030 && gp_reference (ep))
1031 r = BFD_RELOC_MIPS_GPREL;
1032
1033 append_insn (&insn, ep, r);
3d3c5039
ILT
1034}
1035
1036/*
1037 * Generate a "lui" instruction.
1038 */
1039static void
1040macro_build_lui (counter, ep, regnum)
1041 int *counter;
1042 expressionS *ep;
1043 int regnum;
1044{
670a50eb
ILT
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";
1050
1051 high_expr = *ep;
1052
5ac34ac3 1053 if (high_expr.X_op == O_constant)
670a50eb
ILT
1054 {
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;
1061 }
1062 else
1063 r = BFD_RELOC_HI16_S;
1064
1065 /*
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...
1069 */
1070 if (mips_warn_about_macros && *counter == 1)
1071 as_warn ("Macro instruction expanded into multiple instructions");
1072
1073 *counter += 1; /* bump instruction counter */
1074
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);
1079
1080 insn.insn_opcode = insn.insn_mo->match | (regnum << 16);
1081 if (r == BFD_RELOC_UNUSED)
1082 {
1083 insn.insn_opcode |= high_expr.X_add_number;
1084 append_insn (&insn, NULL, r);
1085 }
1086 else
1087 append_insn (&insn, &high_expr, r);
3d3c5039
ILT
1088}
1089
1090/* set_at()
1091 * Generates code to set the $at register to true (one)
1092 * if reg is less than the immediate expression.
1093 */
1094static void
1095set_at (counter, reg)
1096 int *counter;
1097 int reg;
1098{
1099
670a50eb
ILT
1100 switch (imm_expr.X_add_number & 0xffff8000)
1101 {
1102 case 0:
1103 case 0xffff8000:
1104 macro_build (counter, &imm_expr, "slti", "t,r,j", AT, reg);
1105 return;
3d3c5039 1106
670a50eb
ILT
1107 case 0x8000:
1108 macro_build (counter, &imm_expr, "ori", "t,r,i", AT, 0);
1109 break;
3d3c5039 1110
670a50eb
ILT
1111 default:
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);
1115 }
1116 macro_build (counter, NULL, "slt", "d,v,t", AT, reg, AT);
3d3c5039
ILT
1117}
1118
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.
1123 */
1124static void
1125set_at_unsigned (counter, reg)
1126 int *counter;
1127 int reg;
1128{
1129
670a50eb
ILT
1130 switch (imm_expr.X_add_number & 0xffff8000)
1131 {
1132 case 0:
1133 case 0xffff8000:
1134 macro_build (counter, &imm_expr, "sltiu", "t,r,j", AT, reg);
1135 return;
3d3c5039 1136
670a50eb
ILT
1137 case 0x8000:
1138 macro_build (counter, &imm_expr, "ori", "t,r,i", AT, 0);
1139 break;
3d3c5039 1140
670a50eb
ILT
1141 default:
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);
1145 }
1146 macro_build (counter, NULL, "sltu", "d,v,t", AT, reg, AT);
3d3c5039
ILT
1147}
1148
1149static void
1150check_absolute_expr (ip, expr)
1151 struct mips_cl_insn *ip;
1152 expressionS *expr;
1153{
1154
5ac34ac3 1155 if (expr->X_op != O_constant)
670a50eb 1156 as_warn ("Instruction %s requires absolute expression", ip->insn_mo->name);
3d3c5039
ILT
1157}
1158
1159/* load_register()
1160 * This routine generates the least number of instructions neccessary to load
1161 * an absolute expression value into a register.
1162 */
1163static void
1164load_register (counter, ip, reg, ep)
670a50eb
ILT
1165 int *counter;
1166 struct mips_cl_insn *ip;
1167 int reg;
1168 expressionS *ep;
3d3c5039 1169{
670a50eb
ILT
1170 switch (ep->X_add_number & 0xffff8000)
1171 {
1172 case 0:
1173 case 0xffff8000:
1174 macro_build (counter, ep, "addiu", "t,r,j", reg, 0);
1175 break;
1176
1177 case 0x8000:
1178 macro_build (counter, ep, "ori", "t,r,i", reg, 0);
1179 break;
1180
1181 default:
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);
1185 }
3d3c5039
ILT
1186}
1187
1188
1189/*
1190 * Build macros
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
1205 * we're missing.
1206 */
1207static void
1208macro (ip)
1209 struct mips_cl_insn *ip;
1210{
670a50eb
ILT
1211 register int treg, sreg, dreg, breg;
1212 int tempreg;
1213 int mask;
1214 int icnt = 0;
1215 int used_at;
670a50eb
ILT
1216 expressionS expr1;
1217 const char *s;
1218 const char *fmt;
1219
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;
1224
5ac34ac3
ILT
1225 expr1.X_op = O_constant;
1226 expr1.X_op_symbol = NULL;
670a50eb
ILT
1227 expr1.X_add_symbol = NULL;
1228 expr1.X_add_number = 1;
1229
1230 switch (mask)
1231 {
3d3c5039
ILT
1232 case M_ABS:
1233 case M_ABSU:
670a50eb 1234 /*
3d3c5039
ILT
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
1239 <main+12>: nop
1240 */
1241
becfe05e
ILT
1242 mips_emit_delays ();
1243 ++mips_noreorder;
3d3c5039 1244
670a50eb
ILT
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",
1249 dreg, 0, sreg);
3d3c5039 1250
becfe05e 1251 --mips_noreorder;
670a50eb 1252 return;
3d3c5039
ILT
1253
1254 case M_ADD_I:
1255 case M_ADDU_I:
670a50eb
ILT
1256 switch (imm_expr.X_add_number & 0xffff8000)
1257 {
1258 case 0:
1259 case 0xffff8000:
1260 macro_build (&icnt, &imm_expr,
1261 mask == M_ADD_I ? "addi" : "addiu", "t,r,j", treg, sreg);
1262 return;
3d3c5039 1263
670a50eb
ILT
1264 case 0x8000:
1265 macro_build (&icnt, &imm_expr, "ori", "t,r,i", AT, 0);
1266 break;
1267
1268 default:
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);
1272 break;
3d3c5039 1273 }
670a50eb
ILT
1274 macro_build (&icnt, NULL,
1275 mask == M_ADD_I ? "add" : "addu", "d,v,t", treg, sreg, AT);
1276 break;
3d3c5039
ILT
1277
1278 case M_AND_I:
1279 case M_OR_I:
1280 case M_NOR_I:
1281 case M_XOR_I:
670a50eb
ILT
1282 switch (imm_expr.X_add_number & 0xffff8000)
1283 {
3d3c5039
ILT
1284 case 0:
1285 case 0x8000:
670a50eb
ILT
1286 switch (mask)
1287 {
3d3c5039 1288 case M_AND_I:
670a50eb
ILT
1289 macro_build (&icnt, &imm_expr, "andi", "t,r,i", treg, sreg);
1290 return;
3d3c5039 1291 case M_OR_I:
670a50eb
ILT
1292 macro_build (&icnt, &imm_expr, "ori", "t,r,i", treg, sreg);
1293 return;
3d3c5039 1294 case M_NOR_I:
670a50eb
ILT
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);
1297 return;
3d3c5039 1298 case M_XOR_I:
670a50eb
ILT
1299 macro_build (&icnt, &imm_expr, "xori", "t,r,i", treg, sreg);
1300 return;
3d3c5039 1301 default:
670a50eb 1302 internalError ();
3d3c5039
ILT
1303 }
1304
1305 case 0xffff8000:
670a50eb
ILT
1306 macro_build (&icnt, &imm_expr, "addiu", "t,r,j", AT, 0);
1307 break;
3d3c5039
ILT
1308
1309 default:
670a50eb
ILT
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);
3d3c5039 1313 }
670a50eb
ILT
1314 switch (mask)
1315 {
3d3c5039 1316 case M_AND_I:
670a50eb
ILT
1317 macro_build (&icnt, NULL, "and", "d,v,t", treg, sreg, AT);
1318 break;
3d3c5039 1319 case M_OR_I:
670a50eb
ILT
1320 macro_build (&icnt, NULL, "or", "d,v,t", treg, sreg, AT);
1321 break;
3d3c5039 1322 case M_NOR_I:
670a50eb
ILT
1323 macro_build (&icnt, NULL, "nor", "d,v,t", treg, sreg, AT);
1324 break;
3d3c5039 1325 case M_XOR_I:
670a50eb
ILT
1326 macro_build (&icnt, NULL, "xor", "d,v,t", treg, sreg, AT);
1327 break;
3d3c5039 1328 default:
670a50eb 1329 internalError ();
3d3c5039 1330 }
670a50eb 1331 break;
3d3c5039
ILT
1332
1333 case M_BEQ_I:
1334 case M_BNE_I:
670a50eb
ILT
1335 if (imm_expr.X_add_number == 0)
1336 {
1337 macro_build (&icnt, &offset_expr, mask == M_BEQ_I ? "beq" : "bne",
1338 "s,t,p", sreg, 0);
1339 return;
1340 }
1341 load_register (&icnt, ip, AT, &imm_expr);
1342 macro_build (&icnt, &offset_expr, mask == M_BEQ_I ? "beq" : "bne",
1343 "s,t,p", sreg, AT);
1344 break;
3d3c5039
ILT
1345
1346 case M_BGE:
670a50eb
ILT
1347 if (treg == 0)
1348 {
1349 macro_build (&icnt, &offset_expr, "bgez", "s,p", sreg);
1350 return;
3d3c5039 1351 }
9a7d824a
ILT
1352 if (sreg == 0)
1353 {
1354 macro_build (&icnt, &offset_expr, "blez", "s,p", treg);
1355 return;
1356 }
670a50eb
ILT
1357 macro_build (&icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
1358 macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
1359 break;
3d3c5039
ILT
1360
1361 case M_BGT_I:
9a7d824a
ILT
1362 /* check for > max integer */
1363 if (imm_expr.X_add_number == 0x7fffffff)
1364 {
1365 do_false:
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);
1369 return;
1370 }
670a50eb
ILT
1371 imm_expr.X_add_number++;
1372 /* FALLTHROUGH */
9a7d824a 1373
3d3c5039 1374 case M_BGE_I:
670a50eb
ILT
1375 if (imm_expr.X_add_number == 0)
1376 {
1377 macro_build (&icnt, &offset_expr, "bgez", "s,p", sreg);
1378 return;
3d3c5039 1379 }
670a50eb
ILT
1380 if (imm_expr.X_add_number == 1)
1381 {
1382 macro_build (&icnt, &offset_expr, "bgtz", "s,p", sreg);
1383 return;
3d3c5039 1384 }
9a7d824a
ILT
1385 if (imm_expr.X_add_number == 0x80000000)
1386 {
1387 do_true:
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");
1391 return;
1392 }
670a50eb
ILT
1393 set_at (&icnt, sreg);
1394 macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
1395 break;
3d3c5039
ILT
1396
1397 case M_BGEU:
670a50eb 1398 if (treg == 0)
9a7d824a
ILT
1399 goto do_true;
1400 if (sreg == 0)
670a50eb 1401 {
9a7d824a 1402 macro_build (&icnt, &offset_expr, "beq", "s,t,p", 0, treg);
670a50eb 1403 return;
3d3c5039 1404 }
670a50eb
ILT
1405 macro_build (&icnt, NULL, "sltu", "d,v,t", AT, sreg, treg);
1406 macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
1407 break;
3d3c5039 1408
9a7d824a
ILT
1409 case M_BGTU_I:
1410 if (sreg == 0 || imm_expr.X_add_number == 0xffffffff)
1411 goto do_false;
1412 imm_expr.X_add_number++;
1413 /* FALLTHROUGH */
1414
3d3c5039 1415 case M_BGEU_I:
670a50eb 1416 if (imm_expr.X_add_number == 0)
9a7d824a 1417 goto do_true;
670a50eb
ILT
1418 if (imm_expr.X_add_number == 1)
1419 {
1420 macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0);
1421 return;
3d3c5039 1422 }
670a50eb
ILT
1423 set_at_unsigned (&icnt, sreg);
1424 macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
1425 break;
3d3c5039
ILT
1426
1427 case M_BGT:
670a50eb
ILT
1428 if (treg == 0)
1429 {
1430 macro_build (&icnt, &offset_expr, "bgtz", "s,p", sreg);
1431 return;
3d3c5039 1432 }
9a7d824a
ILT
1433 if (sreg == 0)
1434 {
1435 macro_build (&icnt, &offset_expr, "bltz", "s,p", treg);
1436 return;
1437 }
670a50eb
ILT
1438 macro_build (&icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
1439 macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
1440 break;
3d3c5039
ILT
1441
1442 case M_BGTU:
670a50eb
ILT
1443 if (treg == 0)
1444 {
1445 macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0);
1446 return;
3d3c5039 1447 }
9a7d824a
ILT
1448 if (sreg == 0)
1449 goto do_false;
670a50eb
ILT
1450 macro_build (&icnt, NULL, "sltu", "d,v,t", AT, treg, sreg);
1451 macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
1452 break;
3d3c5039 1453
3d3c5039 1454 case M_BLE:
670a50eb
ILT
1455 if (treg == 0)
1456 {
1457 macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
1458 return;
1459 }
9a7d824a
ILT
1460 if (sreg == 0)
1461 {
1462 macro_build (&icnt, &offset_expr, "bgez", "s,p", treg);
1463 return;
1464 }
670a50eb
ILT
1465 macro_build (&icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
1466 macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
1467 break;
3d3c5039
ILT
1468
1469 case M_BLE_I:
9a7d824a
ILT
1470 if (imm_expr.X_add_number == 0x7fffffff)
1471 goto do_true;
1472 imm_expr.X_add_number++;
1473 /* FALLTHROUGH */
1474
1475 case M_BLT_I:
670a50eb
ILT
1476 if (imm_expr.X_add_number == 0)
1477 {
9a7d824a 1478 macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
670a50eb
ILT
1479 return;
1480 }
9a7d824a 1481 if (imm_expr.X_add_number == 1)
670a50eb 1482 {
9a7d824a 1483 macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
670a50eb
ILT
1484 return;
1485 }
670a50eb
ILT
1486 set_at (&icnt, sreg);
1487 macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
1488 break;
3d3c5039
ILT
1489
1490 case M_BLEU:
670a50eb
ILT
1491 if (treg == 0)
1492 {
1493 macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0);
1494 return;
3d3c5039 1495 }
9a7d824a
ILT
1496 if (sreg == 0)
1497 goto do_true;
670a50eb
ILT
1498 macro_build (&icnt, NULL, "sltu", "d,v,t", AT, treg, sreg);
1499 macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
1500 break;
3d3c5039
ILT
1501
1502 case M_BLEU_I:
9a7d824a
ILT
1503 if (sreg == 0 || imm_expr.X_add_number == 0xffffffff)
1504 goto do_true;
1505 imm_expr.X_add_number++;
1506 /* FALLTHROUGH */
1507
1508 case M_BLTU_I:
670a50eb 1509 if (imm_expr.X_add_number == 0)
9a7d824a
ILT
1510 goto do_false;
1511 if (imm_expr.X_add_number == 1)
670a50eb
ILT
1512 {
1513 macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0);
1514 return;
3d3c5039 1515 }
670a50eb
ILT
1516 set_at_unsigned (&icnt, sreg);
1517 macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
1518 break;
3d3c5039
ILT
1519
1520 case M_BLT:
670a50eb
ILT
1521 if (treg == 0)
1522 {
1523 macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
1524 return;
3d3c5039 1525 }
9a7d824a 1526 if (sreg == 0)
670a50eb 1527 {
9a7d824a 1528 macro_build (&icnt, &offset_expr, "bgtz", "s,p", treg);
670a50eb 1529 return;
3d3c5039 1530 }
9a7d824a 1531 macro_build (&icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
670a50eb
ILT
1532 macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
1533 break;
3d3c5039
ILT
1534
1535 case M_BLTU:
670a50eb 1536 if (treg == 0)
9a7d824a
ILT
1537 goto do_false;
1538 if (sreg == 0)
670a50eb 1539 {
9a7d824a 1540 macro_build (&icnt, &offset_expr, "bne", "s,t,p", 0, treg);
670a50eb
ILT
1541 return;
1542 }
1543 macro_build (&icnt, NULL, "sltu", "d,v,t", AT, sreg, treg);
1544 macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
1545 break;
3d3c5039 1546
3d3c5039
ILT
1547 case M_DIV_3:
1548 case M_REM_3:
670a50eb
ILT
1549 if (treg == 0)
1550 {
1551 as_warn ("Divide by zero.");
1552 macro_build (&icnt, NULL, "break", "c", 7);
1553 return;
1554 }
1555
becfe05e
ILT
1556 mips_emit_delays ();
1557 ++mips_noreorder;
670a50eb
ILT
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);
becfe05e 1573 --mips_noreorder;
670a50eb
ILT
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. */
1576 break;
3d3c5039
ILT
1577
1578 case M_DIV_3I:
1579 case M_DIVU_3I:
1580 case M_REM_3I:
1581 case M_REMU_3I:
670a50eb
ILT
1582 if (imm_expr.X_add_number == 0)
1583 {
1584 as_warn ("Divide by zero.");
1585 macro_build (&icnt, NULL, "break", "c", 7);
1586 return;
1587 }
1588 if (imm_expr.X_add_number == 1)
1589 {
1590 if (mask == (int) M_DIV_3I || mask == (int) M_DIVU_3I)
1591 macro_build (&icnt, NULL, "move", "d,s", dreg, sreg);
3d3c5039 1592 else
670a50eb 1593 macro_build (&icnt, NULL, "move", "d,s", dreg, 0);
3d3c5039
ILT
1594 return;
1595 }
1596
670a50eb
ILT
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);
1600 else
1601 macro_build (&icnt, NULL, "divu", "s,t", sreg, AT);
3d3c5039 1602
670a50eb
ILT
1603 if (mask == (int) M_DIV_3I || mask == (int) M_DIVU_3I)
1604 macro_build (&icnt, NULL, "mflo", "d", dreg);
1605 else
1606 macro_build (&icnt, NULL, "mfhi", "d", dreg);
1607 /* two implicit nop's required for mflo or mfhi */
1608 break;
1609
1610 case M_DIVU_3:
1611 case M_REMU_3:
becfe05e
ILT
1612 mips_emit_delays ();
1613 ++mips_noreorder;
670a50eb
ILT
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);
becfe05e 1619 --mips_noreorder;
670a50eb
ILT
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. */
1622 return;
3d3c5039
ILT
1623
1624 case M_LA:
5ac34ac3 1625 if (offset_expr.X_op == O_constant)
670a50eb
ILT
1626 {
1627 load_register (&icnt, ip, treg, &offset_expr);
1628 return;
3d3c5039 1629 }
670a50eb
ILT
1630 if (gp_reference (&offset_expr))
1631 macro_build (&icnt, &offset_expr, "addiu", "t,r,j", treg, GP);
1632 else
1633 {
1634 macro_build_lui (&icnt, &offset_expr, treg);
1635 macro_build (&icnt, &offset_expr, "addiu", "t,r,j", treg, treg);
1636 }
1637 return;
3d3c5039
ILT
1638
1639 case M_LA_AB:
670a50eb 1640 tempreg = (breg == treg) ? AT : treg;
5ac34ac3 1641 if (offset_expr.X_op == O_constant)
670a50eb
ILT
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);
1645 else
1646 {
1647 macro_build_lui (&icnt, &offset_expr, tempreg);
1648 macro_build (&icnt, &offset_expr, "addiu", "t,r,j", tempreg, tempreg);
1649 }
1650 if (breg != 0)
1651 macro_build (&icnt, NULL, "addu", "d,v,t", treg, tempreg, breg);
1652 if (breg == treg)
1653 break;
1654 return;
3d3c5039
ILT
1655
1656 case M_LB_AB:
670a50eb
ILT
1657 s = "lb";
1658 goto ld;
3d3c5039 1659 case M_LBU_AB:
670a50eb
ILT
1660 s = "lbu";
1661 goto ld;
3d3c5039 1662 case M_LH_AB:
670a50eb
ILT
1663 s = "lh";
1664 goto ld;
3d3c5039 1665 case M_LHU_AB:
670a50eb
ILT
1666 s = "lhu";
1667 goto ld;
3d3c5039 1668 case M_LW_AB:
670a50eb
ILT
1669 s = "lw";
1670 goto ld;
3d3c5039 1671 case M_LWC0_AB:
670a50eb
ILT
1672 s = "lwc0";
1673 goto ld;
3d3c5039 1674 case M_LWC1_AB:
670a50eb
ILT
1675 s = "lwc1";
1676 goto ld;
3d3c5039 1677 case M_LWC2_AB:
670a50eb
ILT
1678 s = "lwc2";
1679 goto ld;
3d3c5039 1680 case M_LWC3_AB:
670a50eb
ILT
1681 s = "lwc3";
1682 goto ld;
3d3c5039 1683 case M_LWL_AB:
670a50eb
ILT
1684 s = "lwl";
1685 goto ld;
3d3c5039 1686 case M_LWR_AB:
670a50eb 1687 s = "lwr";
3d3c5039 1688 ld:
670a50eb
ILT
1689 if (breg == treg || mask == M_LWC1_AB)
1690 {
1691 tempreg = AT;
1692 used_at = 1;
1693 }
1694 else
1695 {
1696 tempreg = treg;
1697 used_at = 0;
1698 }
1699 goto ld_st;
3d3c5039 1700 case M_SB_AB:
670a50eb
ILT
1701 s = "sb";
1702 goto st;
3d3c5039 1703 case M_SH_AB:
670a50eb
ILT
1704 s = "sh";
1705 goto st;
3d3c5039 1706 case M_SW_AB:
670a50eb
ILT
1707 s = "sw";
1708 goto st;
3d3c5039 1709 case M_SWC0_AB:
670a50eb
ILT
1710 s = "swc0";
1711 goto st;
3d3c5039 1712 case M_SWC1_AB:
670a50eb
ILT
1713 s = "swc1";
1714 goto st;
3d3c5039 1715 case M_SWC2_AB:
670a50eb
ILT
1716 s = "swc2";
1717 goto st;
3d3c5039 1718 case M_SWC3_AB:
670a50eb
ILT
1719 s = "swc3";
1720 goto st;
3d3c5039 1721 case M_SWL_AB:
670a50eb
ILT
1722 s = "swl";
1723 goto st;
3d3c5039 1724 case M_SWR_AB:
670a50eb 1725 s = "swr";
3d3c5039 1726 st:
670a50eb
ILT
1727 tempreg = AT;
1728 used_at = 1;
3d3c5039 1729 ld_st:
670a50eb
ILT
1730 if (mask == M_LWC1_AB || mask == M_SWC1_AB)
1731 fmt = "T,o(b)";
1732 else
1733 fmt = "t,o(b)";
1734 if (gp_reference (&offset_expr))
1735 {
1736 if (breg == 0)
1737 {
1738 macro_build (&icnt, &offset_expr, s, fmt, treg, GP);
1739 return;
1740 }
1741 macro_build (&icnt, (expressionS *) NULL, "addu", "d,v,t",
1742 tempreg, breg, GP);
1743 }
1744 else
1745 {
1746 macro_build_lui (&icnt, &offset_expr, tempreg);
1747 if (breg != 0)
1748 macro_build (&icnt, NULL, "addu", "d,v,t", tempreg, tempreg, breg);
1749 }
1750 macro_build (&icnt, &offset_expr, s, fmt, treg, tempreg);
1751 if (used_at)
1752 break;
1753 return;
3d3c5039
ILT
1754
1755 case M_LI:
670a50eb
ILT
1756 load_register (&icnt, ip, treg, &imm_expr);
1757 return;
3d3c5039
ILT
1758
1759 case M_LI_D:
670a50eb 1760 /*
3d3c5039
ILT
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)
1764 .data
1765 <foo>:
1766 .float 3.133435
1767 */
670a50eb
ILT
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);
1775 break;
3d3c5039
ILT
1776
1777 case M_LI_DD:
670a50eb 1778 /*
3d3c5039
ILT
1779 0x4003a0 <main>: lwc1 $f0,-32752($gp)
1780 0x4003a4 <main+4>: lwc1 $f1,-32748($gp)
1781 0x4003a8 <main+8>: nop
1782 */
670a50eb
ILT
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);
1788 break;
3d3c5039
ILT
1789
1790 case M_L_DOB:
9a7d824a
ILT
1791 /* Even on a big endian machine $fn comes before $fn+1. We have
1792 to adjust when loading from memory. */
9a7d824a
ILT
1793 macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
1794 byte_order == LITTLE_ENDIAN ? treg : treg + 1,
1795 breg);
670a50eb 1796 offset_expr.X_add_number += 4;
9a7d824a
ILT
1797 macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
1798 byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
1799 breg);
670a50eb 1800 return;
3d3c5039
ILT
1801
1802 case M_L_DAB:
670a50eb
ILT
1803 /*
1804 * The MIPS assembler seems to check for X_add_number not
1805 * being double aligned and generating:
1806 * lui at,%hi(foo+1)
1807 * addu at,at,v1
1808 * addiu at,at,%lo(foo+1)
1809 * lwc1 f2,0(at)
1810 * lwc1 f3,4(at)
1811 * But, the resulting address is the same after relocation so why
1812 * generate the extra instruction?
1813 */
1814 if (gp_reference (&offset_expr))
1815 {
1816 if (breg == 0)
1817 tempreg = GP;
1818 else
1819 {
1820 macro_build (&icnt, &offset_expr, "addu", "d,v,t", AT, breg, GP);
1821 tempreg = AT;
1822 }
1823 }
1824 else
1825 {
1826 macro_build_lui (&icnt, &offset_expr, AT);
1827 if (breg != 0)
1828 macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg);
1829 tempreg = AT;
1830 }
9a7d824a
ILT
1831 /* Even on a big endian machine $fn comes before $fn+1. We have
1832 to adjust when loading from memory. */
9a7d824a
ILT
1833 macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
1834 byte_order == LITTLE_ENDIAN ? treg : treg + 1,
1835 tempreg);
670a50eb 1836 offset_expr.X_add_number += 4;
9a7d824a
ILT
1837 macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
1838 byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
1839 tempreg);
670a50eb 1840 if (tempreg == AT)
3d3c5039 1841 break;
670a50eb 1842 return;
3d3c5039
ILT
1843
1844 case M_LD_OB:
670a50eb
ILT
1845 s = "lw";
1846 goto sd_ob;
3d3c5039 1847 case M_SD_OB:
670a50eb 1848 s = "sw";
3d3c5039 1849 sd_ob:
670a50eb
ILT
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);
1853 return;
3d3c5039
ILT
1854
1855 case M_LD_AB:
670a50eb
ILT
1856 s = "lw";
1857 if (breg == treg)
1858 {
1859 tempreg = AT;
1860 used_at = 1;
1861 }
1862 else
1863 {
1864 tempreg = treg;
1865 used_at = 0;
1866 }
1867 goto sd_ab;
3d3c5039 1868 case M_SD_AB:
670a50eb
ILT
1869 s = "sw";
1870 tempreg = AT;
1871 used_at = 1;
3d3c5039 1872 sd_ab:
670a50eb
ILT
1873 if (gp_reference (&offset_expr))
1874 {
1875 if (breg == 0)
1876 {
1877 tempreg = GP;
1878 used_at = 0;
1879 }
1880 else
1881 macro_build (&icnt, (expressionS *) NULL, "addu", "d,v,t",
1882 tempreg, breg, GP);
1883 }
1884 else
1885 {
1886 macro_build_lui (&icnt, &offset_expr, tempreg);
1887 if (breg != 0)
1888 macro_build (&icnt, NULL, "addu", "d,v,t", tempreg, tempreg, breg);
1889 }
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);
1893 if (used_at)
1894 break;
1895 return;
3d3c5039
ILT
1896
1897 case M_MUL:
670a50eb
ILT
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 */
1901 return;
3d3c5039
ILT
1902
1903 case M_MUL_I:
670a50eb
ILT
1904 /*
1905 * The mips assembler some times generates shifts and adds.
1906 * Im not trying to be that fancy. GCC should do this for us
1907 * anyway.
1908 */
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 */
1913 break;
3d3c5039
ILT
1914
1915 case M_ROL:
670a50eb
ILT
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);
1920 break;
3d3c5039
ILT
1921
1922 case M_ROL_I:
670a50eb
ILT
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);
1928 break;
3d3c5039
ILT
1929
1930 case M_ROR:
670a50eb
ILT
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);
1935 break;
3d3c5039
ILT
1936
1937 case M_ROR_I:
670a50eb
ILT
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);
1943 break;
3d3c5039
ILT
1944
1945 case M_S_DOB:
9a7d824a
ILT
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,
1950 breg);
670a50eb 1951 offset_expr.X_add_number += 4;
9a7d824a
ILT
1952 macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
1953 byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
1954 breg);
670a50eb 1955 return;
3d3c5039
ILT
1956
1957 case M_S_DAB:
670a50eb
ILT
1958 if (gp_reference (&offset_expr))
1959 {
1960 if (breg == 0)
1961 tempreg = GP;
1962 else
1963 {
1964 macro_build (&icnt, (expressionS *) NULL, "addu", "d,v,t",
1965 AT, breg, GP);
1966 tempreg = AT;
1967 }
1968 }
1969 else
1970 {
1971 macro_build_lui (&icnt, &offset_expr, AT);
1972 if (breg != 0)
1973 macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg);
1974 tempreg = AT;
1975 }
9a7d824a
ILT
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,
1980 tempreg);
670a50eb 1981 offset_expr.X_add_number += 4;
9a7d824a
ILT
1982 macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
1983 byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
1984 tempreg);
670a50eb 1985 if (tempreg == AT)
3d3c5039 1986 break;
670a50eb 1987 return;
3d3c5039
ILT
1988
1989 case M_SEQ:
670a50eb
ILT
1990 if (sreg == 0)
1991 macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, treg);
1992 else if (treg == 0)
1993 macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, sreg);
1994 else
1995 {
1996 macro_build (&icnt, NULL, "xor", "d,v,t", dreg, sreg, treg);
1997 macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, dreg);
3d3c5039 1998 }
670a50eb 1999 return;
3d3c5039
ILT
2000
2001 case M_SEQ_I:
670a50eb
ILT
2002 if (imm_expr.X_add_number == 0)
2003 {
2004 macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, sreg);
2005 return;
3d3c5039 2006 }
670a50eb
ILT
2007 if (sreg == 0)
2008 {
9a7d824a
ILT
2009 as_warn ("Instruction %s: result is always false",
2010 ip->insn_mo->name);
670a50eb
ILT
2011 macro_build (&icnt, NULL, "move", "d,s", dreg, 0);
2012 return;
3d3c5039 2013 }
670a50eb
ILT
2014 switch (imm_expr.X_add_number & 0xffff8000)
2015 {
3d3c5039
ILT
2016 case 0:
2017 case 0x8000:
670a50eb
ILT
2018 macro_build (&icnt, &imm_expr, "xori", "t,r,i", dreg, sreg);
2019 used_at = 0;
2020 break;
3d3c5039
ILT
2021
2022 case 0xffff8000:
670a50eb
ILT
2023 if (imm_expr.X_add_number != -32768)
2024 {
2025 imm_expr.X_add_number = -imm_expr.X_add_number;
2026 macro_build (&icnt, &imm_expr, "addiu", "t,r,j", dreg, sreg);
2027 used_at = 0;
2028 break;
3d3c5039 2029 }
670a50eb 2030 /* FALLTHROUGH */
3d3c5039
ILT
2031
2032 default:
670a50eb
ILT
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);
2037 used_at = 1;
2038 }
2039 macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, dreg);
2040 if (used_at)
2041 break;
2042 return;
3d3c5039
ILT
2043
2044 case M_SGE: /* sreg >= treg <==> not (sreg < treg) */
670a50eb
ILT
2045 s = "slt";
2046 goto sge;
3d3c5039 2047 case M_SGEU:
670a50eb 2048 s = "sltu";
3d3c5039 2049 sge:
670a50eb
ILT
2050 macro_build (&icnt, NULL, s, "d,v,t", dreg, sreg, treg);
2051 macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg);
2052 return;
3d3c5039 2053
670a50eb 2054 case M_SGE_I: /* sreg >= I <==> not (sreg < I) */
3d3c5039 2055 case M_SGEU_I:
670a50eb
ILT
2056 if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32769)
2057 {
2058 macro_build (&icnt, &expr1,
2059 mask == M_SGE_I ? "slti" : "sltiu", "t,r,j", dreg, sreg);
2060 used_at = 0;
2061 }
2062 else
2063 {
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);
2067 used_at = 1;
2068 }
2069 macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg);
2070 if (used_at)
2071 break;
2072 return;
3d3c5039
ILT
2073
2074 case M_SGT: /* sreg > treg <==> treg < sreg */
670a50eb
ILT
2075 s = "slt";
2076 goto sgt;
3d3c5039 2077 case M_SGTU:
670a50eb 2078 s = "sltu";
3d3c5039 2079 sgt:
670a50eb
ILT
2080 macro_build (&icnt, NULL, s, "d,v,t", dreg, treg, sreg);
2081 return;
3d3c5039 2082
670a50eb
ILT
2083 case M_SGT_I: /* sreg > I <==> I < sreg */
2084 s = "slt";
2085 goto sgti;
3d3c5039 2086 case M_SGTU_I:
670a50eb 2087 s = "sltu";
3d3c5039 2088 sgti:
670a50eb
ILT
2089 load_register (&icnt, ip, AT, &imm_expr);
2090 macro_build (&icnt, NULL, s, "d,v,t", dreg, AT, sreg);
2091 break;
3d3c5039 2092
670a50eb
ILT
2093 case M_SLE: /* sreg <= treg <==> treg >= sreg <==> not (treg < sreg) */
2094 s = "slt";
2095 goto sle;
3d3c5039 2096 case M_SLEU:
670a50eb 2097 s = "sltu";
3d3c5039 2098 sle:
670a50eb 2099 macro_build (&icnt, NULL, s, "d,v,t", dreg, treg, sreg);
9a7d824a 2100 macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg);
670a50eb 2101 return;
3d3c5039 2102
670a50eb
ILT
2103 case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */
2104 s = "slt";
2105 goto slei;
3d3c5039 2106 case M_SLEU_I:
670a50eb 2107 s = "sltu";
3d3c5039 2108 slei:
670a50eb
ILT
2109 load_register (&icnt, ip, AT, &imm_expr);
2110 macro_build (&icnt, NULL, s, "d,v,t", dreg, AT, sreg);
9a7d824a 2111 macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg);
670a50eb 2112 break;
3d3c5039
ILT
2113
2114 case M_SLT_I:
670a50eb
ILT
2115 if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32769)
2116 {
2117 macro_build (&icnt, &imm_expr, "slti", "t,r,j", dreg, sreg);
2118 return;
3d3c5039 2119 }
670a50eb
ILT
2120 load_register (&icnt, ip, AT, &imm_expr);
2121 macro_build (&icnt, NULL, "slt", "d,v,t", dreg, sreg, AT);
2122 break;
3d3c5039
ILT
2123
2124 case M_SLTU_I:
670a50eb
ILT
2125 if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32769)
2126 {
2127 macro_build (&icnt, &imm_expr, "sltiu", "t,r,j", dreg, sreg);
2128 return;
3d3c5039 2129 }
670a50eb
ILT
2130 load_register (&icnt, ip, AT, &imm_expr);
2131 macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, sreg, AT);
2132 break;
3d3c5039
ILT
2133
2134 case M_SNE:
670a50eb
ILT
2135 if (sreg == 0)
2136 macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, treg);
2137 else if (treg == 0)
2138 macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, sreg);
2139 else
2140 {
2141 macro_build (&icnt, NULL, "xor", "d,v,t", dreg, sreg, treg);
2142 macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg);
3d3c5039 2143 }
670a50eb 2144 return;
3d3c5039
ILT
2145
2146 case M_SNE_I:
670a50eb
ILT
2147 if (imm_expr.X_add_number == 0)
2148 {
2149 macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, sreg);
2150 return;
3d3c5039 2151 }
670a50eb
ILT
2152 if (sreg == 0)
2153 {
9a7d824a
ILT
2154 as_warn ("Instruction %s: result is always true",
2155 ip->insn_mo->name);
670a50eb
ILT
2156 macro_build (&icnt, &expr1, "addiu", "t,r,j", dreg, 0);
2157 return;
3d3c5039 2158 }
670a50eb
ILT
2159 switch (imm_expr.X_add_number & 0xffff8000)
2160 {
3d3c5039
ILT
2161 case 0:
2162 case 0x8000:
670a50eb
ILT
2163 macro_build (&icnt, &imm_expr, "xori", "t,r,i", dreg, sreg);
2164 used_at = 0;
2165 break;
3d3c5039
ILT
2166
2167 case 0xffff8000:
670a50eb
ILT
2168 if (imm_expr.X_add_number != -32768)
2169 {
2170 imm_expr.X_add_number = -imm_expr.X_add_number;
2171 macro_build (&icnt, &imm_expr, "addiu", "t,r,j", dreg, sreg);
2172 used_at = 0;
2173 break;
3d3c5039 2174 }
670a50eb 2175 /* FALLTHROUGH */
3d3c5039
ILT
2176
2177 default:
670a50eb
ILT
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);
2182 used_at = 1;
2183 }
2184 macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg);
2185 if (used_at)
2186 break;
2187 return;
3d3c5039
ILT
2188
2189 case M_SUB_I:
670a50eb
ILT
2190 if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32768)
2191 {
2192 imm_expr.X_add_number = -imm_expr.X_add_number;
2193 macro_build (&icnt, &imm_expr, "addi", "t,r,j", dreg, sreg);
2194 return;
3d3c5039 2195 }
670a50eb
ILT
2196 load_register (&icnt, ip, AT, &imm_expr);
2197 macro_build (&icnt, NULL, "sub", "d,v,t", dreg, sreg, AT);
2198 break;
3d3c5039
ILT
2199
2200 case M_SUBU_I:
670a50eb
ILT
2201 if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32768)
2202 {
2203 imm_expr.X_add_number = -imm_expr.X_add_number;
2204 macro_build (&icnt, &imm_expr, "addiu", "t,r,j", dreg, sreg);
2205 return;
3d3c5039 2206 }
670a50eb
ILT
2207 load_register (&icnt, ip, AT, &imm_expr);
2208 macro_build (&icnt, NULL, "subu", "d,v,t", dreg, sreg, AT);
2209 break;
3d3c5039
ILT
2210
2211 case M_TRUNCWD:
2212 case M_TRUNCWS:
670a50eb
ILT
2213 sreg = (ip->insn_opcode >> 11) & 0x1f; /* floating reg */
2214 dreg = (ip->insn_opcode >> 06) & 0x1f; /* floating reg */
2215
2216 /*
2217 * Is the double cfc1 instruction a bug in the mips assembler;
2218 * or is there a reason for it?
2219 */
becfe05e
ILT
2220 mips_emit_delays ();
2221 ++mips_noreorder;
918692a5
ILT
2222 macro_build (&icnt, NULL, "cfc1", "t,G", treg, 31);
2223 macro_build (&icnt, NULL, "cfc1", "t,G", treg, 31);
670a50eb
ILT
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);
918692a5 2229 macro_build (&icnt, NULL, "ctc1", "t,G", AT, 31);
670a50eb
ILT
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);
918692a5 2233 macro_build (&icnt, NULL, "ctc1", "t,G", treg, 31);
670a50eb 2234 macro_build (&icnt, NULL, "nop", "");
becfe05e 2235 --mips_noreorder;
670a50eb 2236 break;
3d3c5039
ILT
2237
2238 case M_ULH:
670a50eb
ILT
2239 s = "lb";
2240 goto ulh;
3d3c5039 2241 case M_ULHU:
670a50eb 2242 s = "lbu";
3d3c5039 2243 ulh:
670a50eb
ILT
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);
2251 break;
3d3c5039
ILT
2252
2253 case M_ULW:
670a50eb
ILT
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);
2259 return;
3d3c5039
ILT
2260
2261 case M_ULH_A:
2262 case M_ULHU_A:
2263 case M_ULW_A:
5ac34ac3 2264 if (offset_expr.X_op == O_constant)
670a50eb
ILT
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);
2268 else
2269 {
2270 macro_build_lui (&icnt, &offset_expr, AT);
2271 macro_build (&icnt, &offset_expr, "addiu", "t,r,j", AT, AT);
3d3c5039 2272 }
670a50eb
ILT
2273 if (mask == M_ULW_A)
2274 {
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);
2279 }
2280 else
2281 {
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);
2288 }
2289 break;
3d3c5039
ILT
2290
2291 case M_USH:
670a50eb
ILT
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);
2296 break;
3d3c5039
ILT
2297
2298 case M_USW:
670a50eb
ILT
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);
2303 return;
3d3c5039
ILT
2304
2305 case M_USH_A:
2306 case M_USW_A:
5ac34ac3 2307 if (offset_expr.X_op == O_constant)
670a50eb
ILT
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);
2311 else
2312 {
2313 macro_build_lui (&icnt, &offset_expr, AT);
2314 macro_build (&icnt, &offset_expr, "addiu", "t,r,j", AT, AT);
3d3c5039 2315 }
670a50eb
ILT
2316 if (mask == M_USW_A)
2317 {
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);
2322 }
2323 else
2324 {
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);
2334 }
2335 break;
3d3c5039
ILT
2336
2337 default:
670a50eb 2338 as_bad ("Macro %s not implemented yet", ip->insn_mo->name);
3d3c5039 2339 }
670a50eb
ILT
2340 if (mips_noat)
2341 as_warn ("Macro used $at after \".set noat\"");
3d3c5039
ILT
2342}
2343
2344
2345/*
2346This routine assembles an instruction into its binary format. As a side
2347effect it sets one of the global variables imm_reloc or offset_reloc to the
2348type of relocation to do if one of the operands is an address expression.
2349*/
2350static void
2351mips_ip (str, ip)
2352 char *str;
2353 struct mips_cl_insn *ip;
2354{
670a50eb
ILT
2355 char *s;
2356 const char *args;
2357 char c;
2358 struct mips_opcode *insn;
2359 char *argsStart;
2360 unsigned int regno;
2361 unsigned int lastregno = 0;
2362 char *s_reset;
2363
2364 insn_error = NULL;
2365
2366 for (s = str; islower (*s) || (*s >= '0' && *s <= '3') || *s == '.'; ++s)
2367 continue;
2368 switch (*s)
2369 {
3d3c5039 2370 case '\0':
670a50eb 2371 break;
3d3c5039
ILT
2372
2373 case ' ':
670a50eb
ILT
2374 *s++ = '\0';
2375 break;
3d3c5039
ILT
2376
2377 default:
670a50eb
ILT
2378 as_warn ("Unknown opcode: `%s'", str);
2379 exit (1);
3d3c5039 2380 }
670a50eb
ILT
2381 if ((insn = (struct mips_opcode *) hash_find (op_hash, str)) == NULL)
2382 {
2383 as_warn ("`%s' not in hash table.", str);
2384 insn_error = "ERROR: Unrecognized opcode";
2385 return;
3d3c5039 2386 }
670a50eb
ILT
2387 argsStart = s;
2388 for (;;)
2389 {
2390 assert (strcmp (insn->name, str) == 0);
2391 ip->insn_mo = insn;
2392 ip->insn_opcode = insn->match;
2393 for (args = insn->args;; ++args)
2394 {
2395 if (*s == ' ')
2396 ++s;
2397 switch (*args)
2398 {
2399 case '\0': /* end of args */
2400 if (*s == '\0')
2401 return;
2402 break;
3d3c5039
ILT
2403
2404 case ',':
670a50eb
ILT
2405 if (*s++ == *args)
2406 continue;
2407 s--;
2408 switch (*++args)
2409 {
3d3c5039
ILT
2410 case 'r':
2411 case 'v':
670a50eb
ILT
2412 ip->insn_opcode |= lastregno << 21;
2413 continue;
3d3c5039
ILT
2414
2415 case 'w':
2416 case 'W':
670a50eb
ILT
2417 ip->insn_opcode |= lastregno << 16;
2418 continue;
3d3c5039
ILT
2419
2420 case 'V':
670a50eb
ILT
2421 ip->insn_opcode |= lastregno << 11;
2422 continue;
3d3c5039 2423 }
670a50eb 2424 break;
3d3c5039
ILT
2425
2426 case '(':
670a50eb
ILT
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');
2433 if (*s == '\0')
2434 return;
3d3c5039 2435
670a50eb
ILT
2436 case ')': /* these must match exactly */
2437 if (*s++ == *args)
3d3c5039 2438 continue;
670a50eb
ILT
2439 break;
2440
2441 case '<': /* must be at least one digit */
2442 /*
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.
2447 */
2448 my_getExpression (&imm_expr, s);
2449 check_absolute_expr (ip, &imm_expr);
2450 if ((unsigned long) imm_expr.X_add_number > 31)
2451 {
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;
2455 }
2456 ip->insn_opcode |= imm_expr.X_add_number << 6;
5ac34ac3 2457 imm_expr.X_op = O_absent;
670a50eb
ILT
2458 s = expr_end;
2459 continue;
2460
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;
5ac34ac3 2467 imm_expr.X_op = O_absent;
670a50eb
ILT
2468 s = expr_end;
2469 continue;
2470
918692a5
ILT
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;
5ac34ac3 2477 imm_expr.X_op = O_absent;
918692a5
ILT
2478 s = expr_end;
2479 continue;
2480
0aa07269
ILT
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))
2485 {
2486 as_warn ("Coproccesor code > 25 bits (%d)",
2487 imm_expr.X_add_number);
2488 imm_expr.X_add_number &= ((1<<25) - 1);
2489 }
2490 ip->insn_opcode |= imm_expr.X_add_number;
2491 imm_expr.X_op = O_absent;
2492 s = expr_end;
2493 continue;
2494
670a50eb
ILT
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 */
918692a5
ILT
2502 case 'E': /* coprocessor target register */
2503 case 'G': /* coprocessor destination register */
670a50eb
ILT
2504 s_reset = s;
2505 if (s[0] == '$')
2506 {
2507 if (isdigit (s[1]))
2508 {
2509 ++s;
2510 regno = 0;
2511 do
2512 {
2513 regno *= 10;
2514 regno += *s - '0';
2515 ++s;
2516 }
2517 while (isdigit (*s));
0aa07269
ILT
2518 if (regno > 31)
2519 as_bad ("Invalid register number (%d)", regno);
670a50eb 2520 }
0aa07269 2521 else if (*args != 'E' && *args != 'G')
670a50eb 2522 {
0aa07269
ILT
2523 if (s[1] == 'f' && s[2] == 'p')
2524 {
2525 s += 3;
2526 regno = 30;
2527 }
2528 else if (s[1] == 's' && s[2] == 'p')
2529 {
2530 s += 3;
2531 regno = 29;
2532 }
2533 else if (s[1] == 'g' && s[2] == 'p')
2534 {
2535 s += 3;
2536 regno = 28;
2537 }
2538 else if (s[1] == 'a' && s[2] == 't')
2539 {
2540 s += 3;
2541 regno = 1;
2542 }
2543 else
2544 goto notreg;
2545 if (regno == AT && ! mips_noat)
2546 as_warn ("Used $at without \".set noat\"");
670a50eb 2547 }
670a50eb
ILT
2548 c = *args;
2549 if (*s == ' ')
2550 s++;
2551 if (args[1] != *s)
2552 {
2553 if (c == 'r' || c == 'v' || c == 'w')
2554 {
2555 regno = lastregno;
2556 s = s_reset;
2557 args++;
2558 }
2559 }
2560 switch (c)
2561 {
3d3c5039
ILT
2562 case 'r':
2563 case 's':
2564 case 'v':
2565 case 'b':
670a50eb
ILT
2566 ip->insn_opcode |= regno << 21;
2567 break;
3d3c5039 2568 case 'd':
918692a5 2569 case 'G':
670a50eb
ILT
2570 ip->insn_opcode |= regno << 11;
2571 break;
3d3c5039
ILT
2572 case 'w':
2573 case 't':
918692a5 2574 case 'E':
670a50eb 2575 ip->insn_opcode |= regno << 16;
3d3c5039 2576 }
670a50eb
ILT
2577 lastregno = regno;
2578 continue;
3d3c5039
ILT
2579 }
2580 notreg:
670a50eb
ILT
2581 switch (*args++)
2582 {
3d3c5039
ILT
2583 case 'r':
2584 case 'v':
670a50eb
ILT
2585 ip->insn_opcode |= lastregno << 21;
2586 continue;
3d3c5039 2587 case 'w':
670a50eb
ILT
2588 ip->insn_opcode |= lastregno << 16;
2589 continue;
3d3c5039 2590 }
670a50eb 2591 break;
3d3c5039 2592
670a50eb
ILT
2593 case 'D': /* floating point destination register */
2594 case 'S': /* floating point source register */
2595 case 'T': /* floating point target register */
3d3c5039
ILT
2596 case 'V':
2597 case 'W':
670a50eb
ILT
2598 s_reset = s;
2599 if (s[0] == '$' && s[1] == 'f' && isdigit (s[2]))
2600 {
2601 s += 2;
2602 regno = 0;
2603 do
2604 {
2605 regno *= 10;
2606 regno += *s - '0';
2607 ++s;
2608 }
2609 while (isdigit (*s));
2610
2611 if (regno > 31)
2612 as_bad ("Invalid float register number (%d)", regno);
2613
2614 if ((regno & 1) &&
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",
2620 regno);
2621
2622 c = *args;
2623 if (*s == ' ')
2624 s++;
2625 if (args[1] != *s)
2626 {
2627 if (c == 'V' || c == 'W')
2628 {
2629 regno = lastregno;
2630 s = s_reset;
2631 args++;
3d3c5039
ILT
2632 }
2633 }
670a50eb
ILT
2634 switch (c)
2635 {
3d3c5039 2636 case 'D':
670a50eb
ILT
2637 ip->insn_opcode |= regno << 6;
2638 break;
3d3c5039
ILT
2639 case 'V':
2640 case 'S':
670a50eb
ILT
2641 ip->insn_opcode |= regno << 11;
2642 break;
3d3c5039
ILT
2643 case 'W':
2644 case 'T':
670a50eb 2645 ip->insn_opcode |= regno << 16;
3d3c5039 2646 }
670a50eb
ILT
2647 lastregno = regno;
2648 continue;
3d3c5039 2649 }
670a50eb
ILT
2650 switch (*args++)
2651 {
3d3c5039 2652 case 'V':
670a50eb
ILT
2653 ip->insn_opcode |= lastregno << 11;
2654 continue;
3d3c5039 2655 case 'W':
670a50eb
ILT
2656 ip->insn_opcode |= lastregno << 16;
2657 continue;
3d3c5039 2658 }
670a50eb 2659 break;
3d3c5039
ILT
2660
2661 case 'I':
670a50eb
ILT
2662 my_getExpression (&imm_expr, s);
2663 check_absolute_expr (ip, &imm_expr);
2664 s = expr_end;
2665 continue;
3d3c5039
ILT
2666
2667 case 'A':
670a50eb
ILT
2668 my_getExpression (&offset_expr, s);
2669 imm_reloc = BFD_RELOC_32;
2670 s = expr_end;
2671 continue;
3d3c5039
ILT
2672
2673 case 'F':
670a50eb
ILT
2674 as_bad ("Floating point constants only implemented for pseudo ops.");
2675 continue;
2676
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);
2681 if (c)
2682 {
2683 if (c != 'l')
2684 {
5ac34ac3 2685 if (imm_expr.X_op == O_constant)
670a50eb
ILT
2686 imm_expr.X_add_number =
2687 (imm_expr.X_add_number >> 16) & 0xffff;
2688 else if (c == 'h')
2689 imm_reloc = BFD_RELOC_HI16_S;
2690 else
2691 imm_reloc = BFD_RELOC_HI16;
3d3c5039 2692 }
670a50eb
ILT
2693 }
2694 else
2695 check_absolute_expr (ip, &imm_expr);
2696 if (*args == 'i')
2697 {
2698 if ((unsigned long) imm_expr.X_add_number > 65535)
99c24539
ILT
2699 {
2700 if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
2701 !strcmp (insn->name, insn[1].name))
2702 break;
2703 as_bad ("16 bit expression not in range 0..65535");
2704 }
670a50eb
ILT
2705 }
2706 else
2707 {
2708 if (imm_expr.X_add_number < -32768 ||
3d3c5039 2709 imm_expr.X_add_number > 32767)
99c24539
ILT
2710 {
2711 if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
2712 !strcmp (insn->name, insn[1].name))
2713 break;
2714 as_bad ("16 bit expression not in range -32768..32767");
2715 }
3d3c5039 2716 }
670a50eb
ILT
2717 s = expr_end;
2718 continue;
2719
2720 case 'o': /* 16 bit offset */
2721 c = my_getSmallExpression (&offset_expr, s);
2722 /*
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
2725 * code pattern.
2726 */
2727 if ((offset_expr.X_add_symbol
5ac34ac3
ILT
2728 && offset_expr.X_op != O_constant)
2729 || offset_expr.X_op_symbol
670a50eb
ILT
2730 || offset_expr.X_add_number > 32767
2731 || offset_expr.X_add_number < -32768)
2732 break;
3d3c5039 2733
670a50eb
ILT
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;
2738 s = expr_end;
2739 continue;
2740
2741 case 'p': /* pc relative offset */
2742 offset_reloc = BFD_RELOC_16_PCREL_S2;
2743 my_getExpression (&offset_expr, s);
2744 s = expr_end;
2745 continue;
2746
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;
2752 if (c)
2753 {
2754 if (c != 'l')
2755 {
5ac34ac3 2756 if (imm_expr.X_op == O_constant)
670a50eb
ILT
2757 imm_expr.X_add_number =
2758 (imm_expr.X_add_number >> 16) & 0xffff;
2759 else if (c == 'h')
2760 imm_reloc = BFD_RELOC_HI16_S;
2761 else
2762 imm_reloc = BFD_RELOC_HI16;
3d3c5039
ILT
2763 }
2764 }
670a50eb
ILT
2765 s = expr_end;
2766 continue;
3d3c5039 2767
670a50eb
ILT
2768 case 'a': /* 26 bit address */
2769 my_getExpression (&offset_expr, s);
2770 s = expr_end;
2771 offset_reloc = BFD_RELOC_MIPS_JMP;
2772 continue;
3d3c5039
ILT
2773
2774 default:
670a50eb
ILT
2775 fprintf (stderr, "bad char = '%c'\n", *args);
2776 internalError ();
3d3c5039 2777 }
670a50eb 2778 break;
3d3c5039 2779 }
670a50eb
ILT
2780 /* Args don't match. */
2781 if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
2782 !strcmp (insn->name, insn[1].name))
2783 {
2784 ++insn;
2785 s = argsStart;
2786 continue;
3d3c5039 2787 }
670a50eb
ILT
2788 insn_error = "ERROR: Illegal operands";
2789 return;
3d3c5039
ILT
2790 }
2791}
2792
2793#define LP '('
2794#define RP ')'
2795
2796static int
2797my_getSmallExpression (ep, str)
670a50eb
ILT
2798 expressionS *ep;
2799 char *str;
3d3c5039 2800{
670a50eb
ILT
2801 char *sp;
2802 int c = 0;
2803
2804 if (*str == ' ')
2805 str++;
2806 if (*str == LP
2807 || (*str == '%' &&
2808 ((str[1] == 'h' && str[2] == 'i')
2809 || (str[1] == 'H' && str[2] == 'I')
2810 || (str[1] == 'l' && str[2] == 'o'))
2811 && str[3] == LP))
2812 {
2813 if (*str == LP)
2814 c = 0;
2815 else
2816 {
2817 c = str[1];
2818 str += 3;
2819 }
2820
2821 /*
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...)
2826 */
2827 for (sp = str; *sp && *sp != ','; sp++)
2828 ;
2829 if (sp - 4 >= str && sp[-1] == RP)
2830 {
2831 if (isdigit (sp[-2]))
2832 {
2833 for (sp -= 3; sp >= str && isdigit (*sp); sp--)
2834 ;
2835 if (*sp == '$' && sp > str && sp[-1] == LP)
2836 {
2837 sp--;
2838 goto do_it;
3d3c5039 2839 }
670a50eb
ILT
2840 }
2841 else if (sp - 5 >= str
2842 && sp[-5] == LP
2843 && sp[-4] == '$'
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')))
2848 {
2849 sp -= 5;
3d3c5039 2850 do_it:
670a50eb
ILT
2851 if (sp == str)
2852 {
2853 /* no expression means zero offset */
2854 if (c)
2855 {
2856 /* %xx(reg) is an error */
5ac34ac3 2857 ep->X_op = O_absent;
670a50eb 2858 expr_end = str - 3;
3d3c5039 2859 }
670a50eb
ILT
2860 else
2861 {
5ac34ac3 2862 ep->X_op = O_absent;
670a50eb
ILT
2863 expr_end = sp;
2864 }
2865 ep->X_add_symbol = NULL;
5ac34ac3 2866 ep->X_op_symbol = NULL;
670a50eb
ILT
2867 ep->X_add_number = 0;
2868 }
2869 else
2870 {
2871 *sp = '\0';
2872 my_getExpression (ep, str);
2873 *sp = LP;
3d3c5039 2874 }
670a50eb 2875 return c;
3d3c5039
ILT
2876 }
2877 }
2878 }
670a50eb
ILT
2879 my_getExpression (ep, str);
2880 return c; /* => %hi or %lo encountered */
3d3c5039
ILT
2881}
2882
2883static void
2884my_getExpression (ep, str)
670a50eb
ILT
2885 expressionS *ep;
2886 char *str;
3d3c5039 2887{
670a50eb 2888 char *save_in;
670a50eb
ILT
2889
2890 save_in = input_line_pointer;
2891 input_line_pointer = str;
5ac34ac3 2892 expression (ep);
670a50eb
ILT
2893 expr_end = input_line_pointer;
2894 input_line_pointer = save_in;
3d3c5039
ILT
2895}
2896
becfe05e
ILT
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. */
2901
3d3c5039 2902char *
670a50eb 2903md_atof (type, litP, sizeP)
becfe05e 2904 int type;
3d3c5039
ILT
2905 char *litP;
2906 int *sizeP;
2907{
becfe05e
ILT
2908 int prec;
2909 LITTLENUM_TYPE words[4];
2910 char *t;
2911 int i;
2912
2913 switch (type)
2914 {
2915 case 'f':
2916 prec = 2;
2917 break;
2918
2919 case 'd':
2920 prec = 4;
2921 break;
2922
2923 default:
2924 *sizeP = 0;
2925 return "bad call to md_atof";
2926 }
2927
2928 t = atof_ieee (input_line_pointer, type, words);
2929 if (t)
2930 input_line_pointer = t;
2931
2932 *sizeP = prec * 2;
2933
2934 if (byte_order == LITTLE_ENDIAN)
2935 {
2936 for (i = prec - 1; i >= 0; i--)
2937 {
2938 md_number_to_chars (litP, (valueT) words[i], 2);
2939 litP += 2;
2940 }
2941 }
2942 else
2943 {
2944 for (i = 0; i < prec; i++)
2945 {
2946 md_number_to_chars (litP, (valueT) words[i], 2);
2947 litP += 2;
2948 }
2949 }
2950
670a50eb 2951 return NULL;
3d3c5039
ILT
2952}
2953
2954void
2955md_number_to_chars (buf, val, n)
2956 char *buf;
918692a5 2957 valueT val;
3d3c5039
ILT
2958 int n;
2959{
670a50eb
ILT
2960 switch (byte_order)
2961 {
3d3c5039 2962 case LITTLE_ENDIAN:
670a50eb
ILT
2963 switch (n)
2964 {
3d3c5039 2965 case 4:
670a50eb
ILT
2966 *buf++ = val;
2967 *buf++ = val >> 8;
2968 *buf++ = val >> 16;
2969 *buf = val >> 24;
2970 return;
3d3c5039 2971
670a50eb
ILT
2972 case 2:
2973 *buf++ = val;
2974 *buf = val >> 8;
2975 return;
3d3c5039
ILT
2976
2977 case 1:
670a50eb
ILT
2978 *buf = val;
2979 return;
3d3c5039
ILT
2980
2981 default:
670a50eb 2982 internalError ();
3d3c5039
ILT
2983 }
2984
2985 case BIG_ENDIAN:
670a50eb
ILT
2986 switch (n)
2987 {
3d3c5039 2988 case 4:
670a50eb
ILT
2989 *buf++ = val >> 24;
2990 *buf++ = val >> 16;
2991 case 2:
2992 *buf++ = val >> 8;
3d3c5039 2993 case 1:
670a50eb
ILT
2994 *buf = val;
2995 return;
3d3c5039
ILT
2996
2997 default:
670a50eb 2998 internalError ();
3d3c5039
ILT
2999 }
3000
3001 default:
670a50eb 3002 internalError ();
3d3c5039
ILT
3003 }
3004}
3005
3006int
3007md_parse_option (argP, cntP, vecP)
3008 char **argP;
3009 int *cntP;
3010 char ***vecP;
3011{
670a50eb
ILT
3012 /* Accept -nocpp but ignore it. */
3013 if (!strcmp (*argP, "nocpp"))
3014 {
3015 *argP += 5;
3016 return 1;
3017 }
3018
3019 if (strcmp (*argP, "EL") == 0
3020 || strcmp (*argP, "EB") == 0)
3021 {
3022 /* FIXME: This breaks -L -EL. */
3023 flagseen['L'] = 0;
3024 *argP = "";
3025 return 1;
3026 }
3027
4e95866e
ILT
3028 if (**argP == 'O')
3029 {
0aa07269
ILT
3030 if ((*argP)[1] == '0')
3031 mips_optimize = 1;
3032 else
3033 mips_optimize = 2;
3034 return 1;
3035 }
3036
3037 if (**argP == 'g')
3038 {
3039 if ((*argP)[1] == '\0' || (*argP)[1] == '2')
3040 mips_optimize = 0;
4e95866e
ILT
3041 return 1;
3042 }
3043
670a50eb
ILT
3044#ifdef OBJ_ECOFF
3045 if (**argP == 'G')
3046 {
3047 if ((*argP)[1] != '\0')
3048 g_switch_value = atoi (*argP + 1);
3049 else if (*cntP)
3050 {
3051 **vecP = (char *) NULL;
3052 (*cntP)--;
3053 (*vecP)++;
3054 g_switch_value = atoi (**vecP);
3055 }
3056 else
3057 as_warn ("Number expected after -G");
3058 *argP = "";
3059 return 1;
3d3c5039 3060 }
670a50eb 3061#endif
4e95866e 3062
670a50eb 3063 return 1; /* pretend you parsed the character */
3d3c5039
ILT
3064}
3065
3066long
3067md_pcrel_from (fixP)
3068 fixS *fixP;
3069{
670a50eb
ILT
3070 /* return the address of the delay slot */
3071 return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
3d3c5039
ILT
3072}
3073
3074int
3075md_apply_fix (fixP, valueP)
3076 fixS *fixP;
918692a5 3077 valueT *valueP;
3d3c5039 3078{
670a50eb
ILT
3079 unsigned char *buf;
3080 long insn, value;
3d3c5039 3081
670a50eb 3082 assert (fixP->fx_size == 4);
3d3c5039 3083
670a50eb
ILT
3084 value = *valueP;
3085 fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc */
3d3c5039 3086
670a50eb
ILT
3087 switch (fixP->fx_r_type)
3088 {
3d3c5039
ILT
3089 case BFD_RELOC_32:
3090 case BFD_RELOC_MIPS_JMP:
3091 case BFD_RELOC_HI16:
3092 case BFD_RELOC_HI16_S:
3093 case BFD_RELOC_LO16:
670a50eb
ILT
3094 case BFD_RELOC_MIPS_GPREL:
3095 /* Nothing needed to do. The value comes from the reloc entry */
3096 return 1;
3d3c5039
ILT
3097
3098 case BFD_RELOC_16_PCREL_S2:
670a50eb
ILT
3099 /*
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).
3103 */
3104 if (value & 0x3)
3105 as_warn ("Branch to odd address (%x)", value);
3106 value >>= 2;
3107 if ((value & ~0xFFFF) && (value & ~0xFFFF) != (-1 & ~0xFFFF))
3108 as_bad ("Relocation overflow");
3109
3110 /* update old instruction data */
3111 buf = (unsigned char *) (fixP->fx_where + fixP->fx_frag->fr_literal);
3112 switch (byte_order)
3113 {
3d3c5039 3114 case LITTLE_ENDIAN:
670a50eb
ILT
3115 insn = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
3116 break;
3d3c5039
ILT
3117
3118 case BIG_ENDIAN:
670a50eb
ILT
3119 insn = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
3120 break;
3d3c5039
ILT
3121
3122 default:
670a50eb
ILT
3123 internalError ();
3124 return 0;
3d3c5039 3125 }
670a50eb 3126 insn |= value & 0xFFFF;
918692a5 3127 md_number_to_chars ((char *) buf, insn, 4);
670a50eb 3128 break;
3d3c5039
ILT
3129
3130 default:
670a50eb 3131 internalError ();
3d3c5039 3132 }
670a50eb 3133 return 1;
3d3c5039
ILT
3134}
3135
3136#if 0
3137void
670a50eb
ILT
3138printInsn (oc)
3139 unsigned long oc;
3d3c5039 3140{
670a50eb
ILT
3141 const struct mips_opcode *p;
3142 int treg, sreg, dreg, shamt;
3143 short imm;
3144 const char *args;
3145 int i;
3d3c5039 3146
670a50eb
ILT
3147 for (i = 0; i < NUMOPCODES; ++i)
3148 {
3149 p = &mips_opcodes[i];
3150 if (((oc & p->mask) == p->match) && (p->pinfo != INSN_MACRO))
3151 {
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;
3157 imm = oc;
3158 for (args = p->args;; ++args)
3159 {
3160 switch (*args)
3161 {
3d3c5039 3162 case '\0':
670a50eb
ILT
3163 printf ("\n");
3164 break;
3d3c5039
ILT
3165
3166 case ',':
3167 case '(':
3168 case ')':
670a50eb
ILT
3169 printf ("%c", *args);
3170 continue;
3d3c5039
ILT
3171
3172 case 'r':
670a50eb
ILT
3173 assert (treg == sreg);
3174 printf ("$%d,$%d", treg, sreg);
3175 continue;
3d3c5039
ILT
3176
3177 case 'd':
918692a5 3178 case 'G':
670a50eb
ILT
3179 printf ("$%d", dreg);
3180 continue;
3d3c5039
ILT
3181
3182 case 't':
918692a5 3183 case 'E':
670a50eb
ILT
3184 printf ("$%d", treg);
3185 continue;
3d3c5039
ILT
3186
3187 case 'b':
3188 case 's':
670a50eb
ILT
3189 printf ("$%d", sreg);
3190 continue;
3d3c5039
ILT
3191
3192 case 'a':
670a50eb
ILT
3193 printf ("0x%08lx", oc & 0x1ffffff);
3194 continue;
3d3c5039
ILT
3195
3196 case 'i':
3197 case 'j':
3198 case 'o':
3199 case 'u':
670a50eb
ILT
3200 printf ("%d", imm);
3201 continue;
3d3c5039
ILT
3202
3203 case '<':
670a50eb
ILT
3204 printf ("$%d", shamt);
3205 continue;
3d3c5039
ILT
3206
3207 default:
670a50eb 3208 internalError ();
3d3c5039 3209 }
670a50eb 3210 break;
3d3c5039 3211 }
670a50eb 3212 return;
3d3c5039
ILT
3213 }
3214 }
670a50eb 3215 printf ("%08lx UNDEFINED\n", oc);
3d3c5039
ILT
3216}
3217#endif
3218
3219static symbolS *
3220get_symbol ()
3221{
670a50eb
ILT
3222 int c;
3223 char *name;
3224 symbolS *p;
3225
3226 name = input_line_pointer;
3227 c = get_symbol_end ();
3228 p = (symbolS *) symbol_find_or_make (name);
3229 *input_line_pointer = c;
3230 return p;
3d3c5039
ILT
3231}
3232
becfe05e
ILT
3233/* Align the current frag to a given power of two. The MIPS assembler
3234 also automatically adjusts any preceding label. */
3235
3236static void
3237mips_align (to, fill)
3238 int to;
3239 int fill;
3240{
3241 mips_emit_delays ();
3242 frag_align (to, fill);
3243 record_alignment (now_seg, to);
3244 if (insn_label != NULL)
3245 {
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 ());
3249 }
3250}
3251
3252/* Align to a given power of two. .align 0 turns off the automatic
3253 alignment used by the data creating pseudo-ops. */
3254
3d3c5039
ILT
3255static void
3256s_align (x)
3257 int x;
3258{
670a50eb
ILT
3259 register int temp;
3260 register long temp_fill;
3261 long max_alignment = 15;
3d3c5039 3262
670a50eb 3263 /*
3d3c5039
ILT
3264
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.
3271 We don't.
3272
3273 */
3274
670a50eb
ILT
3275 temp = get_absolute_expression ();
3276 if (temp > max_alignment)
3277 as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
3278 else if (temp < 0)
3279 {
3280 as_warn ("Alignment negative: 0 assumed.");
3281 temp = 0;
3282 }
3283 if (*input_line_pointer == ',')
3284 {
3285 input_line_pointer++;
3286 temp_fill = get_absolute_expression ();
3287 }
3288 else
3289 temp_fill = 0;
3290 if (temp)
3291 {
3292 auto_align = 1;
becfe05e 3293 mips_align (temp, (int) temp_fill);
3d3c5039 3294 }
670a50eb
ILT
3295 else
3296 {
3297 auto_align = 0;
3d3c5039
ILT
3298 }
3299
670a50eb 3300 demand_empty_rest_of_line ();
3d3c5039
ILT
3301}
3302
becfe05e
ILT
3303/* Handle .ascii and .asciiz. This just calls stringer and forgets
3304 that there was a previous instruction. */
3305
3306static void
3307s_stringer (append_zero)
3308 int append_zero;
3309{
3310 mips_emit_delays ();
3311 stringer (append_zero);
3312}
3313
3d3c5039
ILT
3314static void
3315s_change_sec (sec)
3316 int sec;
3317{
becfe05e
ILT
3318 segT segment;
3319
3320 mips_emit_delays ();
3321 segment = now_seg;
670a50eb
ILT
3322 switch (sec)
3323 {
3d3c5039 3324 case 't':
670a50eb
ILT
3325 s_text ();
3326 break;
3d3c5039 3327 case 'r':
670a50eb
ILT
3328#ifdef OBJ_ECOFF
3329 subseg_new (".rdata", (subsegT) get_absolute_expression ());
becfe05e 3330 demand_empty_rest_of_line ();
670a50eb
ILT
3331 break;
3332#else
3333 /* Fall through. */
3334#endif
3d3c5039 3335 case 'd':
670a50eb
ILT
3336 s_data ();
3337 break;
3d3c5039
ILT
3338 case 'b':
3339#ifdef BFD_ASSEMBLER
670a50eb 3340 subseg_set (bss_section, (subsegT) get_absolute_expression ());
3d3c5039 3341#else
670a50eb
ILT
3342 subseg_new (bss_section, (subsegT) get_absolute_expression ());
3343#endif
3344 demand_empty_rest_of_line ();
3345 break;
3346 case 's':
3347#ifdef OBJ_ECOFF
3348 subseg_new (".sdata", (subsegT) get_absolute_expression ());
becfe05e 3349 demand_empty_rest_of_line ();
670a50eb
ILT
3350 break;
3351#else
3352 as_bad ("Global pointers not supported; recompile -G 0");
becfe05e 3353 demand_empty_rest_of_line ();
670a50eb 3354 return;
3d3c5039 3355#endif
3d3c5039 3356 }
670a50eb 3357 auto_align = 1;
3d3c5039
ILT
3358}
3359
3360static void
3361s_cons (log_size)
3362 int log_size;
3363{
becfe05e 3364 mips_emit_delays ();
670a50eb 3365 if (log_size > 0 && auto_align)
becfe05e 3366 mips_align (log_size, 0);
670a50eb 3367 cons (1 << log_size);
3d3c5039
ILT
3368}
3369
3370static void
3371s_err (x)
3372 int x;
3373{
670a50eb 3374 as_fatal ("Encountered `.err', aborting assembly");
3d3c5039
ILT
3375}
3376
3377static void
3378s_extern (x)
3379 int x;
3380{
670a50eb
ILT
3381 long size;
3382 symbolS *symbolP;
3383
3384 symbolP = get_symbol ();
3385 if (*input_line_pointer == ',')
3386 input_line_pointer++;
5ac34ac3 3387 size = get_absolute_expression ();
670a50eb
ILT
3388 S_SET_VALUE (symbolP, size);
3389 S_SET_EXTERNAL (symbolP);
3390
3391#ifdef OBJ_ECOFF
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;
3395#endif
3d3c5039
ILT
3396}
3397
3398static void
becfe05e
ILT
3399s_float_cons (type)
3400 int type;
3d3c5039 3401{
becfe05e 3402 mips_emit_delays ();
670a50eb
ILT
3403
3404 if (auto_align)
becfe05e
ILT
3405 if (type == 'd')
3406 mips_align (3, 0);
670a50eb 3407 else
becfe05e 3408 mips_align (2, 0);
670a50eb 3409
becfe05e 3410 float_cons (type);
3d3c5039
ILT
3411}
3412
3413static void
3414s_option (x)
3415 int x;
3416{
670a50eb
ILT
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 ();
3d3c5039
ILT
3421}
3422
3423static void
3424s_mipsset (x)
3425 int x;
3426{
670a50eb
ILT
3427 char *name = input_line_pointer, ch;
3428
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';
3433
3434 if (strcmp (name, "reorder") == 0)
3435 {
4e95866e
ILT
3436 if (mips_noreorder)
3437 {
3438 prev_insn_unreordered = 1;
3439 prev_prev_insn_unreordered = 1;
3440 }
670a50eb
ILT
3441 mips_noreorder = 0;
3442 }
3443 else if (strcmp (name, "noreorder") == 0)
3444 {
becfe05e 3445 mips_emit_delays ();
670a50eb
ILT
3446 mips_noreorder = 1;
3447 }
3448 else if (strcmp (name, "at") == 0)
3449 {
3450 mips_noat = 0;
3451 }
3452 else if (strcmp (name, "noat") == 0)
3453 {
3454 mips_noat = 1;
3d3c5039 3455 }
670a50eb
ILT
3456 else if (strcmp (name, "macro") == 0)
3457 {
3458 mips_warn_about_macros = 0;
3459 }
3460 else if (strcmp (name, "nomacro") == 0)
3461 {
3462 if (mips_noreorder == 0)
3463 as_bad ("`noreorder' must be set before `nomacro'");
3464 mips_warn_about_macros = 1;
3465 }
3466 else if (strcmp (name, "move") == 0 || strcmp (name, "novolatile") == 0)
3467 {
3468 mips_nomove = 0;
3469 }
3470 else if (strcmp (name, "nomove") == 0 || strcmp (name, "volatile") == 0)
3471 {
3472 mips_nomove = 1;
3473 }
3474 else if (strcmp (name, "bopt") == 0)
3475 {
3476 mips_nobopt = 0;
3477 }
3478 else if (strcmp (name, "nobopt") == 0)
3479 {
3480 mips_nobopt = 1;
3481 }
3482 else
3483 {
3484 as_warn ("Tried to set unrecognized symbol: %s\n", name);
3485 }
3486 *input_line_pointer = ch;
3487 demand_empty_rest_of_line ();
3d3c5039
ILT
3488}
3489
becfe05e
ILT
3490/* The same as the usual .space directive, except that we have to
3491 forget about any previous instruction. */
3492
3493static void
3494s_mips_space (param)
3495 int param;
3496{
3497 mips_emit_delays ();
3498 s_space (param);
3499}
3500
3d3c5039
ILT
3501int
3502tc_get_register ()
3503{
3504 int reg;
3505
3506 SKIP_WHITESPACE ();
3507 if (*input_line_pointer++ != '$')
3508 {
3509 as_warn ("expected `$'");
3510 return 0;
3511 }
3512 if (isdigit ((unsigned char) *input_line_pointer))
3513 {
3514 reg = get_absolute_expression ();
3515 if (reg < 0 || reg >= 32)
3516 {
3517 as_warn ("Bad register number");
3518 reg = 0;
3519 }
3520 }
3521 else
3522 {
3523 if (strncmp (input_line_pointer, "fp", 2) == 0)
3524 reg = 30;
3525 else if (strncmp (input_line_pointer, "sp", 2) == 0)
3526 reg = 29;
3527 else if (strncmp (input_line_pointer, "gp", 2) == 0)
3528 reg = 28;
3529 else if (strncmp (input_line_pointer, "at", 2) == 0)
3530 reg = 1;
3531 else
3532 {
3533 as_warn ("Unrecognized register name");
3534 return 0;
3535 }
3536 input_line_pointer += 2;
3537 }
3538 return reg;
3539}
3540
3541/*
3542 * Translate internal representation of relocation info to BFD target format.
3543 */
3544arelent *
3545tc_gen_reloc (section, fixp)
3546 asection *section;
3547 fixS *fixp;
3548{
3549 arelent *reloc;
3550
3551 reloc = (arelent *) xmalloc (sizeof (arelent));
3552 assert (reloc != 0);
3553
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;
3558 else
3559#ifdef OBJ_ELF
3560 reloc->addend = 0;
3561#else
670a50eb 3562 reloc->addend = -reloc->address;
3d3c5039
ILT
3563#endif
3564 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
3565 assert (reloc->howto != 0);
3566
3d3c5039
ILT
3567 return reloc;
3568}
3569
3570/* should never be called */
918692a5 3571valueT
670a50eb
ILT
3572md_section_align (seg, addr)
3573 asection *seg;
918692a5 3574 valueT addr;
3d3c5039 3575{
670a50eb 3576 int align = bfd_get_section_alignment (stdoutput, seg);
3d3c5039 3577
670a50eb 3578 return ((addr + (1 << align) - 1) & (-1 << align));
3d3c5039
ILT
3579}
3580
3581int
670a50eb
ILT
3582md_estimate_size_before_relax (fragP, segtype)
3583 fragS *fragP;
3584 asection *segtype;
3d3c5039 3585{
670a50eb
ILT
3586 as_fatal ("md_estimate_size_before_relax");
3587 return (1);
3588} /* md_estimate_size_before_relax() */
becfe05e
ILT
3589
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
3592 can not move it. */
3593
3594void
3595mips_define_label (sym)
3596 symbolS *sym;
3597{
3598 insn_label = sym;
3599}
3d3c5039
ILT
3600\f
3601#ifndef OBJ_ECOFF
3602
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. */
3609
670a50eb
ILT
3610typedef struct loc
3611{
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;
3d3c5039 3618#if 0
670a50eb 3619 fragS *loc_frag;
3d3c5039 3620#endif
670a50eb
ILT
3621}
3622locS;
3d3c5039 3623
670a50eb
ILT
3624typedef struct proc
3625 {
3d3c5039
ILT
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;
3636 locS *proc_iline;
3637 struct file *proc_file;
3638 int proc_index;
670a50eb
ILT
3639 }
3640procS;
3d3c5039 3641
670a50eb
ILT
3642typedef struct file
3643 {
3d3c5039
ILT
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;
3649 int file_numprocs;
670a50eb
ILT
3650 }
3651fileS;
3d3c5039
ILT
3652
3653static struct obstack proc_frags;
3654static procS *proc_lastP;
3655static procS *proc_rootP;
3656static int numprocs;
3657
3658static void
3659md_obj_begin ()
3660{
670a50eb 3661 obstack_begin (&proc_frags, 0x2000);
3d3c5039
ILT
3662}
3663
3664static void
3665md_obj_end ()
3666{
3667 /* check for premature end, nesting errors, etc */
3668 if (proc_lastP && proc_lastP->proc_end == NULL)
670a50eb 3669 as_warn ("missing `.end' at end of assembly");
3d3c5039
ILT
3670}
3671
3672extern char hex_value[];
3673
3674static long
3675get_number ()
3676{
670a50eb
ILT
3677 int negative = 0;
3678 long val = 0;
3d3c5039 3679
670a50eb
ILT
3680 if (*input_line_pointer == '-')
3681 {
3682 ++input_line_pointer;
3683 negative = 1;
3d3c5039 3684 }
670a50eb
ILT
3685 if (!isdigit (*input_line_pointer))
3686 as_bad ("Expected simple number.");
3687 if (input_line_pointer[0] == '0')
3688 {
3689 if (input_line_pointer[1] == 'x')
3690 {
3691 input_line_pointer += 2;
3692 while (isxdigit (*input_line_pointer))
3693 {
3694 val <<= 4;
3695 val |= hex_value[(int) *input_line_pointer++];
3d3c5039 3696 }
670a50eb
ILT
3697 return negative ? -val : val;
3698 }
3699 else
3700 {
3701 ++input_line_pointer;
3702 while (isdigit (*input_line_pointer))
3703 {
3704 val <<= 3;
3705 val |= *input_line_pointer++ - '0';
3d3c5039 3706 }
670a50eb 3707 return negative ? -val : val;
3d3c5039
ILT
3708 }
3709 }
670a50eb
ILT
3710 if (!isdigit (*input_line_pointer))
3711 {
3712 printf (" *input_line_pointer == '%c' 0x%02x\n",
3713 *input_line_pointer, *input_line_pointer);
3714 as_warn ("Invalid number");
3715 return -1;
3d3c5039 3716 }
670a50eb
ILT
3717 while (isdigit (*input_line_pointer))
3718 {
3719 val *= 10;
3720 val += *input_line_pointer++ - '0';
3d3c5039 3721 }
670a50eb 3722 return negative ? -val : val;
3d3c5039
ILT
3723}
3724
3725/* The .file directive; just like the usual .file directive, but there
3726 is an initial number which is the ECOFF file index. */
3727
3728static void
3729s_file (x)
3730 int x;
3731{
670a50eb 3732 int line;
3d3c5039 3733
670a50eb 3734 line = get_number ();
9a7d824a 3735 s_app_file (0);
3d3c5039
ILT
3736}
3737
3738
3739/* The .end directive. */
3740
3741static void
3742s_mipsend (x)
3743 int x;
3744{
670a50eb
ILT
3745 symbolS *p;
3746
3747 if (!is_end_of_line[(unsigned char) *input_line_pointer])
3748 {
3749 p = get_symbol ();
3750 demand_empty_rest_of_line ();
3751 }
3752 else
3753 p = NULL;
3754 if (now_seg != text_section)
3755 as_warn (".end not in text section");
3756 if (!proc_lastP)
3757 {
3758 as_warn (".end and no .ent seen yet.");
3759 return;
3d3c5039
ILT
3760 }
3761
670a50eb
ILT
3762 if (p != NULL)
3763 {
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.");
3d3c5039
ILT
3767 }
3768
670a50eb 3769 proc_lastP->proc_end = (symbolS *) 1;
3d3c5039
ILT
3770}
3771
3772/* The .aent and .ent directives. */
3773
3774static void
3775s_ent (aent)
3776 int aent;
3777{
670a50eb
ILT
3778 int number = 0;
3779 procS *procP;
3780 symbolS *symbolP;
3781
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.");
3789
3790 if (!aent && proc_lastP && proc_lastP->proc_end == NULL)
3791 as_warn ("missing `.end'");
3792
3793 if (!aent)
3794 {
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;
3806 if (proc_lastP)
3807 proc_lastP->proc_next = procP;
3808 else
3809 proc_rootP = procP;
3810 proc_lastP = procP;
3811 numprocs++;
3d3c5039 3812 }
670a50eb 3813 demand_empty_rest_of_line ();
3d3c5039
ILT
3814}
3815
3816/* The .frame directive. */
3817
3818static void
3819s_frame (x)
670a50eb 3820 int x;
3d3c5039
ILT
3821{
3822#if 0
670a50eb
ILT
3823 char str[100];
3824 symbolS *symP;
3825 int frame_reg;
3826 int frame_off;
3827 int pcreg;
3828
3829 frame_reg = tc_get_register ();
3830 if (*input_line_pointer == ',')
3831 input_line_pointer++;
5ac34ac3 3832 frame_off = get_absolute_expression ();
670a50eb
ILT
3833 if (*input_line_pointer == ',')
3834 input_line_pointer++;
3835 pcreg = tc_get_register ();
3836
3837 /* bob third eye */
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 */
3843
3844 /* We don't have to write out a frame stab for unoptimized code. */
3845 if (!(frame_reg == 30 && frame_off == 0))
3846 {
3847 if (!proc_lastP)
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 */
3d3c5039 3856 }
670a50eb 3857 demand_empty_rest_of_line ();
3d3c5039
ILT
3858#endif
3859}
3860
3861/* The .fmask and .mask directives. */
3862
3863static void
3864s_mask (reg_type)
3865 char reg_type;
3866{
3867#if 0
670a50eb
ILT
3868 char str[100], *strP;
3869 symbolS *symP;
3870 int i;
3871 unsigned int mask;
3872 int off;
3873
3874 mask = get_number ();
3875 if (*input_line_pointer == ',')
3876 input_line_pointer++;
3877 off = get_absolute_expression ();
3878
3879 /* bob only for coff */
3880 assert (proc_rootP);
3881 if (reg_type == 'F')
3882 {
3883 proc_rootP->proc_fpreg_mask = mask;
3884 proc_rootP->proc_fpreg_offset = off;
3d3c5039 3885 }
670a50eb
ILT
3886 else
3887 {
3888 proc_rootP->proc_reg_mask = mask;
3889 proc_rootP->proc_reg_offset = off;
3890 }
3891
3892 /* bob macho .mask + .fmask */
3d3c5039 3893
670a50eb
ILT
3894 /* We don't have to write out a mask stab if no saved regs. */
3895 if (!(mask == 0))
3896 {
3897 if (!proc_lastP)
3898 as_warn ("No .ent for .mask to use.");
3899 strP = str;
3900 for (i = 0; i < 32; i++)
3901 {
3902 if (mask % 2)
3903 {
3904 sprintf (strP, "%c%d,", reg_type, i);
3905 strP += strlen (strP);
3906 }
3d3c5039 3907 mask /= 2;
670a50eb
ILT
3908 }
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 */
3d3c5039
ILT
3916 }
3917#endif
3918}
3919
3920/* The .loc directive. */
3921
3922static void
3923s_loc (x)
3924 int x;
3925{
3926#if 0
670a50eb
ILT
3927 symbolS *symbolP;
3928 int lineno;
3929 int addroff;
3d3c5039 3930
670a50eb 3931 assert (now_seg == text_section);
3d3c5039 3932
670a50eb
ILT
3933 lineno = get_number ();
3934 addroff = obstack_next_free (&frags) - frag_now->fr_literal;
3d3c5039 3935
670a50eb
ILT
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;
3d3c5039
ILT
3941#endif
3942}
3943
3944#endif /* ! defined (OBJ_ECOFF) */