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