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