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