]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-mips.c
* bfd.c (_bfd_host_big_endian): Removed.
[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
4e95866e
ILT
105/* Whether we are optimizing. We always optimize unless -O0 is given.
106 For the very simple optimizations we do, this is compatible with
107 the MIPS assembler. */
108static int mips_optimize = 1;
109
becfe05e
ILT
110/* The previous instruction. */
111static struct mips_cl_insn prev_insn;
112
113/* The instruction before prev_insn. */
114static struct mips_cl_insn prev_prev_insn;
115
116/* If we don't want information for prev_insn or prev_prev_insn, we
117 point the insn_mo field at this dummy integer. */
118static const struct mips_opcode dummy_opcode = { 0 };
119
120/* Non-zero if prev_insn is valid. */
121static int prev_insn_valid;
122
123/* The frag for the previous instruction. */
124static struct frag *prev_insn_frag;
125
126/* The offset into prev_insn_frag for the previous instruction. */
127static long prev_insn_where;
128
129/* The reloc for the previous instruction, if any. */
130static fixS *prev_insn_fixp;
131
132/* Non-zero if the previous instruction was in a delay slot. */
133static int prev_insn_is_delay_slot;
4e95866e
ILT
134
135/* Non-zero if the previous instruction was in a .set noreorder. */
136static int prev_insn_unreordered;
137
138/* Non-zero if the previous previous instruction was in a .set
139 noreorder. */
140static int prev_prev_insn_unreordered;
3d3c5039
ILT
141\f
142/* Prototypes for static functions. */
143
144#ifdef __STDC__
145#define internalError() \
146 as_fatal ("internal Error, line %d, %s", __LINE__, __FILE__)
147#else
148#define internalError() as_fatal ("MIPS internal Error");
149#endif
150
becfe05e
ILT
151static int insn_uses_reg PARAMS ((struct mips_cl_insn *ip,
152 int reg, int fpr));
670a50eb
ILT
153static void append_insn PARAMS ((struct mips_cl_insn * ip,
154 expressionS * p,
3d3c5039 155 bfd_reloc_code_real_type r));
becfe05e
ILT
156static void mips_no_prev_insn PARAMS ((void));
157static void mips_emit_delays PARAMS ((void));
670a50eb
ILT
158static int gp_reference PARAMS ((expressionS * ep));
159static void macro_build PARAMS ((int *counter, expressionS * ep,
3d3c5039
ILT
160 const char *name, const char *fmt,
161 ...));
670a50eb 162static void macro_build_lui PARAMS ((int *counter, expressionS * ep,
3d3c5039
ILT
163 int regnum));
164static void set_at PARAMS ((int *counter, int reg));
165static void set_at_unsigned PARAMS ((int *counter, int reg));
670a50eb
ILT
166static void check_absolute_expr PARAMS ((struct mips_cl_insn * ip,
167 expressionS * expr));
3d3c5039 168static void load_register PARAMS ((int *counter,
670a50eb
ILT
169 struct mips_cl_insn * ip,
170 int reg, expressionS * ep));
171static void macro PARAMS ((struct mips_cl_insn * ip));
172static void mips_ip PARAMS ((char *str, struct mips_cl_insn * ip));
173static int my_getSmallExpression PARAMS ((expressionS * ep, char *str));
174static void my_getExpression PARAMS ((expressionS * ep, char *str));
3d3c5039 175static symbolS *get_symbol PARAMS ((void));
becfe05e 176static void mips_align PARAMS ((int to, int fill));
3d3c5039 177static void s_align PARAMS ((int));
becfe05e 178static void s_stringer PARAMS ((int));
3d3c5039
ILT
179static void s_change_sec PARAMS ((int));
180static void s_cons PARAMS ((int));
181static void s_err PARAMS ((int));
182static void s_extern PARAMS ((int));
183static void s_float_cons PARAMS ((int));
184static void s_option PARAMS ((int));
185static void s_mipsset PARAMS ((int));
becfe05e 186static void s_mips_space PARAMS ((int));
3d3c5039
ILT
187#ifndef OBJ_ECOFF
188static void md_obj_begin PARAMS ((void));
189static void md_obj_end PARAMS ((void));
190static long get_number PARAMS ((void));
191static void s_ent PARAMS ((int));
192static void s_mipsend PARAMS ((int));
193static void s_file PARAMS ((int));
194static void s_frame PARAMS ((int));
195static void s_loc PARAMS ((int));
196static void s_mask PARAMS ((char));
197#endif
198\f
199/* Pseudo-op table.
200
201 The following pseudo-ops from the Kane and Heinrich MIPS book
202 should be defined here, but are currently unsupported: .alias,
203 .galive, .gjaldef, .gjrlive, .livereg, .noalias.
204
205 The following pseudo-ops from the Kane and Heinrich MIPS book are
206 specific to the type of debugging information being generated, and
207 should be defined by the object format: .aent, .begin, .bend,
208 .bgnb, .end, .endb, .ent, .fmask, .frame, .loc, .mask, .verstamp,
209 .vreg.
210
211 The following pseudo-ops from the Kane and Heinrich MIPS book are
212 not MIPS CPU specific, but are also not specific to the object file
213 format. This file is probably the best place to define them, but
214 they are not currently supported: .asm0, .endr, .lab, .repeat,
215 .struct, .weakext. */
216
217const pseudo_typeS md_pseudo_table[] =
218{
670a50eb
ILT
219 /* MIPS specific pseudo-ops. */
220 {"option", s_option, 0},
221 {"set", s_mipsset, 0},
222 {"rdata", s_change_sec, 'r',},
223 {"sdata", s_change_sec, 's',},
3d3c5039 224
670a50eb 225 /* Relatively generic pseudo-ops that happen to be used on MIPS
3d3c5039 226 chips. */
becfe05e 227 {"asciiz", s_stringer, 1},
670a50eb
ILT
228 {"bss", s_change_sec, 'b'},
229 {"err", s_err, 0},
230 {"half", s_cons, 1},
3d3c5039 231
670a50eb 232 /* These pseudo-ops are defined in read.c, but must be overridden
3d3c5039 233 here for one reason or another. */
670a50eb 234 {"align", s_align, 0},
becfe05e
ILT
235 {"ascii", s_stringer, 0},
236 {"asciz", s_stringer, 1},
670a50eb
ILT
237 {"byte", s_cons, 0},
238 {"data", s_change_sec, 'd'},
becfe05e 239 {"double", s_float_cons, 'd'},
670a50eb 240 {"extern", s_extern, 0},
becfe05e
ILT
241 {"float", s_float_cons, 'f'},
242 {"space", s_mips_space, 0},
670a50eb
ILT
243 {"text", s_change_sec, 't'},
244 {"word", s_cons, 2},
3d3c5039
ILT
245
246#ifndef OBJ_ECOFF
670a50eb 247 /* These pseudo-ops should be defined by the object file format.
3d3c5039
ILT
248 However, ECOFF is the only format which currently defines them,
249 so we have versions here for a.out. */
670a50eb
ILT
250 {"aent", s_ent, 1},
251 {"end", s_mipsend, 0},
252 {"ent", s_ent, 0},
253 {"file", s_file, 0},
254 {"fmask", s_ignore, 'F'},
255 {"frame", s_ignore, 0},
256 {"loc", s_ignore, 0},
257 {"mask", s_ignore, 'R'},
258 {"verstamp", s_ignore, 0},
3d3c5039
ILT
259#endif
260
670a50eb
ILT
261 /* Sentinel. */
262 {NULL}
3d3c5039
ILT
263};
264\f
670a50eb
ILT
265const relax_typeS md_relax_table[] =
266{
918692a5 267 { 0 }
3d3c5039
ILT
268};
269
270
271static char *expr_end;
272
273static expressionS imm_expr;
274static expressionS offset_expr;
275static bfd_reloc_code_real_type imm_reloc;
276static bfd_reloc_code_real_type offset_reloc;
277
278/*
279 * This function is called once, at assembler startup time. It should
280 * set up all the tables, etc. that the MD part of the assembler will need.
281 */
282void
670a50eb 283md_begin ()
3d3c5039 284{
670a50eb
ILT
285 register char *retval = NULL;
286 register unsigned int i = 0;
3d3c5039 287
670a50eb
ILT
288 if ((op_hash = hash_new ()) == NULL)
289 {
290 as_fatal ("Virtual memory exhausted");
3d3c5039 291 }
670a50eb
ILT
292 for (i = 0; i < NUMOPCODES;)
293 {
294 const char *name = mips_opcodes[i].name;
295
296 retval = hash_insert (op_hash, name, &mips_opcodes[i]);
297 if (retval != NULL && *retval != '\0')
298 {
299 fprintf (stderr, "internal error: can't hash `%s': %s\n",
300 mips_opcodes[i].name, retval);
301 as_fatal ("Broken assembler. No assembly attempted.");
302 }
303 do
304 {
305 if ((mips_opcodes[i].match & mips_opcodes[i].mask) !=
306 mips_opcodes[i].match)
307 {
308 fprintf (stderr, "internal error: bad opcode: `%s' \"%s\"\n",
309 mips_opcodes[i].name, mips_opcodes[i].args);
310 as_fatal ("Broken assembler. No assembly attempted.");
3d3c5039 311 }
670a50eb
ILT
312 ++i;
313 }
314 while ((i < NUMOPCODES) && !strcmp (mips_opcodes[i].name, name));
3d3c5039
ILT
315 }
316
becfe05e
ILT
317 mips_no_prev_insn ();
318
3d3c5039 319#ifndef OBJ_ECOFF
670a50eb 320 md_obj_begin ();
3d3c5039
ILT
321#endif
322}
323
324void
325md_end ()
326{
327#ifndef OBJ_ECOFF
328 md_obj_end ();
329#endif
330}
331
332void
670a50eb
ILT
333md_assemble (str)
334 char *str;
3d3c5039 335{
670a50eb
ILT
336 struct mips_cl_insn insn;
337 static int init;
338
339 if (!init)
340 {
341 /* set the default alignment for the text section (2**2) */
342 /* This should go in md_begin but text_section isn't initialized then */
343 record_alignment (text_section, 2);
918692a5 344#ifdef OBJ_ECOFF
670a50eb 345 bfd_set_gp_size (stdoutput, g_switch_value);
918692a5 346#endif
670a50eb 347 init = 1;
3d3c5039
ILT
348 }
349
5ac34ac3
ILT
350 imm_expr.X_op = O_absent;
351 offset_expr.X_op = O_absent;
3d3c5039 352
670a50eb
ILT
353 mips_ip (str, &insn);
354 if (insn_error)
355 {
356 as_bad ("%s `%s'", insn_error, str);
357 return;
358 }
359 if (insn.insn_mo->pinfo == INSN_MACRO)
360 {
361 macro (&insn);
3d3c5039 362 }
670a50eb
ILT
363 else
364 {
5ac34ac3 365 if (imm_expr.X_op != O_absent)
670a50eb 366 append_insn (&insn, &imm_expr, imm_reloc);
5ac34ac3 367 else if (offset_expr.X_op != O_absent)
670a50eb
ILT
368 append_insn (&insn, &offset_expr, offset_reloc);
369 else
370 append_insn (&insn, NULL, BFD_RELOC_UNUSED);
3d3c5039
ILT
371 }
372}
373
becfe05e
ILT
374/* See whether instruction IP reads register REG. If FPR is non-zero,
375 REG is a floating point register. */
376
377static int
378insn_uses_reg (ip, reg, fpr)
379 struct mips_cl_insn *ip;
380 int reg;
381 int fpr;
382{
383 /* Don't report on general register 0, since it never changes. */
384 if (! fpr && reg == 0)
385 return 0;
386
387 if (fpr)
388 {
389 /* If we are called with either $f0 or $f1, we must check $f0.
390 This is not optimal, because it will introduce an unnecessary
391 NOP between "lwc1 $f0" and "swc1 $f1". To fix this we would
392 need to distinguish reading both $f0 and $f1 or just one of
393 them. Note that we don't have to check the other way,
394 because there is no instruction that sets both $f0 and $f1
395 and requires a delay. */
396 if ((ip->insn_mo->pinfo & INSN_READ_FPR_S)
397 && ((ip->insn_opcode >> OP_SH_FS) & OP_MASK_FS) == (reg &~ 1))
398 return 1;
399 if ((ip->insn_mo->pinfo & INSN_READ_FPR_T)
400 && ((ip->insn_opcode >> OP_SH_FT) & OP_MASK_FT) == (reg &~ 1))
401 return 1;
402 }
403 else
404 {
405 if ((ip->insn_mo->pinfo & INSN_READ_GPR_S)
406 && ((ip->insn_opcode >> OP_SH_RS) & OP_MASK_RS) == reg)
407 return 1;
408 if ((ip->insn_mo->pinfo & INSN_READ_GPR_T)
409 && ((ip->insn_opcode >> OP_SH_RT) & OP_MASK_RT) == reg)
410 return 1;
411 }
412
413 return 0;
414}
415
3d3c5039
ILT
416#define ALIGN_ERR "Attempt to assemble instruction onto non word boundary."
417#define ALIGN_ERR2 "GAS doesn't do implicit alignment; use .align directive."
418
419/*
420 * append insn
421 * Output an instruction.
422 */
423static void
670a50eb
ILT
424append_insn (ip, address_expr, reloc_type)
425 struct mips_cl_insn *ip;
426 expressionS *address_expr;
427 bfd_reloc_code_real_type reloc_type;
3d3c5039 428{
670a50eb 429 char *f;
becfe05e
ILT
430 fixS *fixp;
431 int nops = 0;
3d3c5039 432
becfe05e
ILT
433 if (! mips_noreorder)
434 {
435 /* If the previous insn required any delay slots, see if we need
436 to insert a NOP or two. There are six kinds of possible
437 hazards, of which an instruction can have at most one type.
438 (1) a load delay
439 (2) an unconditional branch delay
440 (3) a conditional branch delay
441 (4) a generic coprocessor delay
442 (5) a coprocessor condition code delay
443 (6) a HI/LO special register delay
444
445 There are a lot of optimizations we could do that we don't.
446 In particular, we do not, in general, reorder instructions.
447 If you use gcc with optimization, it will reorder
448 instructions and generally do much more optimization then we
449 do here; repeating all that work in the assembler would only
450 benefit hand written assembly code, and does not seem worth
451 it. */
452
453 /* This is how a NOP is emitted. */
454#define emit_nop() md_number_to_chars (frag_more (4), 0, 4)
455
456 /* The previous insn might require a delay slot, depending upon
457 the contents of the current insn. */
458 if (prev_insn.insn_mo->pinfo & INSN_LOAD_DELAY)
459 {
460 /* A load delay. All load delays delay the use of general
461 register rt for one instruction. */
462 know (prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_T);
463 if (insn_uses_reg (ip,
464 (prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT,
465 0))
466 ++nops;
467 }
468 else if (prev_insn.insn_mo->pinfo & INSN_COPROC_DELAY)
469 {
470 /* A generic coprocessor delay. The previous instruction
471 modified a coprocessor general or control register. If
472 it modified a control register, we need to avoid any
473 coprocessor instruction (this is probably not always
474 required, but it sometimes is). If it modified a general
475 register, we avoid using that register.
476
477 This case is not handled very well. There is no special
478 knowledge of CP0 handling, and the coprocessors other
479 than the floating point unit are not distinguished at
480 all. */
481 if (prev_insn.insn_mo->pinfo & INSN_WRITE_FPR_T)
482 {
483 if (insn_uses_reg (ip,
484 ((prev_insn.insn_opcode >> OP_SH_RT)
485 & OP_MASK_RT),
486 1))
487 ++nops;
488 }
489 else if (prev_insn.insn_mo->pinfo & INSN_WRITE_FPR_D)
490 {
491 if (insn_uses_reg (ip,
492 ((prev_insn.insn_opcode >> OP_SH_RD)
493 & OP_MASK_RD),
494 1))
495 ++nops;
496 }
497 else
498 {
499 /* We don't know exactly what the previous instruction
500 does. If the current instruction uses a coprocessor
501 register, we must insert a NOP. If previous
502 instruction may set the condition codes, and the
503 current instruction uses them, we must insert two
504 NOPS. */
505 if ((prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
506 && (ip->insn_mo->pinfo & INSN_READ_COND_CODE))
507 nops += 2;
508 else if (ip->insn_mo->pinfo & INSN_COP)
509 ++nops;
510 }
511 }
512 else if (prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
513 {
514 /* The previous instruction sets the coprocessor condition
515 codes, but does not require a general coprocessor delay
516 (this means it is a floating point comparison
517 instruction). If this instruction uses the condition
518 codes, we need to insert a single NOP. */
519 if (ip->insn_mo->pinfo & INSN_READ_COND_CODE)
520 ++nops;
521 }
522 else if (prev_insn.insn_mo->pinfo & INSN_READ_LO)
523 {
524 /* The previous instruction reads the LO register; if the
525 current instruction writes to the LO register, we must
526 insert two NOPS. */
527 if (ip->insn_mo->pinfo & INSN_WRITE_LO)
528 nops += 2;
529 }
530 else if (prev_insn.insn_mo->pinfo & INSN_READ_HI)
531 {
532 /* The previous instruction reads the HI register; if the
533 current instruction writes to the HI register, we must
534 insert a NOP. */
535 if (ip->insn_mo->pinfo & INSN_WRITE_HI)
536 nops += 2;
537 }
538
539 /* There are two cases which require two intervening
540 instructions: 1) setting the condition codes using a move to
541 coprocessor instruction which requires a general coprocessor
542 delay and then reading the condition codes 2) reading the HI
543 or LO register and then writing to it. If we are not already
544 emitting a NOP instruction, we must check for these cases
545 compared to the instruction previous to the previous
546 instruction. */
547 if (nops == 0
548 && (((prev_prev_insn.insn_mo->pinfo & INSN_COPROC_DELAY)
549 && (prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
550 && (ip->insn_mo->pinfo & INSN_READ_COND_CODE))
551 || ((prev_prev_insn.insn_mo->pinfo & INSN_READ_LO)
552 && (ip->insn_mo->pinfo & INSN_WRITE_LO))
553 || ((prev_prev_insn.insn_mo->pinfo & INSN_READ_HI)
554 && (ip->insn_mo->pinfo & INSN_WRITE_HI))))
555 ++nops;
556
557 /* Now emit the right number of NOP instructions. */
558 if (nops > 0)
559 {
560 emit_nop ();
561 if (nops > 1)
562 emit_nop ();
563 if (insn_label != NULL)
564 {
565 assert (S_GET_SEGMENT (insn_label) == now_seg);
566 insn_label->sy_frag = frag_now;
567 S_SET_VALUE (insn_label, frag_now_fix ());
568 }
569 }
570 }
571
670a50eb 572 f = frag_more (4);
becfe05e
ILT
573#if 0
574 /* This is testing the address of the frag, not the alignment of
575 the instruction in the current section. */
670a50eb
ILT
576 if ((int) f & 3)
577 {
578 as_bad (ALIGN_ERR);
579 as_bad (ALIGN_ERR2);
3d3c5039
ILT
580 }
581#endif
becfe05e 582 fixp = NULL;
670a50eb
ILT
583 if (address_expr != NULL)
584 {
5ac34ac3 585 if (address_expr->X_op == O_constant)
670a50eb
ILT
586 {
587 switch (reloc_type)
588 {
3d3c5039 589 case BFD_RELOC_32:
670a50eb
ILT
590 ip->insn_opcode |= address_expr->X_add_number;
591 break;
3d3c5039
ILT
592
593 case BFD_RELOC_LO16:
670a50eb
ILT
594 ip->insn_opcode |= address_expr->X_add_number & 0xffff;
595 break;
3d3c5039
ILT
596
597 case BFD_RELOC_MIPS_JMP:
598 case BFD_RELOC_16_PCREL_S2:
670a50eb 599 goto need_reloc;
3d3c5039
ILT
600
601 default:
670a50eb 602 internalError ();
3d3c5039 603 }
670a50eb
ILT
604 }
605 else
606 {
607 assert (reloc_type != BFD_RELOC_UNUSED);
3d3c5039 608 need_reloc:
5ac34ac3
ILT
609 fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
610 address_expr,
611 reloc_type == BFD_RELOC_16_PCREL_S2,
612 reloc_type);
3d3c5039
ILT
613 }
614 }
becfe05e 615
670a50eb
ILT
616 md_number_to_chars (f, ip->insn_opcode, 4);
617
becfe05e 618 if (! mips_noreorder)
670a50eb 619 {
becfe05e
ILT
620 /* Filling the branch delay slot is more complex. We try to
621 switch the branch with the previous instruction, which we can
622 do if the previous instruction does not set up a condition
623 that the branch tests and if the branch is not itself the
624 target of any branch. */
625 if ((ip->insn_mo->pinfo & INSN_UNCOND_BRANCH_DELAY)
626 || (ip->insn_mo->pinfo & INSN_COND_BRANCH_DELAY))
627 {
4e95866e
ILT
628 if (! mips_optimize
629 /* If we had to emit any NOP instructions, then we
630 already know we can not swap. */
631 || nops != 0
becfe05e
ILT
632 /* If we don't even know the previous insn, we can not
633 swap. */
634 || ! prev_insn_valid
635 /* If the previous insn is already in a branch delay
636 slot, then we can not swap. */
637 || prev_insn_is_delay_slot
4e95866e
ILT
638 /* If the previous previous insn was in a .set
639 noreorder, we can't swap. Actually, the MIPS
640 assembler will swap in this situation. However, gcc
641 configured -with-gnu-as will generate code like
642 .set noreorder
643 lw $4,XXX
644 .set reorder
645 INSN
646 bne $4,$0,foo
647 in which we can not swap the bne and INSN. If gcc is
648 not configured -with-gnu-as, it does not output the
649 .set pseudo-ops. We don't have to check
650 prev_insn_unreordered, because prev_insn_valid will
651 be 0 in that case. We don't want to use
652 prev_prev_insn_valid, because we do want to be able
653 to swap at the start of a function. */
654 || prev_prev_insn_unreordered
becfe05e
ILT
655 /* If the branch is itself the target of a branch, we
656 can not swap. We cheat on this; all we check for is
657 whether there is a label on this instruction. If
658 there are any branches to anything other than a
659 label, users must use .set noreorder. */
660 || insn_label != NULL
661 /* If the branch reads the condition codes, we don't
662 even try to swap, because in the sequence
663 ctc1 $X,$31
664 INSN
665 INSN
666 bc1t LABEL
667 we can not swap, and I don't feel like handling that
668 case. */
669 || (ip->insn_mo->pinfo & INSN_READ_COND_CODE)
670 /* We can not swap with an instruction that requires a
671 delay slot, becase the target of the branch might
672 interfere with that instruction. */
673 || (prev_insn.insn_mo->pinfo
674 & (INSN_LOAD_DELAY
675 | INSN_COPROC_DELAY
676 | INSN_WRITE_COND_CODE
677 | INSN_READ_LO
678 | INSN_READ_HI))
679 /* We can not swap with a branch instruction. */
680 || (prev_insn.insn_mo->pinfo
681 & (INSN_UNCOND_BRANCH_DELAY | INSN_COND_BRANCH_DELAY))
682 /* If the branch reads a register that the previous
683 instruction sets, we can not swap. */
684 || ((prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_T)
685 && insn_uses_reg (ip,
686 ((prev_insn.insn_opcode >> OP_SH_RT)
687 & OP_MASK_RT),
688 0))
689 || ((prev_insn.insn_mo->pinfo & INSN_WRITE_GPR_D)
690 && insn_uses_reg (ip,
691 ((prev_insn.insn_opcode >> OP_SH_RD)
692 & OP_MASK_RD),
693 0))
694 /* If the branch writes a register that the previous
695 instruction reads, we can not swap (we know that
696 branches only write to RD or to $31). */
697 || ((ip->insn_mo->pinfo & INSN_WRITE_GPR_D)
698 && insn_uses_reg (&prev_insn,
699 ((ip->insn_opcode >> OP_SH_RD)
700 & OP_MASK_RD),
701 0))
702 || ((ip->insn_mo->pinfo & INSN_WRITE_GPR_31)
703 && insn_uses_reg (&prev_insn, 31, 0))
704 /* If the previous previous instruction has a load
705 delay, and sets a register that the branch reads, we
706 can not swap. */
707 || ((prev_prev_insn.insn_mo->pinfo & INSN_LOAD_DELAY)
708 && insn_uses_reg (ip,
709 ((prev_prev_insn.insn_opcode >> OP_SH_RT)
710 & OP_MASK_RT),
711 0)))
712 {
713 /* We could do even better for unconditional branches to
714 portions of this object file; we could pick up the
715 instruction at the destination, put it in the delay
716 slot, and bump the destination address. */
717 emit_nop ();
718 /* Update the previous insn information. */
719 prev_prev_insn = *ip;
720 prev_insn.insn_mo = &dummy_opcode;
721 }
722 else
723 {
724 char *prev_f;
725 char temp[4];
726
727 /* It looks like we can actually do the swap. */
728 prev_f = prev_insn_frag->fr_literal + prev_insn_where;
729 memcpy (temp, prev_f, 4);
730 memcpy (prev_f, f, 4);
731 memcpy (f, temp, 4);
732 if (prev_insn_fixp)
733 {
734 prev_insn_fixp->fx_frag = frag_now;
735 prev_insn_fixp->fx_where = f - frag_now->fr_literal;
736 }
737 if (fixp)
738 {
739 fixp->fx_frag = prev_insn_frag;
740 fixp->fx_where = prev_insn_where;
741 }
742 /* Update the previous insn information; leave prev_insn
743 unchanged. */
744 prev_prev_insn = *ip;
745 }
746 prev_insn_is_delay_slot = 1;
747
748 /* If that was an unconditional branch, forget the previous
749 insn information. */
750 if (ip->insn_mo->pinfo & INSN_UNCOND_BRANCH_DELAY)
751 {
752 prev_prev_insn.insn_mo = &dummy_opcode;
753 prev_insn.insn_mo = &dummy_opcode;
754 }
755 }
756 else
670a50eb 757 {
becfe05e
ILT
758 /* Update the previous insn information. */
759 if (nops > 0)
760 prev_prev_insn.insn_mo = &dummy_opcode;
761 else
762 prev_prev_insn = prev_insn;
763 prev_insn = *ip;
764
765 /* Any time we see a branch, we always fill the delay slot
766 immediately; since this insn is not a branch, we know it
767 is not in a delay slot. */
768 prev_insn_is_delay_slot = 0;
769 }
770
4e95866e
ILT
771 prev_prev_insn_unreordered = prev_insn_unreordered;
772 prev_insn_unreordered = 0;
becfe05e
ILT
773 prev_insn_frag = frag_now;
774 prev_insn_where = f - frag_now->fr_literal;
775 prev_insn_fixp = fixp;
776 prev_insn_valid = 1;
777 }
3d3c5039 778
becfe05e
ILT
779 /* We just output an insn, so the next one doesn't have a label. */
780 insn_label = NULL;
781}
782
783/* This function forgets that there was any previous instruction or
784 label. */
785
786static void
787mips_no_prev_insn ()
788{
789 prev_insn.insn_mo = &dummy_opcode;
790 prev_prev_insn.insn_mo = &dummy_opcode;
791 prev_insn_valid = 0;
792 prev_insn_is_delay_slot = 0;
4e95866e
ILT
793 prev_insn_unreordered = 0;
794 prev_prev_insn_unreordered = 0;
becfe05e
ILT
795 insn_label = NULL;
796}
797
798/* This function must be called whenever we turn on noreorder or emit
799 something other than instructions. It inserts any NOPS which might
800 be needed by the previous instruction, and clears the information
801 kept for the previous instructions. */
802
803static void
804mips_emit_delays ()
805{
806 if (! mips_noreorder)
807 {
808 int nop;
809
810 nop = 0;
811 if (prev_insn.insn_mo->pinfo & ANY_DELAY)
812 {
813 nop = 1;
814 if ((prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
815 || (prev_insn.insn_mo->pinfo & INSN_READ_HI)
816 || (prev_insn.insn_mo->pinfo & INSN_READ_LO))
817 emit_nop ();
818 }
819 else if ((prev_prev_insn.insn_mo->pinfo & INSN_WRITE_COND_CODE)
820 || (prev_prev_insn.insn_mo->pinfo & INSN_READ_HI)
821 || (prev_prev_insn.insn_mo->pinfo & INSN_READ_LO))
822 nop = 1;
823 if (nop)
670a50eb 824 {
becfe05e
ILT
825 emit_nop ();
826 if (insn_label != NULL)
827 {
828 assert (S_GET_SEGMENT (insn_label) == now_seg);
829 insn_label->sy_frag = frag_now;
830 S_SET_VALUE (insn_label, frag_now_fix ());
831 }
3d3c5039 832 }
becfe05e 833 mips_no_prev_insn ();
3d3c5039
ILT
834 }
835}
836
670a50eb
ILT
837/* Return 1 if an expression can be accessed via the GP register. */
838
839static int
840gp_reference (ep)
841 expressionS *ep;
842{
843#ifdef OBJ_ECOFF
844 symbolS *sym;
9a7d824a 845 const char *symname;
670a50eb
ILT
846 const char *segname;
847
848 sym = ep->X_add_symbol;
849 if (sym == (symbolS *) NULL
5ac34ac3 850 || ep->X_op_symbol != (symbolS *) NULL)
670a50eb 851 return 0;
9a7d824a
ILT
852
853 /* Certain symbols can not be referenced off the GP, although it
854 appears as though they can. */
855 symname = S_GET_NAME (sym);
856 if (symname != (const char *) NULL
857 && (strcmp (symname, "eprol") == 0
858 || strcmp (symname, "etext") == 0
859 || strcmp (symname, "_gp") == 0
860 || strcmp (symname, "edata") == 0
861 || strcmp (symname, "_fbss") == 0
862 || strcmp (symname, "_fdata") == 0
863 || strcmp (symname, "_ftext") == 0
864 || strcmp (symname, "end") == 0))
865 return 0;
670a50eb
ILT
866 if (! S_IS_DEFINED (sym)
867 && S_GET_VALUE (sym) != 0
868 && S_GET_VALUE (sym) <= g_switch_value)
869 return 1;
870 segname = segment_name (S_GET_SEGMENT (ep->X_add_symbol));
871 return (strcmp (segname, ".sdata") == 0
872 || strcmp (segname, ".sbss") == 0);
873#else /* ! defined (OBJ_ECOFF) */
874 /* The GP register is only used for ECOFF. */
875 return 0;
876#endif /* ! defined (OBJ_ECOFF) */
877}
878
879/* Build an instruction created by a macro expansion. This is passed
880 a pointer to the count of instructions created so far, an
881 expression, the name of the instruction to build, an operand format
882 string, and corresponding arguments. */
883
3d3c5039
ILT
884#ifndef NO_STDARG
885static void
886macro_build (int *counter,
670a50eb 887 expressionS * ep,
3d3c5039
ILT
888 const char *name,
889 const char *fmt,
890 ...)
891#else /* ! defined (NO_STDARG) */
892static void
893macro_build (counter, ep, name, fmt, va_alist)
894 int *counter;
895 expressionS *ep;
896 const char *name;
897 const char *fmt;
898 va_dcl
899#endif /* ! defined (NO_STDARG) */
900{
670a50eb
ILT
901 struct mips_cl_insn insn;
902 bfd_reloc_code_real_type r;
903 va_list args;
3d3c5039
ILT
904
905#ifndef NO_STDARG
670a50eb 906 va_start (args, fmt);
3d3c5039 907#else
670a50eb 908 va_start (args);
3d3c5039
ILT
909#endif
910
670a50eb
ILT
911 /*
912 * If the macro is about to expand into a second instruction,
913 * print a warning if needed. We need to pass ip as a parameter
914 * to generate a better warning message here...
915 */
916 if (mips_warn_about_macros && *counter == 1)
917 as_warn ("Macro instruction expanded into multiple instructions");
918
919 *counter += 1; /* bump instruction counter */
920
921 r = BFD_RELOC_UNUSED;
922 insn.insn_mo = (struct mips_opcode *) hash_find (op_hash, name);
923 assert (insn.insn_mo);
924 assert (strcmp (name, insn.insn_mo->name) == 0);
925
926 while (strcmp (fmt, insn.insn_mo->args) != 0)
927 {
928 ++insn.insn_mo;
929 assert (insn.insn_mo->name);
930 assert (strcmp (name, insn.insn_mo->name) == 0);
3d3c5039 931 }
670a50eb
ILT
932 assert (insn.insn_mo->pinfo != INSN_MACRO);
933 insn.insn_opcode = insn.insn_mo->match;
934 for (;;)
935 {
936 switch (*fmt++)
937 {
3d3c5039 938 case '\0':
670a50eb 939 break;
3d3c5039
ILT
940
941 case ',':
942 case '(':
943 case ')':
670a50eb 944 continue;
3d3c5039
ILT
945
946 case 't':
947 case 'w':
918692a5 948 case 'E':
670a50eb
ILT
949 insn.insn_opcode |= va_arg (args, int) << 16;
950 continue;
3d3c5039
ILT
951
952 case 'c':
953 case 'T':
954 case 'W':
670a50eb
ILT
955 insn.insn_opcode |= va_arg (args, int) << 16;
956 continue;
3d3c5039
ILT
957
958 case 'd':
918692a5 959 case 'G':
670a50eb
ILT
960 insn.insn_opcode |= va_arg (args, int) << 11;
961 continue;
3d3c5039
ILT
962
963 case 'V':
964 case 'S':
670a50eb
ILT
965 insn.insn_opcode |= va_arg (args, int) << 11;
966 continue;
3d3c5039
ILT
967
968 case '<':
670a50eb
ILT
969 insn.insn_opcode |= va_arg (args, int) << 6;
970 continue;
3d3c5039
ILT
971
972 case 'D':
670a50eb
ILT
973 insn.insn_opcode |= va_arg (args, int) << 6;
974 continue;
3d3c5039 975
918692a5
ILT
976 case 'B':
977 insn.insn_opcode |= va_arg (args, int) << 6;
978 continue;
979
3d3c5039
ILT
980 case 'b':
981 case 's':
982 case 'r':
983 case 'v':
670a50eb
ILT
984 insn.insn_opcode |= va_arg (args, int) << 21;
985 continue;
3d3c5039
ILT
986
987 case 'i':
988 case 'j':
989 case 'o':
670a50eb
ILT
990 r = BFD_RELOC_LO16;
991 continue;
3d3c5039
ILT
992
993 case 'p':
670a50eb
ILT
994 assert (ep != NULL);
995 /*
996 * This allows macro() to pass an immediate expression for
997 * creating short branches without creating a symbol.
998 * Note that the expression still might come from the assembly
999 * input, in which case the value is not checked for range nor
1000 * is a relocation entry generated (yuck).
1001 */
5ac34ac3 1002 if (ep->X_op == O_constant)
670a50eb
ILT
1003 {
1004 insn.insn_opcode |= (ep->X_add_number >> 2) & 0xffff;
1005 ep = NULL;
1006 }
1007 else
1008 r = BFD_RELOC_16_PCREL_S2;
1009 continue;
3d3c5039
ILT
1010
1011 default:
670a50eb 1012 internalError ();
3d3c5039 1013 }
670a50eb 1014 break;
3d3c5039 1015 }
670a50eb
ILT
1016 va_end (args);
1017 assert (r == BFD_RELOC_UNUSED ? ep == NULL : ep != NULL);
1018
1019 /* Use GP relative addressing if possible. */
1020 if (r == BFD_RELOC_LO16
1021 && gp_reference (ep))
1022 r = BFD_RELOC_MIPS_GPREL;
1023
1024 append_insn (&insn, ep, r);
3d3c5039
ILT
1025}
1026
1027/*
1028 * Generate a "lui" instruction.
1029 */
1030static void
1031macro_build_lui (counter, ep, regnum)
1032 int *counter;
1033 expressionS *ep;
1034 int regnum;
1035{
670a50eb
ILT
1036 expressionS high_expr;
1037 struct mips_cl_insn insn;
1038 bfd_reloc_code_real_type r;
1039 CONST char *name = "lui";
1040 CONST char *fmt = "t,u";
1041
1042 high_expr = *ep;
1043
5ac34ac3 1044 if (high_expr.X_op == O_constant)
670a50eb
ILT
1045 {
1046 /* we can compute the instruction now without a relocation entry */
1047 if (high_expr.X_add_number & 0x8000)
1048 high_expr.X_add_number += 0x10000;
1049 high_expr.X_add_number =
1050 ((unsigned long) high_expr.X_add_number >> 16) & 0xffff;
1051 r = BFD_RELOC_UNUSED;
1052 }
1053 else
1054 r = BFD_RELOC_HI16_S;
1055
1056 /*
1057 * If the macro is about to expand into a second instruction,
1058 * print a warning if needed. We need to pass ip as a parameter
1059 * to generate a better warning message here...
1060 */
1061 if (mips_warn_about_macros && *counter == 1)
1062 as_warn ("Macro instruction expanded into multiple instructions");
1063
1064 *counter += 1; /* bump instruction counter */
1065
1066 insn.insn_mo = (struct mips_opcode *) hash_find (op_hash, name);
1067 assert (insn.insn_mo);
1068 assert (strcmp (name, insn.insn_mo->name) == 0);
1069 assert (strcmp (fmt, insn.insn_mo->args) == 0);
1070
1071 insn.insn_opcode = insn.insn_mo->match | (regnum << 16);
1072 if (r == BFD_RELOC_UNUSED)
1073 {
1074 insn.insn_opcode |= high_expr.X_add_number;
1075 append_insn (&insn, NULL, r);
1076 }
1077 else
1078 append_insn (&insn, &high_expr, r);
3d3c5039
ILT
1079}
1080
1081/* set_at()
1082 * Generates code to set the $at register to true (one)
1083 * if reg is less than the immediate expression.
1084 */
1085static void
1086set_at (counter, reg)
1087 int *counter;
1088 int reg;
1089{
1090
670a50eb
ILT
1091 switch (imm_expr.X_add_number & 0xffff8000)
1092 {
1093 case 0:
1094 case 0xffff8000:
1095 macro_build (counter, &imm_expr, "slti", "t,r,j", AT, reg);
1096 return;
3d3c5039 1097
670a50eb
ILT
1098 case 0x8000:
1099 macro_build (counter, &imm_expr, "ori", "t,r,i", AT, 0);
1100 break;
3d3c5039 1101
670a50eb
ILT
1102 default:
1103 macro_build_lui (counter, &imm_expr, AT);
1104 if (imm_expr.X_add_number & 0xffff)
1105 macro_build (counter, &imm_expr, "addiu", "t,r,j", AT, AT);
1106 }
1107 macro_build (counter, NULL, "slt", "d,v,t", AT, reg, AT);
3d3c5039
ILT
1108}
1109
1110/* set_at_unsigned()
1111 * Generates code to set the $at register to true (one)
1112 * if reg is less than the immediate expression.
1113 * Unsigned comparison is perfomed.
1114 */
1115static void
1116set_at_unsigned (counter, reg)
1117 int *counter;
1118 int reg;
1119{
1120
670a50eb
ILT
1121 switch (imm_expr.X_add_number & 0xffff8000)
1122 {
1123 case 0:
1124 case 0xffff8000:
1125 macro_build (counter, &imm_expr, "sltiu", "t,r,j", AT, reg);
1126 return;
3d3c5039 1127
670a50eb
ILT
1128 case 0x8000:
1129 macro_build (counter, &imm_expr, "ori", "t,r,i", AT, 0);
1130 break;
3d3c5039 1131
670a50eb
ILT
1132 default:
1133 macro_build_lui (counter, &imm_expr, AT);
1134 if (imm_expr.X_add_number & 0xffff)
1135 macro_build (counter, &imm_expr, "addiu", "t,r,j", AT, AT);
1136 }
1137 macro_build (counter, NULL, "sltu", "d,v,t", AT, reg, AT);
3d3c5039
ILT
1138}
1139
1140static void
1141check_absolute_expr (ip, expr)
1142 struct mips_cl_insn *ip;
1143 expressionS *expr;
1144{
1145
5ac34ac3 1146 if (expr->X_op != O_constant)
670a50eb 1147 as_warn ("Instruction %s requires absolute expression", ip->insn_mo->name);
3d3c5039
ILT
1148}
1149
1150/* load_register()
1151 * This routine generates the least number of instructions neccessary to load
1152 * an absolute expression value into a register.
1153 */
1154static void
1155load_register (counter, ip, reg, ep)
670a50eb
ILT
1156 int *counter;
1157 struct mips_cl_insn *ip;
1158 int reg;
1159 expressionS *ep;
3d3c5039 1160{
670a50eb
ILT
1161 switch (ep->X_add_number & 0xffff8000)
1162 {
1163 case 0:
1164 case 0xffff8000:
1165 macro_build (counter, ep, "addiu", "t,r,j", reg, 0);
1166 break;
1167
1168 case 0x8000:
1169 macro_build (counter, ep, "ori", "t,r,i", reg, 0);
1170 break;
1171
1172 default:
1173 macro_build_lui (counter, ep, reg);
1174 if (ep->X_add_number & 0xffff)
1175 macro_build (counter, ep, "addiu", "t,r,j", reg, reg);
1176 }
3d3c5039
ILT
1177}
1178
1179
1180/*
1181 * Build macros
1182 * This routine implements the seemingly endless macro or synthesized
1183 * instructions and addressing modes in the mips assembly language. Many
1184 * of these macros are simple and are similar to each other. These could
1185 * probably be handled by some kind of table or grammer aproach instead of
1186 * this verbose method. Others are not simple macros but are more like
1187 * optimizing code generation.
1188 * One interesting optimization is when several store macros appear
1189 * consecutivly that would load AT with the upper half of the same address.
1190 * The ensuing load upper instructions are ommited. This implies some kind
1191 * of global optimization. We currently only optimize within a single macro.
1192 * For many of the load and store macros if the address is specified as a
1193 * constant expression in the first 64k of memory (ie ld $2,0x4000c) we
1194 * first load register 'at' with zero and use it as the base register. The
1195 * mips assembler simply uses register $zero. Just one tiny optimization
1196 * we're missing.
1197 */
1198static void
1199macro (ip)
1200 struct mips_cl_insn *ip;
1201{
670a50eb
ILT
1202 register int treg, sreg, dreg, breg;
1203 int tempreg;
1204 int mask;
1205 int icnt = 0;
1206 int used_at;
670a50eb
ILT
1207 expressionS expr1;
1208 const char *s;
1209 const char *fmt;
1210
1211 treg = (ip->insn_opcode >> 16) & 0x1f;
1212 dreg = (ip->insn_opcode >> 11) & 0x1f;
1213 sreg = breg = (ip->insn_opcode >> 21) & 0x1f;
1214 mask = ip->insn_mo->mask;
1215
5ac34ac3
ILT
1216 expr1.X_op = O_constant;
1217 expr1.X_op_symbol = NULL;
670a50eb
ILT
1218 expr1.X_add_symbol = NULL;
1219 expr1.X_add_number = 1;
1220
1221 switch (mask)
1222 {
3d3c5039
ILT
1223 case M_ABS:
1224 case M_ABSU:
670a50eb 1225 /*
3d3c5039
ILT
1226 Note: mips algorithm requires the move in the delay slot.
1227 <main>: bgez $a0,0x4001bc <main+12>
1228 <main+4>: move v0,$a0
1229 <main+8>: sub v0,$zero,$a0
1230 <main+12>: nop
1231 */
1232
becfe05e
ILT
1233 mips_emit_delays ();
1234 ++mips_noreorder;
3d3c5039 1235
670a50eb
ILT
1236 expr1.X_add_number = 8;
1237 macro_build (&icnt, &expr1, "bgez", "s,p", sreg);
1238 macro_build (&icnt, NULL, "move", "d,s", dreg, sreg, 0);
1239 macro_build (&icnt, NULL, mask == M_ABS ? "sub" : "subu", "d,v,t",
1240 dreg, 0, sreg);
3d3c5039 1241
becfe05e 1242 --mips_noreorder;
670a50eb 1243 return;
3d3c5039
ILT
1244
1245 case M_ADD_I:
1246 case M_ADDU_I:
670a50eb
ILT
1247 switch (imm_expr.X_add_number & 0xffff8000)
1248 {
1249 case 0:
1250 case 0xffff8000:
1251 macro_build (&icnt, &imm_expr,
1252 mask == M_ADD_I ? "addi" : "addiu", "t,r,j", treg, sreg);
1253 return;
3d3c5039 1254
670a50eb
ILT
1255 case 0x8000:
1256 macro_build (&icnt, &imm_expr, "ori", "t,r,i", AT, 0);
1257 break;
1258
1259 default:
1260 macro_build_lui (&icnt, &imm_expr, AT);
1261 if (imm_expr.X_add_number & 0xffff)
1262 macro_build (&icnt, &imm_expr, "addiu", "t,r,j", AT, AT);
1263 break;
3d3c5039 1264 }
670a50eb
ILT
1265 macro_build (&icnt, NULL,
1266 mask == M_ADD_I ? "add" : "addu", "d,v,t", treg, sreg, AT);
1267 break;
3d3c5039
ILT
1268
1269 case M_AND_I:
1270 case M_OR_I:
1271 case M_NOR_I:
1272 case M_XOR_I:
670a50eb
ILT
1273 switch (imm_expr.X_add_number & 0xffff8000)
1274 {
3d3c5039
ILT
1275 case 0:
1276 case 0x8000:
670a50eb
ILT
1277 switch (mask)
1278 {
3d3c5039 1279 case M_AND_I:
670a50eb
ILT
1280 macro_build (&icnt, &imm_expr, "andi", "t,r,i", treg, sreg);
1281 return;
3d3c5039 1282 case M_OR_I:
670a50eb
ILT
1283 macro_build (&icnt, &imm_expr, "ori", "t,r,i", treg, sreg);
1284 return;
3d3c5039 1285 case M_NOR_I:
670a50eb
ILT
1286 macro_build (&icnt, &imm_expr, "ori", "t,r,i", treg, sreg);
1287 macro_build (&icnt, &imm_expr, "nor", "d,v,t", treg, treg, 0);
1288 return;
3d3c5039 1289 case M_XOR_I:
670a50eb
ILT
1290 macro_build (&icnt, &imm_expr, "xori", "t,r,i", treg, sreg);
1291 return;
3d3c5039 1292 default:
670a50eb 1293 internalError ();
3d3c5039
ILT
1294 }
1295
1296 case 0xffff8000:
670a50eb
ILT
1297 macro_build (&icnt, &imm_expr, "addiu", "t,r,j", AT, 0);
1298 break;
3d3c5039
ILT
1299
1300 default:
670a50eb
ILT
1301 macro_build_lui (&icnt, &imm_expr, AT);
1302 if (imm_expr.X_add_number & 0xffff)
1303 macro_build (&icnt, &imm_expr, "addiu", "t,r,j", AT, AT);
3d3c5039 1304 }
670a50eb
ILT
1305 switch (mask)
1306 {
3d3c5039 1307 case M_AND_I:
670a50eb
ILT
1308 macro_build (&icnt, NULL, "and", "d,v,t", treg, sreg, AT);
1309 break;
3d3c5039 1310 case M_OR_I:
670a50eb
ILT
1311 macro_build (&icnt, NULL, "or", "d,v,t", treg, sreg, AT);
1312 break;
3d3c5039 1313 case M_NOR_I:
670a50eb
ILT
1314 macro_build (&icnt, NULL, "nor", "d,v,t", treg, sreg, AT);
1315 break;
3d3c5039 1316 case M_XOR_I:
670a50eb
ILT
1317 macro_build (&icnt, NULL, "xor", "d,v,t", treg, sreg, AT);
1318 break;
3d3c5039 1319 default:
670a50eb 1320 internalError ();
3d3c5039 1321 }
670a50eb 1322 break;
3d3c5039
ILT
1323
1324 case M_BEQ_I:
1325 case M_BNE_I:
670a50eb
ILT
1326 if (imm_expr.X_add_number == 0)
1327 {
1328 macro_build (&icnt, &offset_expr, mask == M_BEQ_I ? "beq" : "bne",
1329 "s,t,p", sreg, 0);
1330 return;
1331 }
1332 load_register (&icnt, ip, AT, &imm_expr);
1333 macro_build (&icnt, &offset_expr, mask == M_BEQ_I ? "beq" : "bne",
1334 "s,t,p", sreg, AT);
1335 break;
3d3c5039
ILT
1336
1337 case M_BGE:
670a50eb
ILT
1338 if (treg == 0)
1339 {
1340 macro_build (&icnt, &offset_expr, "bgez", "s,p", sreg);
1341 return;
3d3c5039 1342 }
9a7d824a
ILT
1343 if (sreg == 0)
1344 {
1345 macro_build (&icnt, &offset_expr, "blez", "s,p", treg);
1346 return;
1347 }
670a50eb
ILT
1348 macro_build (&icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
1349 macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
1350 break;
3d3c5039
ILT
1351
1352 case M_BGT_I:
9a7d824a
ILT
1353 /* check for > max integer */
1354 if (imm_expr.X_add_number == 0x7fffffff)
1355 {
1356 do_false:
1357 /* result is always false */
1358 as_warn ("Branch %s is always false (nop)", ip->insn_mo->name);
1359 macro_build (&icnt, NULL, "nop", "", 0);
1360 return;
1361 }
670a50eb
ILT
1362 imm_expr.X_add_number++;
1363 /* FALLTHROUGH */
9a7d824a 1364
3d3c5039 1365 case M_BGE_I:
670a50eb
ILT
1366 if (imm_expr.X_add_number == 0)
1367 {
1368 macro_build (&icnt, &offset_expr, "bgez", "s,p", sreg);
1369 return;
3d3c5039 1370 }
670a50eb
ILT
1371 if (imm_expr.X_add_number == 1)
1372 {
1373 macro_build (&icnt, &offset_expr, "bgtz", "s,p", sreg);
1374 return;
3d3c5039 1375 }
9a7d824a
ILT
1376 if (imm_expr.X_add_number == 0x80000000)
1377 {
1378 do_true:
1379 /* result is always true */
1380 as_warn ("Branch %s is always true", ip->insn_mo->name);
1381 macro_build (&icnt, &offset_expr, "b", "p");
1382 return;
1383 }
670a50eb
ILT
1384 set_at (&icnt, sreg);
1385 macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
1386 break;
3d3c5039
ILT
1387
1388 case M_BGEU:
670a50eb 1389 if (treg == 0)
9a7d824a
ILT
1390 goto do_true;
1391 if (sreg == 0)
670a50eb 1392 {
9a7d824a 1393 macro_build (&icnt, &offset_expr, "beq", "s,t,p", 0, treg);
670a50eb 1394 return;
3d3c5039 1395 }
670a50eb
ILT
1396 macro_build (&icnt, NULL, "sltu", "d,v,t", AT, sreg, treg);
1397 macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
1398 break;
3d3c5039 1399
9a7d824a
ILT
1400 case M_BGTU_I:
1401 if (sreg == 0 || imm_expr.X_add_number == 0xffffffff)
1402 goto do_false;
1403 imm_expr.X_add_number++;
1404 /* FALLTHROUGH */
1405
3d3c5039 1406 case M_BGEU_I:
670a50eb 1407 if (imm_expr.X_add_number == 0)
9a7d824a 1408 goto do_true;
670a50eb
ILT
1409 if (imm_expr.X_add_number == 1)
1410 {
1411 macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0);
1412 return;
3d3c5039 1413 }
670a50eb
ILT
1414 set_at_unsigned (&icnt, sreg);
1415 macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
1416 break;
3d3c5039
ILT
1417
1418 case M_BGT:
670a50eb
ILT
1419 if (treg == 0)
1420 {
1421 macro_build (&icnt, &offset_expr, "bgtz", "s,p", sreg);
1422 return;
3d3c5039 1423 }
9a7d824a
ILT
1424 if (sreg == 0)
1425 {
1426 macro_build (&icnt, &offset_expr, "bltz", "s,p", treg);
1427 return;
1428 }
670a50eb
ILT
1429 macro_build (&icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
1430 macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
1431 break;
3d3c5039
ILT
1432
1433 case M_BGTU:
670a50eb
ILT
1434 if (treg == 0)
1435 {
1436 macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0);
1437 return;
3d3c5039 1438 }
9a7d824a
ILT
1439 if (sreg == 0)
1440 goto do_false;
670a50eb
ILT
1441 macro_build (&icnt, NULL, "sltu", "d,v,t", AT, treg, sreg);
1442 macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
1443 break;
3d3c5039 1444
3d3c5039 1445 case M_BLE:
670a50eb
ILT
1446 if (treg == 0)
1447 {
1448 macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
1449 return;
1450 }
9a7d824a
ILT
1451 if (sreg == 0)
1452 {
1453 macro_build (&icnt, &offset_expr, "bgez", "s,p", treg);
1454 return;
1455 }
670a50eb
ILT
1456 macro_build (&icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
1457 macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
1458 break;
3d3c5039
ILT
1459
1460 case M_BLE_I:
9a7d824a
ILT
1461 if (imm_expr.X_add_number == 0x7fffffff)
1462 goto do_true;
1463 imm_expr.X_add_number++;
1464 /* FALLTHROUGH */
1465
1466 case M_BLT_I:
670a50eb
ILT
1467 if (imm_expr.X_add_number == 0)
1468 {
9a7d824a 1469 macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
670a50eb
ILT
1470 return;
1471 }
9a7d824a 1472 if (imm_expr.X_add_number == 1)
670a50eb 1473 {
9a7d824a 1474 macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
670a50eb
ILT
1475 return;
1476 }
670a50eb
ILT
1477 set_at (&icnt, sreg);
1478 macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
1479 break;
3d3c5039
ILT
1480
1481 case M_BLEU:
670a50eb
ILT
1482 if (treg == 0)
1483 {
1484 macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0);
1485 return;
3d3c5039 1486 }
9a7d824a
ILT
1487 if (sreg == 0)
1488 goto do_true;
670a50eb
ILT
1489 macro_build (&icnt, NULL, "sltu", "d,v,t", AT, treg, sreg);
1490 macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
1491 break;
3d3c5039
ILT
1492
1493 case M_BLEU_I:
9a7d824a
ILT
1494 if (sreg == 0 || imm_expr.X_add_number == 0xffffffff)
1495 goto do_true;
1496 imm_expr.X_add_number++;
1497 /* FALLTHROUGH */
1498
1499 case M_BLTU_I:
670a50eb 1500 if (imm_expr.X_add_number == 0)
9a7d824a
ILT
1501 goto do_false;
1502 if (imm_expr.X_add_number == 1)
670a50eb
ILT
1503 {
1504 macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0);
1505 return;
3d3c5039 1506 }
670a50eb
ILT
1507 set_at_unsigned (&icnt, sreg);
1508 macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
1509 break;
3d3c5039
ILT
1510
1511 case M_BLT:
670a50eb
ILT
1512 if (treg == 0)
1513 {
1514 macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
1515 return;
3d3c5039 1516 }
9a7d824a 1517 if (sreg == 0)
670a50eb 1518 {
9a7d824a 1519 macro_build (&icnt, &offset_expr, "bgtz", "s,p", treg);
670a50eb 1520 return;
3d3c5039 1521 }
9a7d824a 1522 macro_build (&icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
670a50eb
ILT
1523 macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
1524 break;
3d3c5039
ILT
1525
1526 case M_BLTU:
670a50eb 1527 if (treg == 0)
9a7d824a
ILT
1528 goto do_false;
1529 if (sreg == 0)
670a50eb 1530 {
9a7d824a 1531 macro_build (&icnt, &offset_expr, "bne", "s,t,p", 0, treg);
670a50eb
ILT
1532 return;
1533 }
1534 macro_build (&icnt, NULL, "sltu", "d,v,t", AT, sreg, treg);
1535 macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
1536 break;
3d3c5039 1537
3d3c5039
ILT
1538 case M_DIV_3:
1539 case M_REM_3:
670a50eb
ILT
1540 if (treg == 0)
1541 {
1542 as_warn ("Divide by zero.");
1543 macro_build (&icnt, NULL, "break", "c", 7);
1544 return;
1545 }
1546
becfe05e
ILT
1547 mips_emit_delays ();
1548 ++mips_noreorder;
670a50eb
ILT
1549 macro_build (&icnt, NULL, "div", "s,t", sreg, treg);
1550 expr1.X_add_number = 8;
1551 macro_build (&icnt, &expr1, "bne", "s,t,p", treg, 0);
1552 macro_build (&icnt, NULL, "nop", "", 0);
1553 macro_build (&icnt, NULL, "break", "c", 7);
1554 expr1.X_add_number = -1;
1555 macro_build (&icnt, &expr1, "addiu", "t,r,j", AT, 0);
1556 expr1.X_add_number = 16;
1557 macro_build (&icnt, &expr1, "bne", "s,t,p", treg, AT);
1558 expr1.X_add_number = 0x80000000;
1559 macro_build_lui (&icnt, &expr1, AT);
1560 expr1.X_add_number = 8;
1561 macro_build (&icnt, &expr1, "bne", "s,t,p", sreg, AT);
1562 macro_build (&icnt, NULL, "nop", "", 0);
1563 macro_build (&icnt, NULL, "break", "c", 6);
becfe05e 1564 --mips_noreorder;
670a50eb
ILT
1565 macro_build (&icnt, NULL, mask == M_DIV_3 ? "mflo" : "mfhi", "d", dreg);
1566 /* with reorder on there will be two implicit nop instructions here. */
1567 break;
3d3c5039
ILT
1568
1569 case M_DIV_3I:
1570 case M_DIVU_3I:
1571 case M_REM_3I:
1572 case M_REMU_3I:
670a50eb
ILT
1573 if (imm_expr.X_add_number == 0)
1574 {
1575 as_warn ("Divide by zero.");
1576 macro_build (&icnt, NULL, "break", "c", 7);
1577 return;
1578 }
1579 if (imm_expr.X_add_number == 1)
1580 {
1581 if (mask == (int) M_DIV_3I || mask == (int) M_DIVU_3I)
1582 macro_build (&icnt, NULL, "move", "d,s", dreg, sreg);
3d3c5039 1583 else
670a50eb 1584 macro_build (&icnt, NULL, "move", "d,s", dreg, 0);
3d3c5039
ILT
1585 return;
1586 }
1587
670a50eb
ILT
1588 load_register (&icnt, ip, AT, &imm_expr);
1589 if (mask == (int) M_DIV_3I || mask == (int) M_REM_3I)
1590 macro_build (&icnt, NULL, "div", "s,t", sreg, AT);
1591 else
1592 macro_build (&icnt, NULL, "divu", "s,t", sreg, AT);
3d3c5039 1593
670a50eb
ILT
1594 if (mask == (int) M_DIV_3I || mask == (int) M_DIVU_3I)
1595 macro_build (&icnt, NULL, "mflo", "d", dreg);
1596 else
1597 macro_build (&icnt, NULL, "mfhi", "d", dreg);
1598 /* two implicit nop's required for mflo or mfhi */
1599 break;
1600
1601 case M_DIVU_3:
1602 case M_REMU_3:
becfe05e
ILT
1603 mips_emit_delays ();
1604 ++mips_noreorder;
670a50eb
ILT
1605 macro_build (&icnt, NULL, "divu", "s,t", sreg, treg);
1606 expr1.X_add_number = 8;
1607 macro_build (&icnt, &expr1, "bne", "s,t,p", treg, 0);
1608 macro_build (&icnt, NULL, "nop", "", 0);
1609 macro_build (&icnt, NULL, "break", "c", 7);
becfe05e 1610 --mips_noreorder;
670a50eb
ILT
1611 macro_build (&icnt, NULL, mask == M_DIVU_3 ? "mflo" : "mfhi", "d", dreg);
1612 /* with reorder on there will be two implicit nop instructions here. */
1613 return;
3d3c5039
ILT
1614
1615 case M_LA:
5ac34ac3 1616 if (offset_expr.X_op == O_constant)
670a50eb
ILT
1617 {
1618 load_register (&icnt, ip, treg, &offset_expr);
1619 return;
3d3c5039 1620 }
670a50eb
ILT
1621 if (gp_reference (&offset_expr))
1622 macro_build (&icnt, &offset_expr, "addiu", "t,r,j", treg, GP);
1623 else
1624 {
1625 macro_build_lui (&icnt, &offset_expr, treg);
1626 macro_build (&icnt, &offset_expr, "addiu", "t,r,j", treg, treg);
1627 }
1628 return;
3d3c5039
ILT
1629
1630 case M_LA_AB:
670a50eb 1631 tempreg = (breg == treg) ? AT : treg;
5ac34ac3 1632 if (offset_expr.X_op == O_constant)
670a50eb
ILT
1633 load_register (&icnt, ip, tempreg, &offset_expr);
1634 else if (gp_reference (&offset_expr))
1635 macro_build (&icnt, &offset_expr, "addiu", "t,r,j", tempreg, GP);
1636 else
1637 {
1638 macro_build_lui (&icnt, &offset_expr, tempreg);
1639 macro_build (&icnt, &offset_expr, "addiu", "t,r,j", tempreg, tempreg);
1640 }
1641 if (breg != 0)
1642 macro_build (&icnt, NULL, "addu", "d,v,t", treg, tempreg, breg);
1643 if (breg == treg)
1644 break;
1645 return;
3d3c5039
ILT
1646
1647 case M_LB_AB:
670a50eb
ILT
1648 s = "lb";
1649 goto ld;
3d3c5039 1650 case M_LBU_AB:
670a50eb
ILT
1651 s = "lbu";
1652 goto ld;
3d3c5039 1653 case M_LH_AB:
670a50eb
ILT
1654 s = "lh";
1655 goto ld;
3d3c5039 1656 case M_LHU_AB:
670a50eb
ILT
1657 s = "lhu";
1658 goto ld;
3d3c5039 1659 case M_LW_AB:
670a50eb
ILT
1660 s = "lw";
1661 goto ld;
3d3c5039 1662 case M_LWC0_AB:
670a50eb
ILT
1663 s = "lwc0";
1664 goto ld;
3d3c5039 1665 case M_LWC1_AB:
670a50eb
ILT
1666 s = "lwc1";
1667 goto ld;
3d3c5039 1668 case M_LWC2_AB:
670a50eb
ILT
1669 s = "lwc2";
1670 goto ld;
3d3c5039 1671 case M_LWC3_AB:
670a50eb
ILT
1672 s = "lwc3";
1673 goto ld;
3d3c5039 1674 case M_LWL_AB:
670a50eb
ILT
1675 s = "lwl";
1676 goto ld;
3d3c5039 1677 case M_LWR_AB:
670a50eb 1678 s = "lwr";
3d3c5039 1679 ld:
670a50eb
ILT
1680 if (breg == treg || mask == M_LWC1_AB)
1681 {
1682 tempreg = AT;
1683 used_at = 1;
1684 }
1685 else
1686 {
1687 tempreg = treg;
1688 used_at = 0;
1689 }
1690 goto ld_st;
3d3c5039 1691 case M_SB_AB:
670a50eb
ILT
1692 s = "sb";
1693 goto st;
3d3c5039 1694 case M_SH_AB:
670a50eb
ILT
1695 s = "sh";
1696 goto st;
3d3c5039 1697 case M_SW_AB:
670a50eb
ILT
1698 s = "sw";
1699 goto st;
3d3c5039 1700 case M_SWC0_AB:
670a50eb
ILT
1701 s = "swc0";
1702 goto st;
3d3c5039 1703 case M_SWC1_AB:
670a50eb
ILT
1704 s = "swc1";
1705 goto st;
3d3c5039 1706 case M_SWC2_AB:
670a50eb
ILT
1707 s = "swc2";
1708 goto st;
3d3c5039 1709 case M_SWC3_AB:
670a50eb
ILT
1710 s = "swc3";
1711 goto st;
3d3c5039 1712 case M_SWL_AB:
670a50eb
ILT
1713 s = "swl";
1714 goto st;
3d3c5039 1715 case M_SWR_AB:
670a50eb 1716 s = "swr";
3d3c5039 1717 st:
670a50eb
ILT
1718 tempreg = AT;
1719 used_at = 1;
3d3c5039 1720 ld_st:
670a50eb
ILT
1721 if (mask == M_LWC1_AB || mask == M_SWC1_AB)
1722 fmt = "T,o(b)";
1723 else
1724 fmt = "t,o(b)";
1725 if (gp_reference (&offset_expr))
1726 {
1727 if (breg == 0)
1728 {
1729 macro_build (&icnt, &offset_expr, s, fmt, treg, GP);
1730 return;
1731 }
1732 macro_build (&icnt, (expressionS *) NULL, "addu", "d,v,t",
1733 tempreg, breg, GP);
1734 }
1735 else
1736 {
1737 macro_build_lui (&icnt, &offset_expr, tempreg);
1738 if (breg != 0)
1739 macro_build (&icnt, NULL, "addu", "d,v,t", tempreg, tempreg, breg);
1740 }
1741 macro_build (&icnt, &offset_expr, s, fmt, treg, tempreg);
1742 if (used_at)
1743 break;
1744 return;
3d3c5039
ILT
1745
1746 case M_LI:
670a50eb
ILT
1747 load_register (&icnt, ip, treg, &imm_expr);
1748 return;
3d3c5039
ILT
1749
1750 case M_LI_D:
670a50eb 1751 /*
3d3c5039
ILT
1752 0x400370 <main>: lui $at,%hi(foo)
1753 0x400374 <main+4>: lw $v0,%lo(foo)($at)
1754 0x400378 <main+8>: lw $v1,%lo(foo+4)($at)
1755 .data
1756 <foo>:
1757 .float 3.133435
1758 */
670a50eb
ILT
1759 /* FIXME: I don't think this is used at present, because the 'F'
1760 format character is not supported. When this is supported,
1761 it should use the GP register. */
1762 macro_build_lui (&icnt, &offset_expr, AT);
1763 macro_build (&icnt, &offset_expr, "lw", "t,o(b)", treg, AT);
1764 offset_expr.X_add_number = 4;
1765 macro_build (&icnt, &offset_expr, "lw", "t,o(b)", treg + 1, AT);
1766 break;
3d3c5039
ILT
1767
1768 case M_LI_DD:
670a50eb 1769 /*
3d3c5039
ILT
1770 0x4003a0 <main>: lwc1 $f0,-32752($gp)
1771 0x4003a4 <main+4>: lwc1 $f1,-32748($gp)
1772 0x4003a8 <main+8>: nop
1773 */
670a50eb
ILT
1774 /* FIXME: This is nonsense. It isn't used anyhow. */
1775 sreg = (ip->insn_opcode >> 11) & 0x1f; /* Fs reg */
1776 macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg, AT);
1777 offset_expr.X_add_number = 4;
1778 macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg + 1, AT);
1779 break;
3d3c5039
ILT
1780
1781 case M_L_DOB:
9a7d824a
ILT
1782 /* Even on a big endian machine $fn comes before $fn+1. We have
1783 to adjust when loading from memory. */
9a7d824a
ILT
1784 macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
1785 byte_order == LITTLE_ENDIAN ? treg : treg + 1,
1786 breg);
670a50eb 1787 offset_expr.X_add_number += 4;
9a7d824a
ILT
1788 macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
1789 byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
1790 breg);
670a50eb 1791 return;
3d3c5039
ILT
1792
1793 case M_L_DAB:
670a50eb
ILT
1794 /*
1795 * The MIPS assembler seems to check for X_add_number not
1796 * being double aligned and generating:
1797 * lui at,%hi(foo+1)
1798 * addu at,at,v1
1799 * addiu at,at,%lo(foo+1)
1800 * lwc1 f2,0(at)
1801 * lwc1 f3,4(at)
1802 * But, the resulting address is the same after relocation so why
1803 * generate the extra instruction?
1804 */
1805 if (gp_reference (&offset_expr))
1806 {
1807 if (breg == 0)
1808 tempreg = GP;
1809 else
1810 {
1811 macro_build (&icnt, &offset_expr, "addu", "d,v,t", AT, breg, GP);
1812 tempreg = AT;
1813 }
1814 }
1815 else
1816 {
1817 macro_build_lui (&icnt, &offset_expr, AT);
1818 if (breg != 0)
1819 macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg);
1820 tempreg = AT;
1821 }
9a7d824a
ILT
1822 /* Even on a big endian machine $fn comes before $fn+1. We have
1823 to adjust when loading from memory. */
9a7d824a
ILT
1824 macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
1825 byte_order == LITTLE_ENDIAN ? treg : treg + 1,
1826 tempreg);
670a50eb 1827 offset_expr.X_add_number += 4;
9a7d824a
ILT
1828 macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
1829 byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
1830 tempreg);
670a50eb 1831 if (tempreg == AT)
3d3c5039 1832 break;
670a50eb 1833 return;
3d3c5039
ILT
1834
1835 case M_LD_OB:
670a50eb
ILT
1836 s = "lw";
1837 goto sd_ob;
3d3c5039 1838 case M_SD_OB:
670a50eb 1839 s = "sw";
3d3c5039 1840 sd_ob:
670a50eb
ILT
1841 macro_build (&icnt, &offset_expr, s, "t,o(b)", treg, breg);
1842 offset_expr.X_add_number = 4;
1843 macro_build (&icnt, &offset_expr, s, "t,o(b)", treg + 1, breg);
1844 return;
3d3c5039
ILT
1845
1846 case M_LD_AB:
670a50eb
ILT
1847 s = "lw";
1848 if (breg == treg)
1849 {
1850 tempreg = AT;
1851 used_at = 1;
1852 }
1853 else
1854 {
1855 tempreg = treg;
1856 used_at = 0;
1857 }
1858 goto sd_ab;
3d3c5039 1859 case M_SD_AB:
670a50eb
ILT
1860 s = "sw";
1861 tempreg = AT;
1862 used_at = 1;
3d3c5039 1863 sd_ab:
670a50eb
ILT
1864 if (gp_reference (&offset_expr))
1865 {
1866 if (breg == 0)
1867 {
1868 tempreg = GP;
1869 used_at = 0;
1870 }
1871 else
1872 macro_build (&icnt, (expressionS *) NULL, "addu", "d,v,t",
1873 tempreg, breg, GP);
1874 }
1875 else
1876 {
1877 macro_build_lui (&icnt, &offset_expr, tempreg);
1878 if (breg != 0)
1879 macro_build (&icnt, NULL, "addu", "d,v,t", tempreg, tempreg, breg);
1880 }
1881 macro_build (&icnt, &offset_expr, s, "t,o(b)", treg, tempreg);
1882 offset_expr.X_add_number += 4;
1883 macro_build (&icnt, &offset_expr, s, "t,o(b)", treg + 1, tempreg);
1884 if (used_at)
1885 break;
1886 return;
3d3c5039
ILT
1887
1888 case M_MUL:
670a50eb
ILT
1889 macro_build (&icnt, NULL, "multu", "s,t", sreg, treg);
1890 macro_build (&icnt, NULL, "mflo", "d", dreg);
1891 /* two implicit nop's required for mflo */
1892 return;
3d3c5039
ILT
1893
1894 case M_MUL_I:
670a50eb
ILT
1895 /*
1896 * The mips assembler some times generates shifts and adds.
1897 * Im not trying to be that fancy. GCC should do this for us
1898 * anyway.
1899 */
1900 load_register (&icnt, ip, AT, &imm_expr);
1901 macro_build (&icnt, NULL, "mult", "s,t", sreg, AT);
1902 macro_build (&icnt, NULL, "mflo", "d", dreg);
1903 /* two implicit nop's required for mflo */
1904 break;
3d3c5039
ILT
1905
1906 case M_ROL:
670a50eb
ILT
1907 macro_build (&icnt, NULL, "subu", "d,v,t", AT, 0, treg);
1908 macro_build (&icnt, NULL, "srlv", "d,t,s", AT, sreg, AT);
1909 macro_build (&icnt, NULL, "sllv", "d,t,s", dreg, sreg, treg);
1910 macro_build (&icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
1911 break;
3d3c5039
ILT
1912
1913 case M_ROL_I:
670a50eb
ILT
1914 macro_build (&icnt, NULL, "sll", "d,w,<", AT, sreg,
1915 imm_expr.X_add_number & 0x1f);
1916 macro_build (&icnt, NULL, "srl", "d,w,<", dreg, sreg,
1917 (0 - imm_expr.X_add_number) & 0x1f);
1918 macro_build (&icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
1919 break;
3d3c5039
ILT
1920
1921 case M_ROR:
670a50eb
ILT
1922 macro_build (&icnt, NULL, "subu", "d,v,t", AT, 0, treg);
1923 macro_build (&icnt, NULL, "sllv", "d,t,s", AT, sreg, AT);
1924 macro_build (&icnt, NULL, "srlv", "d,t,s", dreg, sreg, treg);
1925 macro_build (&icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
1926 break;
3d3c5039
ILT
1927
1928 case M_ROR_I:
670a50eb
ILT
1929 macro_build (&icnt, NULL, "srl", "d,w,<", AT, sreg,
1930 imm_expr.X_add_number & 0x1f);
1931 macro_build (&icnt, NULL, "sll", "d,w,<", dreg, sreg,
1932 (0 - imm_expr.X_add_number) & 0x1f);
1933 macro_build (&icnt, NULL, "or", "d,v,t", dreg, dreg, AT);
1934 break;
3d3c5039
ILT
1935
1936 case M_S_DOB:
9a7d824a
ILT
1937 /* Even on a big endian machine $fn comes before $fn+1. We have
1938 to adjust when storing to memory. */
1939 macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
1940 byte_order == LITTLE_ENDIAN ? treg : treg + 1,
1941 breg);
670a50eb 1942 offset_expr.X_add_number += 4;
9a7d824a
ILT
1943 macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
1944 byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
1945 breg);
670a50eb 1946 return;
3d3c5039
ILT
1947
1948 case M_S_DAB:
670a50eb
ILT
1949 if (gp_reference (&offset_expr))
1950 {
1951 if (breg == 0)
1952 tempreg = GP;
1953 else
1954 {
1955 macro_build (&icnt, (expressionS *) NULL, "addu", "d,v,t",
1956 AT, breg, GP);
1957 tempreg = AT;
1958 }
1959 }
1960 else
1961 {
1962 macro_build_lui (&icnt, &offset_expr, AT);
1963 if (breg != 0)
1964 macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg);
1965 tempreg = AT;
1966 }
9a7d824a
ILT
1967 /* Even on a big endian machine $fn comes before $fn+1. We have
1968 to adjust when storing to memory. */
1969 macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
1970 byte_order == LITTLE_ENDIAN ? treg : treg + 1,
1971 tempreg);
670a50eb 1972 offset_expr.X_add_number += 4;
9a7d824a
ILT
1973 macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
1974 byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
1975 tempreg);
670a50eb 1976 if (tempreg == AT)
3d3c5039 1977 break;
670a50eb 1978 return;
3d3c5039
ILT
1979
1980 case M_SEQ:
670a50eb
ILT
1981 if (sreg == 0)
1982 macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, treg);
1983 else if (treg == 0)
1984 macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, sreg);
1985 else
1986 {
1987 macro_build (&icnt, NULL, "xor", "d,v,t", dreg, sreg, treg);
1988 macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, dreg);
3d3c5039 1989 }
670a50eb 1990 return;
3d3c5039
ILT
1991
1992 case M_SEQ_I:
670a50eb
ILT
1993 if (imm_expr.X_add_number == 0)
1994 {
1995 macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, sreg);
1996 return;
3d3c5039 1997 }
670a50eb
ILT
1998 if (sreg == 0)
1999 {
9a7d824a
ILT
2000 as_warn ("Instruction %s: result is always false",
2001 ip->insn_mo->name);
670a50eb
ILT
2002 macro_build (&icnt, NULL, "move", "d,s", dreg, 0);
2003 return;
3d3c5039 2004 }
670a50eb
ILT
2005 switch (imm_expr.X_add_number & 0xffff8000)
2006 {
3d3c5039
ILT
2007 case 0:
2008 case 0x8000:
670a50eb
ILT
2009 macro_build (&icnt, &imm_expr, "xori", "t,r,i", dreg, sreg);
2010 used_at = 0;
2011 break;
3d3c5039
ILT
2012
2013 case 0xffff8000:
670a50eb
ILT
2014 if (imm_expr.X_add_number != -32768)
2015 {
2016 imm_expr.X_add_number = -imm_expr.X_add_number;
2017 macro_build (&icnt, &imm_expr, "addiu", "t,r,j", dreg, sreg);
2018 used_at = 0;
2019 break;
3d3c5039 2020 }
670a50eb 2021 /* FALLTHROUGH */
3d3c5039
ILT
2022
2023 default:
670a50eb
ILT
2024 macro_build_lui (&icnt, &imm_expr, AT);
2025 if (imm_expr.X_add_number & 0xffff)
2026 macro_build (&icnt, &imm_expr, "addiu", "t,r,j", AT, AT);
2027 macro_build (&icnt, NULL, "xor", "d,v,t", dreg, sreg, AT);
2028 used_at = 1;
2029 }
2030 macro_build (&icnt, &expr1, "sltiu", "t,r,j", dreg, dreg);
2031 if (used_at)
2032 break;
2033 return;
3d3c5039
ILT
2034
2035 case M_SGE: /* sreg >= treg <==> not (sreg < treg) */
670a50eb
ILT
2036 s = "slt";
2037 goto sge;
3d3c5039 2038 case M_SGEU:
670a50eb 2039 s = "sltu";
3d3c5039 2040 sge:
670a50eb
ILT
2041 macro_build (&icnt, NULL, s, "d,v,t", dreg, sreg, treg);
2042 macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg);
2043 return;
3d3c5039 2044
670a50eb 2045 case M_SGE_I: /* sreg >= I <==> not (sreg < I) */
3d3c5039 2046 case M_SGEU_I:
670a50eb
ILT
2047 if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32769)
2048 {
2049 macro_build (&icnt, &expr1,
2050 mask == M_SGE_I ? "slti" : "sltiu", "t,r,j", dreg, sreg);
2051 used_at = 0;
2052 }
2053 else
2054 {
2055 load_register (&icnt, ip, AT, &imm_expr);
2056 macro_build (&icnt, NULL,
2057 mask == M_SGE_I ? "slt" : "sltu", "d,v,t", dreg, sreg, AT);
2058 used_at = 1;
2059 }
2060 macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg);
2061 if (used_at)
2062 break;
2063 return;
3d3c5039
ILT
2064
2065 case M_SGT: /* sreg > treg <==> treg < sreg */
670a50eb
ILT
2066 s = "slt";
2067 goto sgt;
3d3c5039 2068 case M_SGTU:
670a50eb 2069 s = "sltu";
3d3c5039 2070 sgt:
670a50eb
ILT
2071 macro_build (&icnt, NULL, s, "d,v,t", dreg, treg, sreg);
2072 return;
3d3c5039 2073
670a50eb
ILT
2074 case M_SGT_I: /* sreg > I <==> I < sreg */
2075 s = "slt";
2076 goto sgti;
3d3c5039 2077 case M_SGTU_I:
670a50eb 2078 s = "sltu";
3d3c5039 2079 sgti:
670a50eb
ILT
2080 load_register (&icnt, ip, AT, &imm_expr);
2081 macro_build (&icnt, NULL, s, "d,v,t", dreg, AT, sreg);
2082 break;
3d3c5039 2083
670a50eb
ILT
2084 case M_SLE: /* sreg <= treg <==> treg >= sreg <==> not (treg < sreg) */
2085 s = "slt";
2086 goto sle;
3d3c5039 2087 case M_SLEU:
670a50eb 2088 s = "sltu";
3d3c5039 2089 sle:
670a50eb 2090 macro_build (&icnt, NULL, s, "d,v,t", dreg, treg, sreg);
9a7d824a 2091 macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg);
670a50eb 2092 return;
3d3c5039 2093
670a50eb
ILT
2094 case M_SLE_I: /* sreg <= I <==> I >= sreg <==> not (I < sreg) */
2095 s = "slt";
2096 goto slei;
3d3c5039 2097 case M_SLEU_I:
670a50eb 2098 s = "sltu";
3d3c5039 2099 slei:
670a50eb
ILT
2100 load_register (&icnt, ip, AT, &imm_expr);
2101 macro_build (&icnt, NULL, s, "d,v,t", dreg, AT, sreg);
9a7d824a 2102 macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg);
670a50eb 2103 break;
3d3c5039
ILT
2104
2105 case M_SLT_I:
670a50eb
ILT
2106 if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32769)
2107 {
2108 macro_build (&icnt, &imm_expr, "slti", "t,r,j", dreg, sreg);
2109 return;
3d3c5039 2110 }
670a50eb
ILT
2111 load_register (&icnt, ip, AT, &imm_expr);
2112 macro_build (&icnt, NULL, "slt", "d,v,t", dreg, sreg, AT);
2113 break;
3d3c5039
ILT
2114
2115 case M_SLTU_I:
670a50eb
ILT
2116 if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32769)
2117 {
2118 macro_build (&icnt, &imm_expr, "sltiu", "t,r,j", dreg, sreg);
2119 return;
3d3c5039 2120 }
670a50eb
ILT
2121 load_register (&icnt, ip, AT, &imm_expr);
2122 macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, sreg, AT);
2123 break;
3d3c5039
ILT
2124
2125 case M_SNE:
670a50eb
ILT
2126 if (sreg == 0)
2127 macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, treg);
2128 else if (treg == 0)
2129 macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, sreg);
2130 else
2131 {
2132 macro_build (&icnt, NULL, "xor", "d,v,t", dreg, sreg, treg);
2133 macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg);
3d3c5039 2134 }
670a50eb 2135 return;
3d3c5039
ILT
2136
2137 case M_SNE_I:
670a50eb
ILT
2138 if (imm_expr.X_add_number == 0)
2139 {
2140 macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, sreg);
2141 return;
3d3c5039 2142 }
670a50eb
ILT
2143 if (sreg == 0)
2144 {
9a7d824a
ILT
2145 as_warn ("Instruction %s: result is always true",
2146 ip->insn_mo->name);
670a50eb
ILT
2147 macro_build (&icnt, &expr1, "addiu", "t,r,j", dreg, 0);
2148 return;
3d3c5039 2149 }
670a50eb
ILT
2150 switch (imm_expr.X_add_number & 0xffff8000)
2151 {
3d3c5039
ILT
2152 case 0:
2153 case 0x8000:
670a50eb
ILT
2154 macro_build (&icnt, &imm_expr, "xori", "t,r,i", dreg, sreg);
2155 used_at = 0;
2156 break;
3d3c5039
ILT
2157
2158 case 0xffff8000:
670a50eb
ILT
2159 if (imm_expr.X_add_number != -32768)
2160 {
2161 imm_expr.X_add_number = -imm_expr.X_add_number;
2162 macro_build (&icnt, &imm_expr, "addiu", "t,r,j", dreg, sreg);
2163 used_at = 0;
2164 break;
3d3c5039 2165 }
670a50eb 2166 /* FALLTHROUGH */
3d3c5039
ILT
2167
2168 default:
670a50eb
ILT
2169 macro_build_lui (&icnt, &imm_expr, AT);
2170 if (imm_expr.X_add_number & 0xffff)
2171 macro_build (&icnt, &imm_expr, "addiu", "t,r,j", AT, AT);
2172 macro_build (&icnt, NULL, "xor", "d,v,t", dreg, sreg, AT);
2173 used_at = 1;
2174 }
2175 macro_build (&icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg);
2176 if (used_at)
2177 break;
2178 return;
3d3c5039
ILT
2179
2180 case M_SUB_I:
670a50eb
ILT
2181 if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32768)
2182 {
2183 imm_expr.X_add_number = -imm_expr.X_add_number;
2184 macro_build (&icnt, &imm_expr, "addi", "t,r,j", dreg, sreg);
2185 return;
3d3c5039 2186 }
670a50eb
ILT
2187 load_register (&icnt, ip, AT, &imm_expr);
2188 macro_build (&icnt, NULL, "sub", "d,v,t", dreg, sreg, AT);
2189 break;
3d3c5039
ILT
2190
2191 case M_SUBU_I:
670a50eb
ILT
2192 if (imm_expr.X_add_number < 32768 && imm_expr.X_add_number > -32768)
2193 {
2194 imm_expr.X_add_number = -imm_expr.X_add_number;
2195 macro_build (&icnt, &imm_expr, "addiu", "t,r,j", dreg, sreg);
2196 return;
3d3c5039 2197 }
670a50eb
ILT
2198 load_register (&icnt, ip, AT, &imm_expr);
2199 macro_build (&icnt, NULL, "subu", "d,v,t", dreg, sreg, AT);
2200 break;
3d3c5039
ILT
2201
2202 case M_TRUNCWD:
2203 case M_TRUNCWS:
670a50eb
ILT
2204 sreg = (ip->insn_opcode >> 11) & 0x1f; /* floating reg */
2205 dreg = (ip->insn_opcode >> 06) & 0x1f; /* floating reg */
2206
2207 /*
2208 * Is the double cfc1 instruction a bug in the mips assembler;
2209 * or is there a reason for it?
2210 */
becfe05e
ILT
2211 mips_emit_delays ();
2212 ++mips_noreorder;
918692a5
ILT
2213 macro_build (&icnt, NULL, "cfc1", "t,G", treg, 31);
2214 macro_build (&icnt, NULL, "cfc1", "t,G", treg, 31);
670a50eb
ILT
2215 macro_build (&icnt, NULL, "nop", "");
2216 expr1.X_add_number = 3;
2217 macro_build (&icnt, &expr1, "ori", "t,r,i", AT, treg);
2218 expr1.X_add_number = 2;
2219 macro_build (&icnt, &expr1, "xori", "t,r,i", AT, AT);
918692a5 2220 macro_build (&icnt, NULL, "ctc1", "t,G", AT, 31);
670a50eb
ILT
2221 macro_build (&icnt, NULL, "nop", "");
2222 macro_build (&icnt, NULL,
2223 mask == M_TRUNCWD ? "cvt.w.d" : "cvt.w.s", "D,S", dreg, sreg);
918692a5 2224 macro_build (&icnt, NULL, "ctc1", "t,G", treg, 31);
670a50eb 2225 macro_build (&icnt, NULL, "nop", "");
becfe05e 2226 --mips_noreorder;
670a50eb 2227 break;
3d3c5039
ILT
2228
2229 case M_ULH:
670a50eb
ILT
2230 s = "lb";
2231 goto ulh;
3d3c5039 2232 case M_ULHU:
670a50eb 2233 s = "lbu";
3d3c5039 2234 ulh:
670a50eb
ILT
2235 /* avoid load delay */
2236 offset_expr.X_add_number += 1;
2237 macro_build (&icnt, &offset_expr, s, "t,o(b)", treg, breg);
2238 offset_expr.X_add_number -= 1;
2239 macro_build (&icnt, &offset_expr, "lbu", "t,o(b)", AT, breg);
2240 macro_build (&icnt, NULL, "sll", "d,w,<", treg, treg, 8);
2241 macro_build (&icnt, NULL, "or", "d,v,t", treg, treg, AT);
2242 break;
3d3c5039
ILT
2243
2244 case M_ULW:
670a50eb
ILT
2245 /* does this work on a big endian machine? */
2246 offset_expr.X_add_number += 3;
2247 macro_build (&icnt, &offset_expr, "lwl", "t,o(b)", treg, breg);
2248 offset_expr.X_add_number -= 3;
2249 macro_build (&icnt, &offset_expr, "lwr", "t,o(b)", treg, breg);
2250 return;
3d3c5039
ILT
2251
2252 case M_ULH_A:
2253 case M_ULHU_A:
2254 case M_ULW_A:
5ac34ac3 2255 if (offset_expr.X_op == O_constant)
670a50eb
ILT
2256 load_register (&icnt, ip, AT, &offset_expr);
2257 else if (gp_reference (&offset_expr))
2258 macro_build (&icnt, &offset_expr, "addiu", "t,r,j", AT, GP);
2259 else
2260 {
2261 macro_build_lui (&icnt, &offset_expr, AT);
2262 macro_build (&icnt, &offset_expr, "addiu", "t,r,j", AT, AT);
3d3c5039 2263 }
670a50eb
ILT
2264 if (mask == M_ULW_A)
2265 {
2266 expr1.X_add_number = 3;
2267 macro_build (&icnt, &expr1, "lwl", "t,o(b)", treg, AT);
2268 imm_expr.X_add_number = 0;
2269 macro_build (&icnt, &expr1, "lwr", "t,o(b)", treg, AT);
2270 }
2271 else
2272 {
2273 macro_build (&icnt, &expr1,
2274 mask == M_ULH_A ? "lb" : "lbu", "t,o(b)", treg, AT);
2275 imm_expr.X_add_number = 0;
2276 macro_build (&icnt, &expr1, "lbu", "t,o(b)", AT, AT);
2277 macro_build (&icnt, NULL, "sll", "d,w,<", treg, treg, 8);
2278 macro_build (&icnt, NULL, "or", "d,v,t", treg, treg, AT);
2279 }
2280 break;
3d3c5039
ILT
2281
2282 case M_USH:
670a50eb
ILT
2283 macro_build (&icnt, &offset_expr, "sb", "t,o(b)", treg, breg);
2284 macro_build (&icnt, NULL, "srl", "d,w,<", AT, treg, 8);
2285 offset_expr.X_add_number += 1;
2286 macro_build (&icnt, &offset_expr, "sb", "t,o(b)", AT, breg);
2287 break;
3d3c5039
ILT
2288
2289 case M_USW:
670a50eb
ILT
2290 offset_expr.X_add_number += 3;
2291 macro_build (&icnt, &offset_expr, "swl", "t,o(b)", treg, breg);
2292 offset_expr.X_add_number -= 3;
2293 macro_build (&icnt, &offset_expr, "swr", "t,o(b)", treg, breg);
2294 return;
3d3c5039
ILT
2295
2296 case M_USH_A:
2297 case M_USW_A:
5ac34ac3 2298 if (offset_expr.X_op == O_constant)
670a50eb
ILT
2299 load_register (&icnt, ip, AT, &offset_expr);
2300 else if (gp_reference (&offset_expr))
2301 macro_build (&icnt, &offset_expr, "addiu", "t,r,j", AT, GP);
2302 else
2303 {
2304 macro_build_lui (&icnt, &offset_expr, AT);
2305 macro_build (&icnt, &offset_expr, "addiu", "t,r,j", AT, AT);
3d3c5039 2306 }
670a50eb
ILT
2307 if (mask == M_USW_A)
2308 {
2309 expr1.X_add_number = 3;
2310 macro_build (&icnt, &expr1, "swl", "t,o(b)", treg, AT);
2311 expr1.X_add_number = 0;
2312 macro_build (&icnt, &expr1, "swr", "t,o(b)", treg, AT);
2313 }
2314 else
2315 {
2316 expr1.X_add_number = 0;
2317 macro_build (&icnt, &expr1, "sb", "t,o(b)", treg, AT);
2318 macro_build (&icnt, NULL, "srl", "d,w,<", treg, treg, 8);
2319 expr1.X_add_number = 1;
2320 macro_build (&icnt, &expr1, "sb", "t,o(b)", treg, AT);
2321 expr1.X_add_number = 0;
2322 macro_build (&icnt, &expr1, "lbu", "t,o(b)", AT, AT);
2323 macro_build (&icnt, NULL, "sll", "d,w,<", treg, treg, 8);
2324 macro_build (&icnt, NULL, "or", "d,v,t", treg, treg, AT);
2325 }
2326 break;
3d3c5039
ILT
2327
2328 default:
670a50eb 2329 as_bad ("Macro %s not implemented yet", ip->insn_mo->name);
3d3c5039 2330 }
670a50eb
ILT
2331 if (mips_noat)
2332 as_warn ("Macro used $at after \".set noat\"");
3d3c5039
ILT
2333}
2334
2335
2336/*
2337This routine assembles an instruction into its binary format. As a side
2338effect it sets one of the global variables imm_reloc or offset_reloc to the
2339type of relocation to do if one of the operands is an address expression.
2340*/
2341static void
2342mips_ip (str, ip)
2343 char *str;
2344 struct mips_cl_insn *ip;
2345{
670a50eb
ILT
2346 char *s;
2347 const char *args;
2348 char c;
2349 struct mips_opcode *insn;
2350 char *argsStart;
2351 unsigned int regno;
2352 unsigned int lastregno = 0;
2353 char *s_reset;
2354
2355 insn_error = NULL;
2356
2357 for (s = str; islower (*s) || (*s >= '0' && *s <= '3') || *s == '.'; ++s)
2358 continue;
2359 switch (*s)
2360 {
3d3c5039 2361 case '\0':
670a50eb 2362 break;
3d3c5039
ILT
2363
2364 case ' ':
670a50eb
ILT
2365 *s++ = '\0';
2366 break;
3d3c5039
ILT
2367
2368 default:
670a50eb
ILT
2369 as_warn ("Unknown opcode: `%s'", str);
2370 exit (1);
3d3c5039 2371 }
670a50eb
ILT
2372 if ((insn = (struct mips_opcode *) hash_find (op_hash, str)) == NULL)
2373 {
2374 as_warn ("`%s' not in hash table.", str);
2375 insn_error = "ERROR: Unrecognized opcode";
2376 return;
3d3c5039 2377 }
670a50eb
ILT
2378 argsStart = s;
2379 for (;;)
2380 {
2381 assert (strcmp (insn->name, str) == 0);
2382 ip->insn_mo = insn;
2383 ip->insn_opcode = insn->match;
2384 for (args = insn->args;; ++args)
2385 {
2386 if (*s == ' ')
2387 ++s;
2388 switch (*args)
2389 {
2390 case '\0': /* end of args */
2391 if (*s == '\0')
2392 return;
2393 break;
3d3c5039
ILT
2394
2395 case ',':
670a50eb
ILT
2396 if (*s++ == *args)
2397 continue;
2398 s--;
2399 switch (*++args)
2400 {
3d3c5039
ILT
2401 case 'r':
2402 case 'v':
670a50eb
ILT
2403 ip->insn_opcode |= lastregno << 21;
2404 continue;
3d3c5039
ILT
2405
2406 case 'w':
2407 case 'W':
670a50eb
ILT
2408 ip->insn_opcode |= lastregno << 16;
2409 continue;
3d3c5039
ILT
2410
2411 case 'V':
670a50eb
ILT
2412 ip->insn_opcode |= lastregno << 11;
2413 continue;
3d3c5039 2414 }
670a50eb 2415 break;
3d3c5039
ILT
2416
2417 case '(':
670a50eb
ILT
2418 /* handle optional base register.
2419 Either the base register is omitted or
2420 we must have a left paren. */
2421 /* this is dependent on the next operand specifier
2422 is a 'b' for base register */
2423 assert (args[1] == 'b');
2424 if (*s == '\0')
2425 return;
3d3c5039 2426
670a50eb
ILT
2427 case ')': /* these must match exactly */
2428 if (*s++ == *args)
3d3c5039 2429 continue;
670a50eb
ILT
2430 break;
2431
2432 case '<': /* must be at least one digit */
2433 /*
2434 * According to the manual, if the shift amount is greater
2435 * than 31 or less than 0 the the shift amount should be
2436 * mod 32. In reality the mips assembler issues an error.
2437 * We issue a warning and do the mod.
2438 */
2439 my_getExpression (&imm_expr, s);
2440 check_absolute_expr (ip, &imm_expr);
2441 if ((unsigned long) imm_expr.X_add_number > 31)
2442 {
2443 as_warn ("Improper shift amount (%d)",
2444 imm_expr.X_add_number);
2445 imm_expr.X_add_number = imm_expr.X_add_number % 32;
2446 }
2447 ip->insn_opcode |= imm_expr.X_add_number << 6;
5ac34ac3 2448 imm_expr.X_op = O_absent;
670a50eb
ILT
2449 s = expr_end;
2450 continue;
2451
2452 case 'c': /* break code */
2453 my_getExpression (&imm_expr, s);
2454 check_absolute_expr (ip, &imm_expr);
2455 if ((unsigned) imm_expr.X_add_number > 1023)
2456 as_warn ("Illegal break code (%d)", imm_expr.X_add_number);
2457 ip->insn_opcode |= imm_expr.X_add_number << 16;
5ac34ac3 2458 imm_expr.X_op = O_absent;
670a50eb
ILT
2459 s = expr_end;
2460 continue;
2461
918692a5
ILT
2462 case 'B': /* syscall code */
2463 my_getExpression (&imm_expr, s);
2464 check_absolute_expr (ip, &imm_expr);
2465 if ((unsigned) imm_expr.X_add_number > 0xfffff)
2466 as_warn ("Illegal syscall code (%d)", imm_expr.X_add_number);
2467 ip->insn_opcode |= imm_expr.X_add_number << 6;
5ac34ac3 2468 imm_expr.X_op = O_absent;
918692a5
ILT
2469 s = expr_end;
2470 continue;
2471
670a50eb
ILT
2472 case 'b': /* base register */
2473 case 'd': /* destination register */
2474 case 's': /* source register */
2475 case 't': /* target register */
2476 case 'r': /* both target and source */
2477 case 'v': /* both dest and source */
2478 case 'w': /* both dest and target */
918692a5
ILT
2479 case 'E': /* coprocessor target register */
2480 case 'G': /* coprocessor destination register */
670a50eb
ILT
2481 s_reset = s;
2482 if (s[0] == '$')
2483 {
2484 if (isdigit (s[1]))
2485 {
2486 ++s;
2487 regno = 0;
2488 do
2489 {
2490 regno *= 10;
2491 regno += *s - '0';
2492 ++s;
2493 }
2494 while (isdigit (*s));
2495 }
2496 else if (s[1] == 'f' && s[2] == 'p')
2497 {
2498 s += 3;
2499 regno = 30;
2500 }
2501 else if (s[1] == 's' && s[2] == 'p')
2502 {
2503 s += 3;
2504 regno = 29;
2505 }
2506 else if (s[1] == 'g' && s[2] == 'p')
2507 {
2508 s += 3;
2509 regno = 28;
3d3c5039 2510 }
670a50eb
ILT
2511 else if (s[1] == 'a' && s[2] == 't')
2512 {
2513 s += 3;
2514 regno = 1;
2515 }
2516 else
2517 goto notreg;
2518 if (regno > 31)
2519 as_bad ("Invalid register number (%d)", regno);
2520 if (regno == AT && !mips_noat)
2521 as_warn ("Used $at without \".set noat\"");
2522 c = *args;
2523 if (*s == ' ')
2524 s++;
2525 if (args[1] != *s)
2526 {
2527 if (c == 'r' || c == 'v' || c == 'w')
2528 {
2529 regno = lastregno;
2530 s = s_reset;
2531 args++;
2532 }
2533 }
2534 switch (c)
2535 {
3d3c5039
ILT
2536 case 'r':
2537 case 's':
2538 case 'v':
2539 case 'b':
670a50eb
ILT
2540 ip->insn_opcode |= regno << 21;
2541 break;
3d3c5039 2542 case 'd':
918692a5 2543 case 'G':
670a50eb
ILT
2544 ip->insn_opcode |= regno << 11;
2545 break;
3d3c5039
ILT
2546 case 'w':
2547 case 't':
918692a5 2548 case 'E':
670a50eb 2549 ip->insn_opcode |= regno << 16;
3d3c5039 2550 }
670a50eb
ILT
2551 lastregno = regno;
2552 continue;
3d3c5039
ILT
2553 }
2554 notreg:
670a50eb
ILT
2555 switch (*args++)
2556 {
3d3c5039
ILT
2557 case 'r':
2558 case 'v':
670a50eb
ILT
2559 ip->insn_opcode |= lastregno << 21;
2560 continue;
3d3c5039 2561 case 'w':
670a50eb
ILT
2562 ip->insn_opcode |= lastregno << 16;
2563 continue;
3d3c5039 2564 }
670a50eb 2565 break;
3d3c5039 2566
670a50eb
ILT
2567 case 'D': /* floating point destination register */
2568 case 'S': /* floating point source register */
2569 case 'T': /* floating point target register */
3d3c5039
ILT
2570 case 'V':
2571 case 'W':
670a50eb
ILT
2572 s_reset = s;
2573 if (s[0] == '$' && s[1] == 'f' && isdigit (s[2]))
2574 {
2575 s += 2;
2576 regno = 0;
2577 do
2578 {
2579 regno *= 10;
2580 regno += *s - '0';
2581 ++s;
2582 }
2583 while (isdigit (*s));
2584
2585 if (regno > 31)
2586 as_bad ("Invalid float register number (%d)", regno);
2587
2588 if ((regno & 1) &&
2589 !(strcmp (str, "mtc1") == 0 ||
2590 strcmp (str, "mfc1") == 0 ||
2591 strcmp (str, "lwc1") == 0 ||
2592 strcmp (str, "swc1") == 0))
2593 as_warn ("Float register should be even, was %d",
2594 regno);
2595
2596 c = *args;
2597 if (*s == ' ')
2598 s++;
2599 if (args[1] != *s)
2600 {
2601 if (c == 'V' || c == 'W')
2602 {
2603 regno = lastregno;
2604 s = s_reset;
2605 args++;
3d3c5039
ILT
2606 }
2607 }
670a50eb
ILT
2608 switch (c)
2609 {
3d3c5039 2610 case 'D':
670a50eb
ILT
2611 ip->insn_opcode |= regno << 6;
2612 break;
3d3c5039
ILT
2613 case 'V':
2614 case 'S':
670a50eb
ILT
2615 ip->insn_opcode |= regno << 11;
2616 break;
3d3c5039
ILT
2617 case 'W':
2618 case 'T':
670a50eb 2619 ip->insn_opcode |= regno << 16;
3d3c5039 2620 }
670a50eb
ILT
2621 lastregno = regno;
2622 continue;
3d3c5039 2623 }
670a50eb
ILT
2624 switch (*args++)
2625 {
3d3c5039 2626 case 'V':
670a50eb
ILT
2627 ip->insn_opcode |= lastregno << 11;
2628 continue;
3d3c5039 2629 case 'W':
670a50eb
ILT
2630 ip->insn_opcode |= lastregno << 16;
2631 continue;
3d3c5039 2632 }
670a50eb 2633 break;
3d3c5039
ILT
2634
2635 case 'I':
670a50eb
ILT
2636 my_getExpression (&imm_expr, s);
2637 check_absolute_expr (ip, &imm_expr);
2638 s = expr_end;
2639 continue;
3d3c5039
ILT
2640
2641 case 'A':
670a50eb
ILT
2642 my_getExpression (&offset_expr, s);
2643 imm_reloc = BFD_RELOC_32;
2644 s = expr_end;
2645 continue;
3d3c5039
ILT
2646
2647 case 'F':
670a50eb
ILT
2648 as_bad ("Floating point constants only implemented for pseudo ops.");
2649 continue;
2650
2651 case 'i': /* 16 bit unsigned immediate */
2652 case 'j': /* 16 bit signed immediate */
2653 imm_reloc = BFD_RELOC_LO16;
2654 c = my_getSmallExpression (&imm_expr, s);
2655 if (c)
2656 {
2657 if (c != 'l')
2658 {
5ac34ac3 2659 if (imm_expr.X_op == O_constant)
670a50eb
ILT
2660 imm_expr.X_add_number =
2661 (imm_expr.X_add_number >> 16) & 0xffff;
2662 else if (c == 'h')
2663 imm_reloc = BFD_RELOC_HI16_S;
2664 else
2665 imm_reloc = BFD_RELOC_HI16;
3d3c5039 2666 }
670a50eb
ILT
2667 }
2668 else
2669 check_absolute_expr (ip, &imm_expr);
2670 if (*args == 'i')
2671 {
2672 if ((unsigned long) imm_expr.X_add_number > 65535)
99c24539
ILT
2673 {
2674 if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
2675 !strcmp (insn->name, insn[1].name))
2676 break;
2677 as_bad ("16 bit expression not in range 0..65535");
2678 }
670a50eb
ILT
2679 }
2680 else
2681 {
2682 if (imm_expr.X_add_number < -32768 ||
3d3c5039 2683 imm_expr.X_add_number > 32767)
99c24539
ILT
2684 {
2685 if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
2686 !strcmp (insn->name, insn[1].name))
2687 break;
2688 as_bad ("16 bit expression not in range -32768..32767");
2689 }
3d3c5039 2690 }
670a50eb
ILT
2691 s = expr_end;
2692 continue;
2693
2694 case 'o': /* 16 bit offset */
2695 c = my_getSmallExpression (&offset_expr, s);
2696 /*
2697 * If this value won't fit into a 16 bit offset, then
2698 * go find a macro that will generate the 32 bit offset
2699 * code pattern.
2700 */
2701 if ((offset_expr.X_add_symbol
5ac34ac3
ILT
2702 && offset_expr.X_op != O_constant)
2703 || offset_expr.X_op_symbol
670a50eb
ILT
2704 || offset_expr.X_add_number > 32767
2705 || offset_expr.X_add_number < -32768)
2706 break;
3d3c5039 2707
670a50eb
ILT
2708 offset_reloc = BFD_RELOC_LO16;
2709 if (c == 'h' || c == 'H')
2710 offset_expr.X_add_number =
2711 (offset_expr.X_add_number >> 16) & 0xffff;
2712 s = expr_end;
2713 continue;
2714
2715 case 'p': /* pc relative offset */
2716 offset_reloc = BFD_RELOC_16_PCREL_S2;
2717 my_getExpression (&offset_expr, s);
2718 s = expr_end;
2719 continue;
2720
2721 case 'u': /* upper 16 bits */
2722 c = my_getSmallExpression (&imm_expr, s);
2723 if ((unsigned long) imm_expr.X_add_number > 65535)
2724 as_bad ("lui expression not in range 0..65535");
2725 imm_reloc = BFD_RELOC_LO16;
2726 if (c)
2727 {
2728 if (c != 'l')
2729 {
5ac34ac3 2730 if (imm_expr.X_op == O_constant)
670a50eb
ILT
2731 imm_expr.X_add_number =
2732 (imm_expr.X_add_number >> 16) & 0xffff;
2733 else if (c == 'h')
2734 imm_reloc = BFD_RELOC_HI16_S;
2735 else
2736 imm_reloc = BFD_RELOC_HI16;
3d3c5039
ILT
2737 }
2738 }
670a50eb
ILT
2739 s = expr_end;
2740 continue;
3d3c5039 2741
670a50eb
ILT
2742 case 'a': /* 26 bit address */
2743 my_getExpression (&offset_expr, s);
2744 s = expr_end;
2745 offset_reloc = BFD_RELOC_MIPS_JMP;
2746 continue;
3d3c5039
ILT
2747
2748 default:
670a50eb
ILT
2749 fprintf (stderr, "bad char = '%c'\n", *args);
2750 internalError ();
3d3c5039 2751 }
670a50eb 2752 break;
3d3c5039 2753 }
670a50eb
ILT
2754 /* Args don't match. */
2755 if (insn + 1 < &mips_opcodes[NUMOPCODES] &&
2756 !strcmp (insn->name, insn[1].name))
2757 {
2758 ++insn;
2759 s = argsStart;
2760 continue;
3d3c5039 2761 }
670a50eb
ILT
2762 insn_error = "ERROR: Illegal operands";
2763 return;
3d3c5039
ILT
2764 }
2765}
2766
2767#define LP '('
2768#define RP ')'
2769
2770static int
2771my_getSmallExpression (ep, str)
670a50eb
ILT
2772 expressionS *ep;
2773 char *str;
3d3c5039 2774{
670a50eb
ILT
2775 char *sp;
2776 int c = 0;
2777
2778 if (*str == ' ')
2779 str++;
2780 if (*str == LP
2781 || (*str == '%' &&
2782 ((str[1] == 'h' && str[2] == 'i')
2783 || (str[1] == 'H' && str[2] == 'I')
2784 || (str[1] == 'l' && str[2] == 'o'))
2785 && str[3] == LP))
2786 {
2787 if (*str == LP)
2788 c = 0;
2789 else
2790 {
2791 c = str[1];
2792 str += 3;
2793 }
2794
2795 /*
2796 * A small expression may be followed by a base register.
2797 * Scan to the end of this operand, and then back over a possible
2798 * base register. Then scan the small expression up to that
2799 * point. (Based on code in sparc.c...)
2800 */
2801 for (sp = str; *sp && *sp != ','; sp++)
2802 ;
2803 if (sp - 4 >= str && sp[-1] == RP)
2804 {
2805 if (isdigit (sp[-2]))
2806 {
2807 for (sp -= 3; sp >= str && isdigit (*sp); sp--)
2808 ;
2809 if (*sp == '$' && sp > str && sp[-1] == LP)
2810 {
2811 sp--;
2812 goto do_it;
3d3c5039 2813 }
670a50eb
ILT
2814 }
2815 else if (sp - 5 >= str
2816 && sp[-5] == LP
2817 && sp[-4] == '$'
2818 && ((sp[-3] == 'f' && sp[-2] == 'p')
2819 || (sp[-3] == 's' && sp[-2] == 'p')
2820 || (sp[-3] == 'g' && sp[-2] == 'p')
2821 || (sp[-3] == 'a' && sp[-2] == 't')))
2822 {
2823 sp -= 5;
3d3c5039 2824 do_it:
670a50eb
ILT
2825 if (sp == str)
2826 {
2827 /* no expression means zero offset */
2828 if (c)
2829 {
2830 /* %xx(reg) is an error */
5ac34ac3 2831 ep->X_op = O_absent;
670a50eb 2832 expr_end = str - 3;
3d3c5039 2833 }
670a50eb
ILT
2834 else
2835 {
5ac34ac3 2836 ep->X_op = O_absent;
670a50eb
ILT
2837 expr_end = sp;
2838 }
2839 ep->X_add_symbol = NULL;
5ac34ac3 2840 ep->X_op_symbol = NULL;
670a50eb
ILT
2841 ep->X_add_number = 0;
2842 }
2843 else
2844 {
2845 *sp = '\0';
2846 my_getExpression (ep, str);
2847 *sp = LP;
3d3c5039 2848 }
670a50eb 2849 return c;
3d3c5039
ILT
2850 }
2851 }
2852 }
670a50eb
ILT
2853 my_getExpression (ep, str);
2854 return c; /* => %hi or %lo encountered */
3d3c5039
ILT
2855}
2856
2857static void
2858my_getExpression (ep, str)
670a50eb
ILT
2859 expressionS *ep;
2860 char *str;
3d3c5039 2861{
670a50eb 2862 char *save_in;
670a50eb
ILT
2863
2864 save_in = input_line_pointer;
2865 input_line_pointer = str;
5ac34ac3 2866 expression (ep);
670a50eb
ILT
2867 expr_end = input_line_pointer;
2868 input_line_pointer = save_in;
3d3c5039
ILT
2869}
2870
becfe05e
ILT
2871/* Turn a string in input_line_pointer into a floating point constant
2872 of type type, and store the appropriate bytes in *litP. The number
2873 of LITTLENUMS emitted is stored in *sizeP . An error message is
2874 returned, or NULL on OK. */
2875
3d3c5039 2876char *
670a50eb 2877md_atof (type, litP, sizeP)
becfe05e 2878 int type;
3d3c5039
ILT
2879 char *litP;
2880 int *sizeP;
2881{
becfe05e
ILT
2882 int prec;
2883 LITTLENUM_TYPE words[4];
2884 char *t;
2885 int i;
2886
2887 switch (type)
2888 {
2889 case 'f':
2890 prec = 2;
2891 break;
2892
2893 case 'd':
2894 prec = 4;
2895 break;
2896
2897 default:
2898 *sizeP = 0;
2899 return "bad call to md_atof";
2900 }
2901
2902 t = atof_ieee (input_line_pointer, type, words);
2903 if (t)
2904 input_line_pointer = t;
2905
2906 *sizeP = prec * 2;
2907
2908 if (byte_order == LITTLE_ENDIAN)
2909 {
2910 for (i = prec - 1; i >= 0; i--)
2911 {
2912 md_number_to_chars (litP, (valueT) words[i], 2);
2913 litP += 2;
2914 }
2915 }
2916 else
2917 {
2918 for (i = 0; i < prec; i++)
2919 {
2920 md_number_to_chars (litP, (valueT) words[i], 2);
2921 litP += 2;
2922 }
2923 }
2924
670a50eb 2925 return NULL;
3d3c5039
ILT
2926}
2927
2928void
2929md_number_to_chars (buf, val, n)
2930 char *buf;
918692a5 2931 valueT val;
3d3c5039
ILT
2932 int n;
2933{
670a50eb
ILT
2934 switch (byte_order)
2935 {
3d3c5039 2936 case LITTLE_ENDIAN:
670a50eb
ILT
2937 switch (n)
2938 {
3d3c5039 2939 case 4:
670a50eb
ILT
2940 *buf++ = val;
2941 *buf++ = val >> 8;
2942 *buf++ = val >> 16;
2943 *buf = val >> 24;
2944 return;
3d3c5039 2945
670a50eb
ILT
2946 case 2:
2947 *buf++ = val;
2948 *buf = val >> 8;
2949 return;
3d3c5039
ILT
2950
2951 case 1:
670a50eb
ILT
2952 *buf = val;
2953 return;
3d3c5039
ILT
2954
2955 default:
670a50eb 2956 internalError ();
3d3c5039
ILT
2957 }
2958
2959 case BIG_ENDIAN:
670a50eb
ILT
2960 switch (n)
2961 {
3d3c5039 2962 case 4:
670a50eb
ILT
2963 *buf++ = val >> 24;
2964 *buf++ = val >> 16;
2965 case 2:
2966 *buf++ = val >> 8;
3d3c5039 2967 case 1:
670a50eb
ILT
2968 *buf = val;
2969 return;
3d3c5039
ILT
2970
2971 default:
670a50eb 2972 internalError ();
3d3c5039
ILT
2973 }
2974
2975 default:
670a50eb 2976 internalError ();
3d3c5039
ILT
2977 }
2978}
2979
2980int
2981md_parse_option (argP, cntP, vecP)
2982 char **argP;
2983 int *cntP;
2984 char ***vecP;
2985{
670a50eb
ILT
2986 /* Accept -nocpp but ignore it. */
2987 if (!strcmp (*argP, "nocpp"))
2988 {
2989 *argP += 5;
2990 return 1;
2991 }
2992
2993 if (strcmp (*argP, "EL") == 0
2994 || strcmp (*argP, "EB") == 0)
2995 {
2996 /* FIXME: This breaks -L -EL. */
2997 flagseen['L'] = 0;
2998 *argP = "";
2999 return 1;
3000 }
3001
4e95866e
ILT
3002 if (**argP == 'O')
3003 {
3004 mips_optimize = (*argP)[1] != '0';
3005 return 1;
3006 }
3007
670a50eb
ILT
3008#ifdef OBJ_ECOFF
3009 if (**argP == 'G')
3010 {
3011 if ((*argP)[1] != '\0')
3012 g_switch_value = atoi (*argP + 1);
3013 else if (*cntP)
3014 {
3015 **vecP = (char *) NULL;
3016 (*cntP)--;
3017 (*vecP)++;
3018 g_switch_value = atoi (**vecP);
3019 }
3020 else
3021 as_warn ("Number expected after -G");
3022 *argP = "";
3023 return 1;
3d3c5039 3024 }
670a50eb 3025#endif
4e95866e 3026
670a50eb 3027 return 1; /* pretend you parsed the character */
3d3c5039
ILT
3028}
3029
3030long
3031md_pcrel_from (fixP)
3032 fixS *fixP;
3033{
670a50eb
ILT
3034 /* return the address of the delay slot */
3035 return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
3d3c5039
ILT
3036}
3037
3038int
3039md_apply_fix (fixP, valueP)
3040 fixS *fixP;
918692a5 3041 valueT *valueP;
3d3c5039 3042{
670a50eb
ILT
3043 unsigned char *buf;
3044 long insn, value;
3d3c5039 3045
670a50eb 3046 assert (fixP->fx_size == 4);
3d3c5039 3047
670a50eb
ILT
3048 value = *valueP;
3049 fixP->fx_addnumber = value; /* Remember value for tc_gen_reloc */
3d3c5039 3050
670a50eb
ILT
3051 switch (fixP->fx_r_type)
3052 {
3d3c5039
ILT
3053 case BFD_RELOC_32:
3054 case BFD_RELOC_MIPS_JMP:
3055 case BFD_RELOC_HI16:
3056 case BFD_RELOC_HI16_S:
3057 case BFD_RELOC_LO16:
670a50eb
ILT
3058 case BFD_RELOC_MIPS_GPREL:
3059 /* Nothing needed to do. The value comes from the reloc entry */
3060 return 1;
3d3c5039
ILT
3061
3062 case BFD_RELOC_16_PCREL_S2:
670a50eb
ILT
3063 /*
3064 * We need to save the bits in the instruction since fixup_segment()
3065 * might be deleting the relocation entry (i.e., a branch within
3066 * the current segment).
3067 */
3068 if (value & 0x3)
3069 as_warn ("Branch to odd address (%x)", value);
3070 value >>= 2;
3071 if ((value & ~0xFFFF) && (value & ~0xFFFF) != (-1 & ~0xFFFF))
3072 as_bad ("Relocation overflow");
3073
3074 /* update old instruction data */
3075 buf = (unsigned char *) (fixP->fx_where + fixP->fx_frag->fr_literal);
3076 switch (byte_order)
3077 {
3d3c5039 3078 case LITTLE_ENDIAN:
670a50eb
ILT
3079 insn = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
3080 break;
3d3c5039
ILT
3081
3082 case BIG_ENDIAN:
670a50eb
ILT
3083 insn = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
3084 break;
3d3c5039
ILT
3085
3086 default:
670a50eb
ILT
3087 internalError ();
3088 return 0;
3d3c5039 3089 }
670a50eb 3090 insn |= value & 0xFFFF;
918692a5 3091 md_number_to_chars ((char *) buf, insn, 4);
670a50eb 3092 break;
3d3c5039
ILT
3093
3094 default:
670a50eb 3095 internalError ();
3d3c5039 3096 }
670a50eb 3097 return 1;
3d3c5039
ILT
3098}
3099
3100#if 0
3101void
670a50eb
ILT
3102printInsn (oc)
3103 unsigned long oc;
3d3c5039 3104{
670a50eb
ILT
3105 const struct mips_opcode *p;
3106 int treg, sreg, dreg, shamt;
3107 short imm;
3108 const char *args;
3109 int i;
3d3c5039 3110
670a50eb
ILT
3111 for (i = 0; i < NUMOPCODES; ++i)
3112 {
3113 p = &mips_opcodes[i];
3114 if (((oc & p->mask) == p->match) && (p->pinfo != INSN_MACRO))
3115 {
3116 printf ("%08lx %s\t", oc, p->name);
3117 treg = (oc >> 16) & 0x1f;
3118 sreg = (oc >> 21) & 0x1f;
3119 dreg = (oc >> 11) & 0x1f;
3120 shamt = (oc >> 6) & 0x1f;
3121 imm = oc;
3122 for (args = p->args;; ++args)
3123 {
3124 switch (*args)
3125 {
3d3c5039 3126 case '\0':
670a50eb
ILT
3127 printf ("\n");
3128 break;
3d3c5039
ILT
3129
3130 case ',':
3131 case '(':
3132 case ')':
670a50eb
ILT
3133 printf ("%c", *args);
3134 continue;
3d3c5039
ILT
3135
3136 case 'r':
670a50eb
ILT
3137 assert (treg == sreg);
3138 printf ("$%d,$%d", treg, sreg);
3139 continue;
3d3c5039
ILT
3140
3141 case 'd':
918692a5 3142 case 'G':
670a50eb
ILT
3143 printf ("$%d", dreg);
3144 continue;
3d3c5039
ILT
3145
3146 case 't':
918692a5 3147 case 'E':
670a50eb
ILT
3148 printf ("$%d", treg);
3149 continue;
3d3c5039
ILT
3150
3151 case 'b':
3152 case 's':
670a50eb
ILT
3153 printf ("$%d", sreg);
3154 continue;
3d3c5039
ILT
3155
3156 case 'a':
670a50eb
ILT
3157 printf ("0x%08lx", oc & 0x1ffffff);
3158 continue;
3d3c5039
ILT
3159
3160 case 'i':
3161 case 'j':
3162 case 'o':
3163 case 'u':
670a50eb
ILT
3164 printf ("%d", imm);
3165 continue;
3d3c5039
ILT
3166
3167 case '<':
670a50eb
ILT
3168 printf ("$%d", shamt);
3169 continue;
3d3c5039
ILT
3170
3171 default:
670a50eb 3172 internalError ();
3d3c5039 3173 }
670a50eb 3174 break;
3d3c5039 3175 }
670a50eb 3176 return;
3d3c5039
ILT
3177 }
3178 }
670a50eb 3179 printf ("%08lx UNDEFINED\n", oc);
3d3c5039
ILT
3180}
3181#endif
3182
3183static symbolS *
3184get_symbol ()
3185{
670a50eb
ILT
3186 int c;
3187 char *name;
3188 symbolS *p;
3189
3190 name = input_line_pointer;
3191 c = get_symbol_end ();
3192 p = (symbolS *) symbol_find_or_make (name);
3193 *input_line_pointer = c;
3194 return p;
3d3c5039
ILT
3195}
3196
becfe05e
ILT
3197/* Align the current frag to a given power of two. The MIPS assembler
3198 also automatically adjusts any preceding label. */
3199
3200static void
3201mips_align (to, fill)
3202 int to;
3203 int fill;
3204{
3205 mips_emit_delays ();
3206 frag_align (to, fill);
3207 record_alignment (now_seg, to);
3208 if (insn_label != NULL)
3209 {
3210 assert (S_GET_SEGMENT (insn_label) == now_seg);
3211 insn_label->sy_frag = frag_now;
3212 S_SET_VALUE (insn_label, frag_now_fix ());
3213 }
3214}
3215
3216/* Align to a given power of two. .align 0 turns off the automatic
3217 alignment used by the data creating pseudo-ops. */
3218
3d3c5039
ILT
3219static void
3220s_align (x)
3221 int x;
3222{
670a50eb
ILT
3223 register int temp;
3224 register long temp_fill;
3225 long max_alignment = 15;
3d3c5039 3226
670a50eb 3227 /*
3d3c5039
ILT
3228
3229 o Note that the assembler pulls down any immediately preceeding label
3230 to the aligned address.
3231 o It's not documented but auto alignment is reinstated by
3232 a .align pseudo instruction.
3233 o Note also that after auto alignment is turned off the mips assembler
3234 issues an error on attempt to assemble an improperly aligned data item.
3235 We don't.
3236
3237 */
3238
670a50eb
ILT
3239 temp = get_absolute_expression ();
3240 if (temp > max_alignment)
3241 as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
3242 else if (temp < 0)
3243 {
3244 as_warn ("Alignment negative: 0 assumed.");
3245 temp = 0;
3246 }
3247 if (*input_line_pointer == ',')
3248 {
3249 input_line_pointer++;
3250 temp_fill = get_absolute_expression ();
3251 }
3252 else
3253 temp_fill = 0;
3254 if (temp)
3255 {
3256 auto_align = 1;
becfe05e 3257 mips_align (temp, (int) temp_fill);
3d3c5039 3258 }
670a50eb
ILT
3259 else
3260 {
3261 auto_align = 0;
3d3c5039
ILT
3262 }
3263
670a50eb 3264 demand_empty_rest_of_line ();
3d3c5039
ILT
3265}
3266
becfe05e
ILT
3267/* Handle .ascii and .asciiz. This just calls stringer and forgets
3268 that there was a previous instruction. */
3269
3270static void
3271s_stringer (append_zero)
3272 int append_zero;
3273{
3274 mips_emit_delays ();
3275 stringer (append_zero);
3276}
3277
3d3c5039
ILT
3278static void
3279s_change_sec (sec)
3280 int sec;
3281{
becfe05e
ILT
3282 segT segment;
3283
3284 mips_emit_delays ();
3285 segment = now_seg;
670a50eb
ILT
3286 switch (sec)
3287 {
3d3c5039 3288 case 't':
670a50eb
ILT
3289 s_text ();
3290 break;
3d3c5039 3291 case 'r':
670a50eb
ILT
3292#ifdef OBJ_ECOFF
3293 subseg_new (".rdata", (subsegT) get_absolute_expression ());
becfe05e 3294 demand_empty_rest_of_line ();
670a50eb
ILT
3295 break;
3296#else
3297 /* Fall through. */
3298#endif
3d3c5039 3299 case 'd':
670a50eb
ILT
3300 s_data ();
3301 break;
3d3c5039
ILT
3302 case 'b':
3303#ifdef BFD_ASSEMBLER
670a50eb 3304 subseg_set (bss_section, (subsegT) get_absolute_expression ());
3d3c5039 3305#else
670a50eb
ILT
3306 subseg_new (bss_section, (subsegT) get_absolute_expression ());
3307#endif
3308 demand_empty_rest_of_line ();
3309 break;
3310 case 's':
3311#ifdef OBJ_ECOFF
3312 subseg_new (".sdata", (subsegT) get_absolute_expression ());
becfe05e 3313 demand_empty_rest_of_line ();
670a50eb
ILT
3314 break;
3315#else
3316 as_bad ("Global pointers not supported; recompile -G 0");
becfe05e 3317 demand_empty_rest_of_line ();
670a50eb 3318 return;
3d3c5039 3319#endif
3d3c5039 3320 }
670a50eb 3321 auto_align = 1;
3d3c5039
ILT
3322}
3323
3324static void
3325s_cons (log_size)
3326 int log_size;
3327{
becfe05e 3328 mips_emit_delays ();
670a50eb 3329 if (log_size > 0 && auto_align)
becfe05e 3330 mips_align (log_size, 0);
670a50eb 3331 cons (1 << log_size);
3d3c5039
ILT
3332}
3333
3334static void
3335s_err (x)
3336 int x;
3337{
670a50eb 3338 as_fatal ("Encountered `.err', aborting assembly");
3d3c5039
ILT
3339}
3340
3341static void
3342s_extern (x)
3343 int x;
3344{
670a50eb
ILT
3345 long size;
3346 symbolS *symbolP;
3347
3348 symbolP = get_symbol ();
3349 if (*input_line_pointer == ',')
3350 input_line_pointer++;
5ac34ac3 3351 size = get_absolute_expression ();
670a50eb
ILT
3352 S_SET_VALUE (symbolP, size);
3353 S_SET_EXTERNAL (symbolP);
3354
3355#ifdef OBJ_ECOFF
3356 /* ECOFF needs to distinguish a .comm symbol from a .extern symbol,
3357 so we use an additional ECOFF specific field. */
3358 symbolP->ecoff_undefined = 1;
3359#endif
3d3c5039
ILT
3360}
3361
3362static void
becfe05e
ILT
3363s_float_cons (type)
3364 int type;
3d3c5039 3365{
becfe05e 3366 mips_emit_delays ();
670a50eb
ILT
3367
3368 if (auto_align)
becfe05e
ILT
3369 if (type == 'd')
3370 mips_align (3, 0);
670a50eb 3371 else
becfe05e 3372 mips_align (2, 0);
670a50eb 3373
becfe05e 3374 float_cons (type);
3d3c5039
ILT
3375}
3376
3377static void
3378s_option (x)
3379 int x;
3380{
670a50eb
ILT
3381 if (strcmp (input_line_pointer, "O1") != 0
3382 && strcmp (input_line_pointer, "O2") != 0)
3383 as_warn ("Unrecognized option");
3384 demand_empty_rest_of_line ();
3d3c5039
ILT
3385}
3386
3387static void
3388s_mipsset (x)
3389 int x;
3390{
670a50eb
ILT
3391 char *name = input_line_pointer, ch;
3392
3393 while (!is_end_of_line[(unsigned char) *input_line_pointer])
3394 input_line_pointer++;
3395 ch = *input_line_pointer;
3396 *input_line_pointer = '\0';
3397
3398 if (strcmp (name, "reorder") == 0)
3399 {
4e95866e
ILT
3400 if (mips_noreorder)
3401 {
3402 prev_insn_unreordered = 1;
3403 prev_prev_insn_unreordered = 1;
3404 }
670a50eb
ILT
3405 mips_noreorder = 0;
3406 }
3407 else if (strcmp (name, "noreorder") == 0)
3408 {
becfe05e 3409 mips_emit_delays ();
670a50eb
ILT
3410 mips_noreorder = 1;
3411 }
3412 else if (strcmp (name, "at") == 0)
3413 {
3414 mips_noat = 0;
3415 }
3416 else if (strcmp (name, "noat") == 0)
3417 {
3418 mips_noat = 1;
3d3c5039 3419 }
670a50eb
ILT
3420 else if (strcmp (name, "macro") == 0)
3421 {
3422 mips_warn_about_macros = 0;
3423 }
3424 else if (strcmp (name, "nomacro") == 0)
3425 {
3426 if (mips_noreorder == 0)
3427 as_bad ("`noreorder' must be set before `nomacro'");
3428 mips_warn_about_macros = 1;
3429 }
3430 else if (strcmp (name, "move") == 0 || strcmp (name, "novolatile") == 0)
3431 {
3432 mips_nomove = 0;
3433 }
3434 else if (strcmp (name, "nomove") == 0 || strcmp (name, "volatile") == 0)
3435 {
3436 mips_nomove = 1;
3437 }
3438 else if (strcmp (name, "bopt") == 0)
3439 {
3440 mips_nobopt = 0;
3441 }
3442 else if (strcmp (name, "nobopt") == 0)
3443 {
3444 mips_nobopt = 1;
3445 }
3446 else
3447 {
3448 as_warn ("Tried to set unrecognized symbol: %s\n", name);
3449 }
3450 *input_line_pointer = ch;
3451 demand_empty_rest_of_line ();
3d3c5039
ILT
3452}
3453
becfe05e
ILT
3454/* The same as the usual .space directive, except that we have to
3455 forget about any previous instruction. */
3456
3457static void
3458s_mips_space (param)
3459 int param;
3460{
3461 mips_emit_delays ();
3462 s_space (param);
3463}
3464
3d3c5039
ILT
3465int
3466tc_get_register ()
3467{
3468 int reg;
3469
3470 SKIP_WHITESPACE ();
3471 if (*input_line_pointer++ != '$')
3472 {
3473 as_warn ("expected `$'");
3474 return 0;
3475 }
3476 if (isdigit ((unsigned char) *input_line_pointer))
3477 {
3478 reg = get_absolute_expression ();
3479 if (reg < 0 || reg >= 32)
3480 {
3481 as_warn ("Bad register number");
3482 reg = 0;
3483 }
3484 }
3485 else
3486 {
3487 if (strncmp (input_line_pointer, "fp", 2) == 0)
3488 reg = 30;
3489 else if (strncmp (input_line_pointer, "sp", 2) == 0)
3490 reg = 29;
3491 else if (strncmp (input_line_pointer, "gp", 2) == 0)
3492 reg = 28;
3493 else if (strncmp (input_line_pointer, "at", 2) == 0)
3494 reg = 1;
3495 else
3496 {
3497 as_warn ("Unrecognized register name");
3498 return 0;
3499 }
3500 input_line_pointer += 2;
3501 }
3502 return reg;
3503}
3504
3505/*
3506 * Translate internal representation of relocation info to BFD target format.
3507 */
3508arelent *
3509tc_gen_reloc (section, fixp)
3510 asection *section;
3511 fixS *fixp;
3512{
3513 arelent *reloc;
3514
3515 reloc = (arelent *) xmalloc (sizeof (arelent));
3516 assert (reloc != 0);
3517
3518 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
3519 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
3520 if (fixp->fx_pcrel == 0)
3521 reloc->addend = fixp->fx_addnumber;
3522 else
3523#ifdef OBJ_ELF
3524 reloc->addend = 0;
3525#else
670a50eb 3526 reloc->addend = -reloc->address;
3d3c5039
ILT
3527#endif
3528 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
3529 assert (reloc->howto != 0);
3530
3d3c5039
ILT
3531 return reloc;
3532}
3533
3534/* should never be called */
918692a5 3535valueT
670a50eb
ILT
3536md_section_align (seg, addr)
3537 asection *seg;
918692a5 3538 valueT addr;
3d3c5039 3539{
670a50eb 3540 int align = bfd_get_section_alignment (stdoutput, seg);
3d3c5039 3541
670a50eb 3542 return ((addr + (1 << align) - 1) & (-1 << align));
3d3c5039
ILT
3543}
3544
3545int
670a50eb
ILT
3546md_estimate_size_before_relax (fragP, segtype)
3547 fragS *fragP;
3548 asection *segtype;
3d3c5039 3549{
670a50eb
ILT
3550 as_fatal ("md_estimate_size_before_relax");
3551 return (1);
3552} /* md_estimate_size_before_relax() */
becfe05e
ILT
3553
3554/* This function is called whenever a label is defined. It is used
3555 when handling branch delays; if a branch has a label, we assume we
3556 can not move it. */
3557
3558void
3559mips_define_label (sym)
3560 symbolS *sym;
3561{
3562 insn_label = sym;
3563}
3d3c5039
ILT
3564\f
3565#ifndef OBJ_ECOFF
3566
3567/* These functions should really be defined by the object file format,
3568 since they are related to debugging information. However, this
3569 code has to work for the a.out format, which does not define them,
3570 so we provide simple versions here. These don't actually generate
3571 any debugging information, but they do simple checking and someday
3572 somebody may make them useful. */
3573
670a50eb
ILT
3574typedef struct loc
3575{
3576 struct loc *loc_next;
3577 unsigned long loc_fileno;
3578 unsigned long loc_lineno;
3579 unsigned long loc_offset;
3580 unsigned short loc_delta;
3581 unsigned short loc_count;
3d3c5039 3582#if 0
670a50eb 3583 fragS *loc_frag;
3d3c5039 3584#endif
670a50eb
ILT
3585}
3586locS;
3d3c5039 3587
670a50eb
ILT
3588typedef struct proc
3589 {
3d3c5039
ILT
3590 struct proc *proc_next;
3591 struct symbol *proc_isym;
3592 struct symbol *proc_end;
3593 unsigned long proc_reg_mask;
3594 unsigned long proc_reg_offset;
3595 unsigned long proc_fpreg_mask;
3596 unsigned long proc_fpreg_offset;
3597 unsigned long proc_frameoffset;
3598 unsigned long proc_framereg;
3599 unsigned long proc_pcreg;
3600 locS *proc_iline;
3601 struct file *proc_file;
3602 int proc_index;
670a50eb
ILT
3603 }
3604procS;
3d3c5039 3605
670a50eb
ILT
3606typedef struct file
3607 {
3d3c5039
ILT
3608 struct file *file_next;
3609 unsigned long file_fileno;
3610 struct symbol *file_symbol;
3611 struct symbol *file_end;
3612 struct proc *file_proc;
3613 int file_numprocs;
670a50eb
ILT
3614 }
3615fileS;
3d3c5039
ILT
3616
3617static struct obstack proc_frags;
3618static procS *proc_lastP;
3619static procS *proc_rootP;
3620static int numprocs;
3621
3622static void
3623md_obj_begin ()
3624{
670a50eb 3625 obstack_begin (&proc_frags, 0x2000);
3d3c5039
ILT
3626}
3627
3628static void
3629md_obj_end ()
3630{
3631 /* check for premature end, nesting errors, etc */
3632 if (proc_lastP && proc_lastP->proc_end == NULL)
670a50eb 3633 as_warn ("missing `.end' at end of assembly");
3d3c5039
ILT
3634}
3635
3636extern char hex_value[];
3637
3638static long
3639get_number ()
3640{
670a50eb
ILT
3641 int negative = 0;
3642 long val = 0;
3d3c5039 3643
670a50eb
ILT
3644 if (*input_line_pointer == '-')
3645 {
3646 ++input_line_pointer;
3647 negative = 1;
3d3c5039 3648 }
670a50eb
ILT
3649 if (!isdigit (*input_line_pointer))
3650 as_bad ("Expected simple number.");
3651 if (input_line_pointer[0] == '0')
3652 {
3653 if (input_line_pointer[1] == 'x')
3654 {
3655 input_line_pointer += 2;
3656 while (isxdigit (*input_line_pointer))
3657 {
3658 val <<= 4;
3659 val |= hex_value[(int) *input_line_pointer++];
3d3c5039 3660 }
670a50eb
ILT
3661 return negative ? -val : val;
3662 }
3663 else
3664 {
3665 ++input_line_pointer;
3666 while (isdigit (*input_line_pointer))
3667 {
3668 val <<= 3;
3669 val |= *input_line_pointer++ - '0';
3d3c5039 3670 }
670a50eb 3671 return negative ? -val : val;
3d3c5039
ILT
3672 }
3673 }
670a50eb
ILT
3674 if (!isdigit (*input_line_pointer))
3675 {
3676 printf (" *input_line_pointer == '%c' 0x%02x\n",
3677 *input_line_pointer, *input_line_pointer);
3678 as_warn ("Invalid number");
3679 return -1;
3d3c5039 3680 }
670a50eb
ILT
3681 while (isdigit (*input_line_pointer))
3682 {
3683 val *= 10;
3684 val += *input_line_pointer++ - '0';
3d3c5039 3685 }
670a50eb 3686 return negative ? -val : val;
3d3c5039
ILT
3687}
3688
3689/* The .file directive; just like the usual .file directive, but there
3690 is an initial number which is the ECOFF file index. */
3691
3692static void
3693s_file (x)
3694 int x;
3695{
670a50eb 3696 int line;
3d3c5039 3697
670a50eb 3698 line = get_number ();
9a7d824a 3699 s_app_file (0);
3d3c5039
ILT
3700}
3701
3702
3703/* The .end directive. */
3704
3705static void
3706s_mipsend (x)
3707 int x;
3708{
670a50eb
ILT
3709 symbolS *p;
3710
3711 if (!is_end_of_line[(unsigned char) *input_line_pointer])
3712 {
3713 p = get_symbol ();
3714 demand_empty_rest_of_line ();
3715 }
3716 else
3717 p = NULL;
3718 if (now_seg != text_section)
3719 as_warn (".end not in text section");
3720 if (!proc_lastP)
3721 {
3722 as_warn (".end and no .ent seen yet.");
3723 return;
3d3c5039
ILT
3724 }
3725
670a50eb
ILT
3726 if (p != NULL)
3727 {
3728 assert (S_GET_NAME (p));
3729 if (strcmp (S_GET_NAME (p), S_GET_NAME (proc_lastP->proc_isym)))
3730 as_warn (".end symbol does not match .ent symbol.");
3d3c5039
ILT
3731 }
3732
670a50eb 3733 proc_lastP->proc_end = (symbolS *) 1;
3d3c5039
ILT
3734}
3735
3736/* The .aent and .ent directives. */
3737
3738static void
3739s_ent (aent)
3740 int aent;
3741{
670a50eb
ILT
3742 int number = 0;
3743 procS *procP;
3744 symbolS *symbolP;
3745
3746 symbolP = get_symbol ();
3747 if (*input_line_pointer == ',')
3748 input_line_pointer++;
3749 if (isdigit (*input_line_pointer) || *input_line_pointer == '-')
3750 number = get_number ();
3751 if (now_seg != text_section)
3752 as_warn (".ent or .aent not in text section.");
3753
3754 if (!aent && proc_lastP && proc_lastP->proc_end == NULL)
3755 as_warn ("missing `.end'");
3756
3757 if (!aent)
3758 {
3759 procP = (procS *) obstack_alloc (&proc_frags, sizeof (*procP));
3760 procP->proc_isym = symbolP;
3761 procP->proc_reg_mask = 0;
3762 procP->proc_reg_offset = 0;
3763 procP->proc_fpreg_mask = 0;
3764 procP->proc_fpreg_offset = 0;
3765 procP->proc_frameoffset = 0;
3766 procP->proc_framereg = 0;
3767 procP->proc_pcreg = 0;
3768 procP->proc_end = NULL;
3769 procP->proc_next = NULL;
3770 if (proc_lastP)
3771 proc_lastP->proc_next = procP;
3772 else
3773 proc_rootP = procP;
3774 proc_lastP = procP;
3775 numprocs++;
3d3c5039 3776 }
670a50eb 3777 demand_empty_rest_of_line ();
3d3c5039
ILT
3778}
3779
3780/* The .frame directive. */
3781
3782static void
3783s_frame (x)
670a50eb 3784 int x;
3d3c5039
ILT
3785{
3786#if 0
670a50eb
ILT
3787 char str[100];
3788 symbolS *symP;
3789 int frame_reg;
3790 int frame_off;
3791 int pcreg;
3792
3793 frame_reg = tc_get_register ();
3794 if (*input_line_pointer == ',')
3795 input_line_pointer++;
5ac34ac3 3796 frame_off = get_absolute_expression ();
670a50eb
ILT
3797 if (*input_line_pointer == ',')
3798 input_line_pointer++;
3799 pcreg = tc_get_register ();
3800
3801 /* bob third eye */
3802 assert (proc_rootP);
3803 proc_rootP->proc_framereg = frame_reg;
3804 proc_rootP->proc_frameoffset = frame_off;
3805 proc_rootP->proc_pcreg = pcreg;
3806 /* bob macho .frame */
3807
3808 /* We don't have to write out a frame stab for unoptimized code. */
3809 if (!(frame_reg == 30 && frame_off == 0))
3810 {
3811 if (!proc_lastP)
3812 as_warn ("No .ent for .frame to use.");
3813 (void) sprintf (str, "R%d;%d", frame_reg, frame_off);
3814 symP = symbol_new (str, N_VFP, 0, frag_now);
3815 S_SET_TYPE (symP, N_RMASK);
3816 S_SET_OTHER (symP, 0);
3817 S_SET_DESC (symP, 0);
3818 symP->sy_forward = proc_lastP->proc_isym;
3819 /* bob perhaps I should have used pseudo set */
3d3c5039 3820 }
670a50eb 3821 demand_empty_rest_of_line ();
3d3c5039
ILT
3822#endif
3823}
3824
3825/* The .fmask and .mask directives. */
3826
3827static void
3828s_mask (reg_type)
3829 char reg_type;
3830{
3831#if 0
670a50eb
ILT
3832 char str[100], *strP;
3833 symbolS *symP;
3834 int i;
3835 unsigned int mask;
3836 int off;
3837
3838 mask = get_number ();
3839 if (*input_line_pointer == ',')
3840 input_line_pointer++;
3841 off = get_absolute_expression ();
3842
3843 /* bob only for coff */
3844 assert (proc_rootP);
3845 if (reg_type == 'F')
3846 {
3847 proc_rootP->proc_fpreg_mask = mask;
3848 proc_rootP->proc_fpreg_offset = off;
3d3c5039 3849 }
670a50eb
ILT
3850 else
3851 {
3852 proc_rootP->proc_reg_mask = mask;
3853 proc_rootP->proc_reg_offset = off;
3854 }
3855
3856 /* bob macho .mask + .fmask */
3d3c5039 3857
670a50eb
ILT
3858 /* We don't have to write out a mask stab if no saved regs. */
3859 if (!(mask == 0))
3860 {
3861 if (!proc_lastP)
3862 as_warn ("No .ent for .mask to use.");
3863 strP = str;
3864 for (i = 0; i < 32; i++)
3865 {
3866 if (mask % 2)
3867 {
3868 sprintf (strP, "%c%d,", reg_type, i);
3869 strP += strlen (strP);
3870 }
3d3c5039 3871 mask /= 2;
670a50eb
ILT
3872 }
3873 sprintf (strP, ";%d,", off);
3874 symP = symbol_new (str, N_RMASK, 0, frag_now);
3875 S_SET_TYPE (symP, N_RMASK);
3876 S_SET_OTHER (symP, 0);
3877 S_SET_DESC (symP, 0);
3878 symP->sy_forward = proc_lastP->proc_isym;
3879 /* bob perhaps I should have used pseudo set */
3d3c5039
ILT
3880 }
3881#endif
3882}
3883
3884/* The .loc directive. */
3885
3886static void
3887s_loc (x)
3888 int x;
3889{
3890#if 0
670a50eb
ILT
3891 symbolS *symbolP;
3892 int lineno;
3893 int addroff;
3d3c5039 3894
670a50eb 3895 assert (now_seg == text_section);
3d3c5039 3896
670a50eb
ILT
3897 lineno = get_number ();
3898 addroff = obstack_next_free (&frags) - frag_now->fr_literal;
3d3c5039 3899
670a50eb
ILT
3900 symbolP = symbol_new ("", N_SLINE, addroff, frag_now);
3901 S_SET_TYPE (symbolP, N_SLINE);
3902 S_SET_OTHER (symbolP, 0);
3903 S_SET_DESC (symbolP, lineno);
3904 symbolP->sy_segment = now_seg;
3d3c5039
ILT
3905#endif
3906}
3907
3908#endif /* ! defined (OBJ_ECOFF) */