]> gcc.gnu.org Git - gcc.git/blob - gcc/config/mips/mips.c
Fix varardic function returning a structure or union.
[gcc.git] / gcc / config / mips / mips.c
1 /* Subroutines for insn-output.c for MIPS
2 Contributed by A. Lichnewsky, lich@inria.inria.fr.
3 Changes by Michael Meissner, meissner@osf.org.
4 Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
5
6 This file is part of GNU CC.
7
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22 #include "config.h"
23 #include "rtl.h"
24 #include "regs.h"
25 #include "hard-reg-set.h"
26 #include "real.h"
27 #include "insn-config.h"
28 #include "conditions.h"
29 #include "insn-flags.h"
30 #include "insn-attr.h"
31 #include "insn-codes.h"
32 #include "recog.h"
33 #include "output.h"
34
35 #undef MAX /* sys/param.h may also define these */
36 #undef MIN
37
38 #include <stdio.h>
39 #include <signal.h>
40 #include <sys/types.h>
41 #include <sys/file.h>
42 #include <ctype.h>
43 #include "tree.h"
44 #include "expr.h"
45 #include "flags.h"
46
47 #ifndef R_OK
48 #define R_OK 4
49 #define W_OK 2
50 #define X_OK 1
51 #endif
52
53 #if defined(USG) || defined(NO_STAB_H)
54 #include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */
55 #else
56 #include <stab.h> /* On BSD, use the system's stab.h. */
57 #endif /* not USG */
58
59 #ifdef __GNU_STAB__
60 #define STAB_CODE_TYPE enum __stab_debug_code
61 #else
62 #define STAB_CODE_TYPE int
63 #endif
64
65 extern void abort ();
66 extern int atoi ();
67 extern char *getenv ();
68 extern char *mktemp ();
69
70 extern rtx adj_offsettable_operand ();
71 extern rtx copy_to_reg ();
72 extern void error ();
73 extern void fatal ();
74 extern tree lookup_name ();
75 extern void pfatal_with_name ();
76 extern void warning ();
77
78 extern tree current_function_decl;
79 extern FILE *asm_out_file;
80
81 /* Enumeration for all of the relational tests, so that we can build
82 arrays indexed by the test type, and not worry about the order
83 of EQ, NE, etc. */
84
85 enum internal_test {
86 ITEST_EQ,
87 ITEST_NE,
88 ITEST_GT,
89 ITEST_GE,
90 ITEST_LT,
91 ITEST_LE,
92 ITEST_GTU,
93 ITEST_GEU,
94 ITEST_LTU,
95 ITEST_LEU,
96 ITEST_MAX
97 };
98
99 /* Global variables for machine-dependent things. */
100
101 /* Threshold for data being put into the small data/bss area, instead
102 of the normal data area (references to the small data/bss area take
103 1 instruction, and use the global pointer, references to the normal
104 data area takes 2 instructions). */
105 int mips_section_threshold = -1;
106
107 /* Count the number of .file directives, so that .loc is up to date. */
108 int num_source_filenames = 0;
109
110 /* Count the number of sdb related labels are generated (to find block
111 start and end boundaries). */
112 int sdb_label_count = 0;
113
114 /* Next label # for each statment for Silicon Graphics IRIS systems. */
115 int sym_lineno = 0;
116
117 /* Non-zero if inside of a function, because the stupid MIPS asm can't
118 handle .files inside of functions. */
119 int inside_function = 0;
120
121 /* Files to separate the text and the data output, so that all of the data
122 can be emitted before the text, which will mean that the assembler will
123 generate smaller code, based on the global pointer. */
124 FILE *asm_out_data_file;
125 FILE *asm_out_text_file;
126
127 /* Linked list of all externals that are to be emitted when optimizing
128 for the global pointer if they haven't been declared by the end of
129 the program with an appropriate .comm or initialization. */
130
131 struct extern_list {
132 struct extern_list *next; /* next external */
133 char *name; /* name of the external */
134 int size; /* size in bytes */
135 } *extern_head = 0;
136
137 /* Name of the file containing the current function. */
138 char *current_function_file = "";
139
140 /* Warning given that Mips ECOFF can't support changing files
141 within a function. */
142 int file_in_function_warning = FALSE;
143
144 /* Whether to suppress issuing .loc's because the user attempted
145 to change the filename within a function. */
146 int ignore_line_number = FALSE;
147
148 /* Number of nested .set noreorder, noat, nomacro, and volatile requests. */
149 int set_noreorder;
150 int set_noat;
151 int set_nomacro;
152 int set_volatile;
153
154 /* The next branch instruction is a branch likely, not branch normal. */
155 int mips_branch_likely;
156
157 /* Count of delay slots and how many are filled. */
158 int dslots_load_total;
159 int dslots_load_filled;
160 int dslots_jump_total;
161 int dslots_jump_filled;
162
163 /* # of nops needed by previous insn */
164 int dslots_number_nops;
165
166 /* Number of 1/2/3 word references to data items (ie, not jal's). */
167 int num_refs[3];
168
169 /* registers to check for load delay */
170 rtx mips_load_reg, mips_load_reg2, mips_load_reg3, mips_load_reg4;
171
172 /* Cached operands, and operator to compare for use in set/branch on
173 condition codes. */
174 rtx branch_cmp[2];
175
176 /* what type of branch to use */
177 enum cmp_type branch_type;
178
179 /* Number of previously seen half-pic pointers and references. */
180 static int prev_half_pic_ptrs = 0;
181 static int prev_half_pic_refs = 0;
182
183 /* which cpu are we scheduling for */
184 enum processor_type mips_cpu;
185
186 /* which instruction set architecture to use. */
187 int mips_isa;
188
189 /* Strings to hold which cpu and instruction set architecture to use. */
190 char *mips_cpu_string; /* for -mcpu=<xxx> */
191 char *mips_isa_string; /* for -mips{1,2,3} */
192
193 /* Array to RTX class classification. At present, we care about
194 whether the operator is an add-type operator, or a divide/modulus,
195 and if divide/modulus, whether it is unsigned. This is for the
196 peephole code. */
197 char mips_rtx_classify[NUM_RTX_CODE];
198
199 /* Array giving truth value on whether or not a given hard register
200 can support a given mode. */
201 char mips_hard_regno_mode_ok[(int)MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
202
203 /* Current frame information calculated by compute_frame_size. */
204 struct mips_frame_info current_frame_info;
205
206 /* Zero structure to initialize current_frame_info. */
207 struct mips_frame_info zero_frame_info;
208
209 /* Temporary filename used to buffer .text until end of program
210 for -mgpopt. */
211 static char *temp_filename;
212
213 /* List of all MIPS punctuation characters used by print_operand. */
214 char mips_print_operand_punct[256];
215
216 /* Map GCC register number to debugger register number. */
217 int mips_dbx_regno[FIRST_PSEUDO_REGISTER];
218
219 /* Buffer to use to enclose a load/store operation with %{ %} to
220 turn on .set volatile. */
221 static char volatile_buffer[60];
222
223 /* Hardware names for the registers. If -mrnames is used, this
224 will be overwritten with mips_sw_reg_names. */
225
226 char mips_reg_names[][8] =
227 {
228 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
229 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
230 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
231 "$24", "$25", "$26", "$27", "$28", "$sp", "$fp", "$31",
232 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
233 "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
234 "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
235 "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
236 "hi", "lo", "$fcr31"
237 };
238
239 /* Mips software names for the registers, used to overwrite the
240 mips_reg_names array. */
241
242 char mips_sw_reg_names[][8] =
243 {
244 "$0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
245 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
246 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
247 "t8", "t9", "k0", "k1", "gp", "sp", "$fp", "ra",
248 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
249 "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
250 "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
251 "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
252 "hi", "lo", "$fcr31"
253 };
254
255 /* Map hard register number to register class */
256 enum reg_class mips_regno_to_class[] =
257 {
258 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
259 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
260 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
261 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
262 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
263 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
264 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
265 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
266 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
267 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
268 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
269 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
270 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
271 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
272 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
273 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
274 HI_REG, LO_REG, ST_REGS
275 };
276
277 /* Map register constraint character to register class. */
278 enum reg_class mips_char_to_class[256] =
279 {
280 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
281 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
282 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
283 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
284 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
285 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
286 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
287 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
288 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
289 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
290 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
291 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
292 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
293 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
294 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
295 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
296 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
297 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
298 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
299 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
300 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
301 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
302 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
303 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
304 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
305 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
306 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
307 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
308 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
309 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
310 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
311 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
312 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
313 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
314 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
315 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
316 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
317 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
318 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
319 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
320 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
321 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
322 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
323 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
324 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
325 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
326 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
327 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
328 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
329 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
330 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
331 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
332 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
333 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
334 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
335 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
336 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
337 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
338 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
339 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
340 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
341 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
342 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
343 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
344 };
345
346 \f
347 /* Return truth value of whether OP can be used as an operands
348 where a register or 16 bit unsigned integer is needed. */
349
350 int
351 uns_arith_operand (op, mode)
352 rtx op;
353 enum machine_mode mode;
354 {
355 if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (op))
356 return TRUE;
357
358 return register_operand (op, mode);
359 }
360
361 /* Return truth value of whether OP can be used as an operands
362 where a 16 bit integer is needed */
363
364 int
365 arith_operand (op, mode)
366 rtx op;
367 enum machine_mode mode;
368 {
369 if (GET_CODE (op) == CONST_INT && SMALL_INT (op))
370 return TRUE;
371
372 return register_operand (op, mode);
373 }
374
375 /* Return truth value of whether OP can be used as an operand in a two
376 address arithmetic insn (such as set 123456,%o4) of mode MODE. */
377
378 int
379 arith32_operand (op, mode)
380 rtx op;
381 enum machine_mode mode;
382 {
383 if (GET_CODE (op) == CONST_INT)
384 return TRUE;
385
386 return register_operand (op, mode);
387 }
388
389 /* Return truth value of whether OP is a integer which fits in 16 bits */
390
391 int
392 small_int (op, mode)
393 rtx op;
394 enum machine_mode mode;
395 {
396 return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
397 }
398
399 /* Return truth value of whether OP is an integer which is too big to
400 be loaded with one instruction. */
401
402 int
403 large_int (op, mode)
404 rtx op;
405 enum machine_mode mode;
406 {
407 HOST_WIDE_INT value;
408
409 if (GET_CODE (op) != CONST_INT)
410 return FALSE;
411
412 value = INTVAL (op);
413 if ((value & ~0x0000ffff) == 0) /* ior reg,$r0,value */
414 return FALSE;
415
416 if (((unsigned long)(value + 32768)) <= 32767) /* subu reg,$r0,value */
417 return FALSE;
418
419 if ((value & 0xffff0000) == value) /* lui reg,value>>16 */
420 return FALSE;
421
422 return TRUE;
423 }
424
425 /* Return truth value of whether OP is a register or the constant 0. */
426
427 int
428 reg_or_0_operand (op, mode)
429 rtx op;
430 enum machine_mode mode;
431 {
432 switch (GET_CODE (op))
433 {
434 default:
435 break;
436
437 case CONST_INT:
438 return (INTVAL (op) == 0);
439
440 case CONST_DOUBLE:
441 if (CONST_DOUBLE_HIGH (op) != 0 || CONST_DOUBLE_LOW (op) != 0)
442 return FALSE;
443
444 return TRUE;
445
446 case REG:
447 case SUBREG:
448 return register_operand (op, mode);
449 }
450
451 return FALSE;
452 }
453
454 /* Return truth value of whether OP is one of the special multiply/divide
455 registers (hi, lo). */
456
457 int
458 md_register_operand (op, mode)
459 rtx op;
460 enum machine_mode mode;
461 {
462 return (GET_MODE_CLASS (mode) == MODE_INT
463 && GET_CODE (op) == REG
464 && MD_REG_P (REGNO (op)));
465 }
466
467 /* Return truth value of whether OP is the FP status register. */
468
469 int
470 fpsw_register_operand (op, mode)
471 rtx op;
472 enum machine_mode mode;
473 {
474 return (GET_CODE (op) == REG && ST_REG_P (REGNO (op)));
475 }
476
477 /* Return truth value if a CONST_DOUBLE is ok to be a legitimate constant. */
478
479 int
480 mips_const_double_ok (op, mode)
481 rtx op;
482 enum machine_mode mode;
483 {
484 if (GET_CODE (op) != CONST_DOUBLE)
485 return FALSE;
486
487 if (mode == DImode)
488 return TRUE;
489
490 if (mode != SFmode && mode != DFmode)
491 return FALSE;
492
493 if (CONST_DOUBLE_HIGH (op) == 0 && CONST_DOUBLE_LOW (op) == 0)
494 return TRUE;
495
496 #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
497 if (TARGET_MIPS_AS) /* gas doesn't like li.d/li.s yet */
498 {
499 union { double d; int i[2]; } u;
500 double d;
501
502 u.i[0] = CONST_DOUBLE_LOW (op);
503 u.i[1] = CONST_DOUBLE_HIGH (op);
504 d = u.d;
505
506 if (d != d)
507 return FALSE; /* NAN */
508
509 if (d < 0.0)
510 d = - d;
511
512 /* Rather than trying to get the accuracy down to the last bit,
513 just use approximate ranges. */
514
515 if (mode == DFmode && d > 1.0e-300 && d < 1.0e300)
516 return TRUE;
517
518 if (mode == SFmode && d > 1.0e-38 && d < 1.0e+38)
519 return TRUE;
520 }
521 #endif
522
523 return FALSE;
524 }
525
526 /* Return truth value if a memory operand fits in a single instruction
527 (ie, register + small offset). */
528
529 int
530 simple_memory_operand (op, mode)
531 rtx op;
532 enum machine_mode mode;
533 {
534 rtx addr, plus0, plus1;
535
536 /* Eliminate non-memory operations */
537 if (GET_CODE (op) != MEM)
538 return FALSE;
539
540 /* dword operations really put out 2 instructions, so eliminate them. */
541 if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
542 return FALSE;
543
544 /* Decode the address now. */
545 addr = XEXP (op, 0);
546 switch (GET_CODE (addr))
547 {
548 default:
549 break;
550
551 case REG:
552 return TRUE;
553
554 case CONST_INT:
555 return SMALL_INT (op);
556
557 case PLUS:
558 plus0 = XEXP (addr, 0);
559 plus1 = XEXP (addr, 1);
560 if (GET_CODE (plus0) == REG
561 && GET_CODE (plus1) == CONST_INT
562 && SMALL_INT (plus1))
563 return TRUE;
564
565 else if (GET_CODE (plus1) == REG
566 && GET_CODE (plus0) == CONST_INT
567 && SMALL_INT (plus0))
568 return TRUE;
569
570 else
571 return FALSE;
572
573 #if 0
574 /* We used to allow small symbol refs here (ie, stuff in .sdata
575 or .sbss), but this causes some bugs in G++. Also, it won't
576 interfere if the MIPS linker rewrites the store instruction
577 because the function is PIC. */
578
579 case LABEL_REF: /* never gp relative */
580 break;
581
582 case CONST:
583 /* If -G 0, we can never have a GP relative memory operation.
584 Also, save some time if not optimizing. */
585 if (mips_section_threshold == 0 || !optimize || !TARGET_GP_OPT)
586 return FALSE;
587
588 {
589 rtx offset = const0_rtx;
590 addr = eliminate_constant_term (addr, &offset);
591 if (GET_CODE (op) != SYMBOL_REF)
592 return FALSE;
593
594 /* let's be paranoid.... */
595 if (INTVAL (offset) < 0 || INTVAL (offset) > 0xffff)
596 return FALSE;
597 }
598 /* fall through */
599
600 case SYMBOL_REF:
601 return SYMBOL_REF_FLAG (addr);
602 #endif
603 }
604
605 return FALSE;
606 }
607
608 /* Return true if the code of this rtx pattern is EQ or NE. */
609
610 int
611 equality_op (op, mode)
612 rtx op;
613 enum machine_mode mode;
614 {
615 if (mode != GET_MODE (op))
616 return FALSE;
617
618 return (classify_op (op, mode) & CLASS_EQUALITY_OP) != 0;
619 }
620
621 /* Return true if the code is a relational operations (EQ, LE, etc.) */
622
623 int
624 cmp_op (op, mode)
625 rtx op;
626 enum machine_mode mode;
627 {
628 if (mode != GET_MODE (op))
629 return FALSE;
630
631 return (classify_op (op, mode) & CLASS_CMP_OP) != 0;
632 }
633
634
635 /* Genrecog does not take the type of match_operator into consideration,
636 and would complain about two patterns being the same if the same
637 function is used, so make it believe they are different. */
638
639 int
640 cmp2_op (op, mode)
641 rtx op;
642 enum machine_mode mode;
643 {
644 if (mode != GET_MODE (op))
645 return FALSE;
646
647 return (classify_op (op, mode) & CLASS_CMP_OP) != 0;
648 }
649
650 /* Return true if the code is an unsigned relational operations (LEU, etc.) */
651
652 int
653 uns_cmp_op (op,mode)
654 rtx op;
655 enum machine_mode mode;
656 {
657 if (mode != GET_MODE (op))
658 return FALSE;
659
660 return (classify_op (op, mode) & CLASS_UNS_CMP_OP) == CLASS_UNS_CMP_OP;
661 }
662
663 /* Return true if the code is a relational operation FP can use. */
664
665 int
666 fcmp_op (op, mode)
667 rtx op;
668 enum machine_mode mode;
669 {
670 if (mode != GET_MODE (op))
671 return FALSE;
672
673 return (classify_op (op, mode) & CLASS_FCMP_OP) != 0;
674 }
675
676
677 /* Return true if the operand is either the PC or a label_ref. */
678
679 int
680 pc_or_label_operand (op, mode)
681 rtx op;
682 enum machine_mode mode;
683 {
684 if (op == pc_rtx)
685 return TRUE;
686
687 if (GET_CODE (op) == LABEL_REF)
688 return TRUE;
689
690 return FALSE;
691 }
692
693 \f
694 /* Return an operand string if the given instruction's delay slot or
695 wrap it in a .set noreorder section. This is for filling delay
696 slots on load type instructions under GAS, which does no reordering
697 on its own. For the MIPS assembler, all we do is update the filled
698 delay slot statistics.
699
700 We assume that operands[0] is the target register that is set.
701
702 In order to check the next insn, most of this functionality is moved
703 to FINAL_PRESCAN_INSN, and we just set the global variables that
704 it needs. */
705
706 char *
707 mips_fill_delay_slot (ret, type, operands, cur_insn)
708 char *ret; /* normal string to return */
709 enum delay_type type; /* type of delay */
710 rtx operands[]; /* operands to use */
711 rtx cur_insn; /* current insn */
712 {
713 register rtx set_reg;
714 register enum machine_mode mode;
715 register rtx next_insn = (cur_insn) ? NEXT_INSN (cur_insn) : (rtx)0;
716 register int num_nops;
717
718 if (type == DELAY_LOAD || type == DELAY_FCMP)
719 num_nops = 1;
720
721 else if (type == DELAY_HILO)
722 num_nops = 2;
723
724 else
725 num_nops = 0;
726
727 /* Make sure that we don't put nop's after labels. */
728 next_insn = NEXT_INSN (cur_insn);
729 while (next_insn != (rtx)0 && GET_CODE (next_insn) == NOTE)
730 next_insn = NEXT_INSN (next_insn);
731
732 dslots_load_total += num_nops;
733 if (TARGET_DEBUG_F_MODE
734 || !optimize
735 || type == DELAY_NONE
736 || operands == (rtx *)0
737 || cur_insn == (rtx)0
738 || next_insn == (rtx)0
739 || GET_CODE (next_insn) == CODE_LABEL
740 || (set_reg = operands[0]) == (rtx)0)
741 {
742 dslots_number_nops = 0;
743 mips_load_reg = (rtx)0;
744 mips_load_reg2 = (rtx)0;
745 mips_load_reg3 = (rtx)0;
746 mips_load_reg4 = (rtx)0;
747 return ret;
748 }
749
750 set_reg = operands[0];
751 if (set_reg == (rtx)0)
752 return ret;
753
754 while (GET_CODE (set_reg) == SUBREG)
755 set_reg = SUBREG_REG (set_reg);
756
757 mode = GET_MODE (set_reg);
758 dslots_number_nops = num_nops;
759 mips_load_reg = set_reg;
760 mips_load_reg2 = (mode == DImode || mode == DFmode)
761 ? gen_rtx (REG, SImode, REGNO (set_reg) + 1)
762 : (rtx)0;
763
764 if (type == DELAY_HILO)
765 {
766 mips_load_reg3 = gen_rtx (REG, SImode, MD_REG_FIRST);
767 mips_load_reg4 = gen_rtx (REG, SImode, MD_REG_FIRST+1);
768 }
769 else
770 {
771 mips_load_reg3 = 0;
772 mips_load_reg4 = 0;
773 }
774
775 if (TARGET_GAS && set_noreorder++ == 0)
776 fputs ("\t.set\tnoreorder\n", asm_out_file);
777
778 return ret;
779 }
780
781 \f
782 /* Determine whether a memory reference takes one (based off of the GP pointer),
783 two (normal), or three (label + reg) instructions, and bump the appropriate
784 counter for -mstats. */
785
786 void
787 mips_count_memory_refs (op, num)
788 rtx op;
789 int num;
790 {
791 int additional = 0;
792 int n_words = 0;
793 rtx addr, plus0, plus1;
794 enum rtx_code code0, code1;
795 int looping;
796
797 if (TARGET_DEBUG_B_MODE)
798 {
799 fprintf (stderr, "\n========== mips_count_memory_refs:\n");
800 debug_rtx (op);
801 }
802
803 /* Skip MEM if passed, otherwise handle movsi of address. */
804 addr = (GET_CODE (op) != MEM) ? op : XEXP (op, 0);
805
806 /* Loop, going through the address RTL */
807 do
808 {
809 looping = FALSE;
810 switch (GET_CODE (addr))
811 {
812 default:
813 break;
814
815 case REG:
816 case CONST_INT:
817 break;
818
819 case PLUS:
820 plus0 = XEXP (addr, 0);
821 plus1 = XEXP (addr, 1);
822 code0 = GET_CODE (plus0);
823 code1 = GET_CODE (plus1);
824
825 if (code0 == REG)
826 {
827 additional++;
828 addr = plus1;
829 looping = TRUE;
830 continue;
831 }
832
833 if (code0 == CONST_INT)
834 {
835 addr = plus1;
836 looping = TRUE;
837 continue;
838 }
839
840 if (code1 == REG)
841 {
842 additional++;
843 addr = plus0;
844 looping = TRUE;
845 continue;
846 }
847
848 if (code1 == CONST_INT)
849 {
850 addr = plus0;
851 looping = TRUE;
852 continue;
853 }
854
855 if (code0 == SYMBOL_REF || code0 == LABEL_REF || code0 == CONST)
856 {
857 addr = plus0;
858 looping = TRUE;
859 continue;
860 }
861
862 if (code1 == SYMBOL_REF || code1 == LABEL_REF || code1 == CONST)
863 {
864 addr = plus1;
865 looping = TRUE;
866 continue;
867 }
868
869 break;
870
871 case LABEL_REF:
872 n_words = 2; /* always 2 words */
873 break;
874
875 case CONST:
876 addr = XEXP (addr, 0);
877 looping = TRUE;
878 continue;
879
880 case SYMBOL_REF:
881 n_words = SYMBOL_REF_FLAG (addr) ? 1 : 2;
882 break;
883 }
884 }
885 while (looping);
886
887 if (n_words == 0)
888 return;
889
890 n_words += additional;
891 if (n_words > 3)
892 n_words = 3;
893
894 num_refs[n_words-1] += num;
895 }
896
897 \f
898 /* Return the appropriate instructions to move one operand to another. */
899
900 char *
901 mips_move_1word (operands, insn, unsignedp)
902 rtx operands[];
903 rtx insn;
904 int unsignedp;
905 {
906 char *ret = 0;
907 rtx op0 = operands[0];
908 rtx op1 = operands[1];
909 enum rtx_code code0 = GET_CODE (op0);
910 enum rtx_code code1 = GET_CODE (op1);
911 enum machine_mode mode = GET_MODE (op0);
912 int subreg_word0 = 0;
913 int subreg_word1 = 0;
914 enum delay_type delay = DELAY_NONE;
915
916 while (code0 == SUBREG)
917 {
918 subreg_word0 += SUBREG_WORD (op0);
919 op0 = SUBREG_REG (op0);
920 code0 = GET_CODE (op0);
921 }
922
923 while (code1 == SUBREG)
924 {
925 subreg_word1 += SUBREG_WORD (op1);
926 op1 = SUBREG_REG (op1);
927 code1 = GET_CODE (op1);
928 }
929
930 if (code0 == REG)
931 {
932 int regno0 = REGNO (op0) + subreg_word0;
933
934 if (code1 == REG)
935 {
936 int regno1 = REGNO (op1) + subreg_word1;
937
938 /* Just in case, don't do anything for assigning a register
939 to itself, unless we are filling a delay slot. */
940 if (regno0 == regno1 && set_nomacro == 0)
941 ret = "";
942
943 else if (GP_REG_P (regno0))
944 {
945 if (GP_REG_P (regno1))
946 ret = "move\t%0,%1";
947
948 else if (MD_REG_P (regno1))
949 {
950 delay = DELAY_HILO;
951 ret = "mf%1\t%0";
952 }
953
954 else
955 {
956 delay = DELAY_LOAD;
957 if (FP_REG_P (regno1))
958 ret = "mfc1\t%0,%1";
959
960 else if (regno1 == FPSW_REGNUM)
961 ret = "cfc1\t%0,$31";
962 }
963 }
964
965 else if (FP_REG_P (regno0))
966 {
967 if (GP_REG_P (regno1))
968 {
969 delay = DELAY_LOAD;
970 ret = "mtc1\t%1,%0";
971 }
972
973 if (FP_REG_P (regno1))
974 ret = "mov.s\t%0,%1";
975 }
976
977 else if (MD_REG_P (regno0))
978 {
979 if (GP_REG_P (regno1))
980 {
981 delay = DELAY_HILO;
982 ret = "mt%0\t%1";
983 }
984 }
985
986 else if (regno0 == FPSW_REGNUM)
987 {
988 if (GP_REG_P (regno1))
989 {
990 delay = DELAY_LOAD;
991 ret = "ctc1\t%0,$31";
992 }
993 }
994 }
995
996 else if (code1 == MEM)
997 {
998 delay = DELAY_LOAD;
999
1000 if (TARGET_STATS)
1001 mips_count_memory_refs (op1, 1);
1002
1003 if (GP_REG_P (regno0))
1004 {
1005 /* For loads, use the mode of the memory item, instead of the
1006 target, so zero/sign extend can use this code as well. */
1007 switch (GET_MODE (op1))
1008 {
1009 default: break;
1010 case SFmode: ret = "lw\t%0,%1"; break;
1011 case SImode: ret = "lw\t%0,%1"; break;
1012 case HImode: ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1"; break;
1013 case QImode: ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1"; break;
1014 }
1015 }
1016
1017 else if (FP_REG_P (regno0) && (mode == SImode || mode == SFmode))
1018 ret = "l.s\t%0,%1";
1019
1020 if (ret != (char *)0 && MEM_VOLATILE_P (op1))
1021 {
1022 int i = strlen (ret);
1023 if (i > sizeof (volatile_buffer) - sizeof ("%{%}"))
1024 abort ();
1025
1026 sprintf (volatile_buffer, "%%{%s%%}", ret);
1027 ret = volatile_buffer;
1028 }
1029 }
1030
1031 else if (code1 == CONST_INT)
1032 {
1033 if (INTVAL (op1) == 0)
1034 {
1035 if (GP_REG_P (regno0))
1036 ret = "move\t%0,%z1";
1037
1038 else if (FP_REG_P (regno0))
1039 {
1040 delay = DELAY_LOAD;
1041 ret = "mtc1\t%z1,%0";
1042 }
1043 }
1044
1045 else if (GP_REG_P (regno0))
1046 ret = (INTVAL (op1) < 0) ? "li\t%0,%1\t\t\t# %X1" : "li\t%0,%X1\t\t# %1";
1047 }
1048
1049 else if (code1 == CONST_DOUBLE && mode == SFmode)
1050 {
1051 if (CONST_DOUBLE_HIGH (op1) == 0 && CONST_DOUBLE_LOW (op1) == 0)
1052 {
1053 if (GP_REG_P (regno0))
1054 ret = "move\t%0,%.";
1055
1056 else if (FP_REG_P (regno0))
1057 {
1058 delay = DELAY_LOAD;
1059 ret = "mtc1\t%.,%0";
1060 }
1061 }
1062
1063 else
1064 {
1065 delay = DELAY_LOAD;
1066 ret = "li.s\t%0,%1";
1067 }
1068 }
1069
1070 else if (code1 == LABEL_REF)
1071 {
1072 if (TARGET_STATS)
1073 mips_count_memory_refs (op1, 1);
1074
1075 ret = "la\t%0,%a1";
1076 }
1077
1078 else if (code1 == SYMBOL_REF || code1 == CONST)
1079 {
1080 if (HALF_PIC_P () && CONSTANT_P (op1) && HALF_PIC_ADDRESS_P (op1))
1081 {
1082 rtx offset = const0_rtx;
1083
1084 if (GET_CODE (op1) == CONST)
1085 op1 = eliminate_constant_term (XEXP (op1, 0), &offset);
1086
1087 if (GET_CODE (op1) == SYMBOL_REF)
1088 {
1089 operands[2] = HALF_PIC_PTR (op1);
1090
1091 if (TARGET_STATS)
1092 mips_count_memory_refs (operands[2], 1);
1093
1094 if (INTVAL (offset) == 0)
1095 {
1096 delay = DELAY_LOAD;
1097 ret = "lw\t%0,%2";
1098 }
1099 else
1100 {
1101 dslots_load_total++;
1102 operands[3] = offset;
1103 ret = (SMALL_INT (offset))
1104 ? "lw\t%0,%2%#\n\tadd\t%0,%0,%3"
1105 : "lw\t%0,%2%#\n\t%[li\t%@,%3\n\tadd\t%0,%0,%@%]";
1106 }
1107 }
1108 }
1109 else
1110 {
1111 if (TARGET_STATS)
1112 mips_count_memory_refs (op1, 1);
1113
1114 ret = "la\t%0,%a1";
1115 }
1116 }
1117
1118 else if (code1 == PLUS)
1119 {
1120 rtx add_op0 = XEXP (op1, 0);
1121 rtx add_op1 = XEXP (op1, 1);
1122
1123 if (GET_CODE (XEXP (op1, 1)) == REG && GET_CODE (XEXP (op1, 0)) == CONST_INT)
1124 {
1125 add_op0 = XEXP (op1, 1); /* reverse operands */
1126 add_op1 = XEXP (op1, 0);
1127 }
1128
1129 operands[2] = add_op0;
1130 operands[3] = add_op1;
1131 ret = "add%:\t%0,%2,%3";
1132 }
1133 }
1134
1135 else if (code0 == MEM)
1136 {
1137 if (TARGET_STATS)
1138 mips_count_memory_refs (op0, 1);
1139
1140 if (code1 == REG)
1141 {
1142 int regno1 = REGNO (op1) + subreg_word1;
1143
1144 if (GP_REG_P (regno1))
1145 {
1146 switch (mode)
1147 {
1148 default: break;
1149 case SFmode: ret = "sw\t%1,%0"; break;
1150 case SImode: ret = "sw\t%1,%0"; break;
1151 case HImode: ret = "sh\t%1,%0"; break;
1152 case QImode: ret = "sb\t%1,%0"; break;
1153 }
1154 }
1155
1156 else if (FP_REG_P (regno1) && (mode == SImode || mode == SFmode))
1157 ret = "s.s\t%1,%0";
1158 }
1159
1160 else if (code1 == CONST_INT && INTVAL (op1) == 0)
1161 {
1162 switch (mode)
1163 {
1164 default: break;
1165 case SFmode: ret = "sw\t%z1,%0"; break;
1166 case SImode: ret = "sw\t%z1,%0"; break;
1167 case HImode: ret = "sh\t%z1,%0"; break;
1168 case QImode: ret = "sb\t%z1,%0"; break;
1169 }
1170 }
1171
1172 else if (code1 == CONST_DOUBLE && CONST_DOUBLE_HIGH (op1) == 0 && CONST_DOUBLE_LOW (op1) == 0)
1173 {
1174 switch (mode)
1175 {
1176 default: break;
1177 case SFmode: ret = "sw\t%.,%0"; break;
1178 case SImode: ret = "sw\t%.,%0"; break;
1179 case HImode: ret = "sh\t%.,%0"; break;
1180 case QImode: ret = "sb\t%.,%0"; break;
1181 }
1182 }
1183
1184 if (ret != (char *)0 && MEM_VOLATILE_P (op0))
1185 {
1186 int i = strlen (ret);
1187 if (i > sizeof (volatile_buffer) - sizeof ("%{%}"))
1188 abort ();
1189
1190 sprintf (volatile_buffer, "%%{%s%%}", ret);
1191 ret = volatile_buffer;
1192 }
1193 }
1194
1195 if (ret == (char *)0)
1196 {
1197 abort_with_insn (insn, "Bad move");
1198 return 0;
1199 }
1200
1201 if (delay != DELAY_NONE)
1202 return mips_fill_delay_slot (ret, delay, operands, insn);
1203
1204 return ret;
1205 }
1206
1207 \f
1208 /* Return the appropriate instructions to move 2 words */
1209
1210 char *
1211 mips_move_2words (operands, insn)
1212 rtx operands[];
1213 rtx insn;
1214 {
1215 char *ret = 0;
1216 rtx op0 = operands[0];
1217 rtx op1 = operands[1];
1218 enum rtx_code code0 = GET_CODE (operands[0]);
1219 enum rtx_code code1 = GET_CODE (operands[1]);
1220 int subreg_word0 = 0;
1221 int subreg_word1 = 0;
1222 enum delay_type delay = DELAY_NONE;
1223
1224 while (code0 == SUBREG)
1225 {
1226 subreg_word0 += SUBREG_WORD (op0);
1227 op0 = SUBREG_REG (op0);
1228 code0 = GET_CODE (op0);
1229 }
1230
1231 while (code1 == SUBREG)
1232 {
1233 subreg_word1 += SUBREG_WORD (op1);
1234 op1 = SUBREG_REG (op1);
1235 code1 = GET_CODE (op1);
1236 }
1237
1238 if (code0 == REG)
1239 {
1240 int regno0 = REGNO (op0) + subreg_word0;
1241
1242 if (code1 == REG)
1243 {
1244 int regno1 = REGNO (op1) + subreg_word1;
1245
1246 /* Just in case, don't do anything for assigning a register
1247 to itself, unless we are filling a delay slot. */
1248 if (regno0 == regno1 && set_nomacro == 0)
1249 ret = "";
1250
1251 else if (FP_REG_P (regno0))
1252 {
1253 if (FP_REG_P (regno1))
1254 ret = "mov.d\t%0,%1";
1255
1256 else
1257 {
1258 delay = DELAY_LOAD;
1259 ret = (TARGET_FLOAT64)
1260 ? "dmtc1\t%1,%0"
1261 : "mtc1\t%L1,%0\n\tmtc1\t%M1,%D0";
1262 }
1263 }
1264
1265 else if (FP_REG_P (regno1))
1266 {
1267 delay = DELAY_LOAD;
1268 ret = (TARGET_FLOAT64)
1269 ? "dmfc1\t%0,%1"
1270 : "mfc1\t%L0,%1\n\tmfc1\t%M0,%D1";
1271 }
1272
1273 else if (MD_REG_P (regno0) && GP_REG_P (regno1))
1274 {
1275 delay = DELAY_HILO;
1276 ret = "mthi\t%M1\n\tmtlo\t%L1";
1277 }
1278
1279 else if (GP_REG_P (regno0) && MD_REG_P (regno1))
1280 {
1281 delay = DELAY_HILO;
1282 ret = "mfhi\t%M0\n\tmflo\t%L0";
1283 }
1284
1285 else if (regno0 != (regno1+1))
1286 ret = "move\t%0,%1\n\tmove\t%D0,%D1";
1287
1288 else
1289 ret = "move\t%D0,%D1\n\tmove\t%0,%1";
1290 }
1291
1292 else if (code1 == CONST_DOUBLE)
1293 {
1294 if (CONST_DOUBLE_HIGH (op1) != 0 || CONST_DOUBLE_LOW (op1) != 0)
1295 {
1296 if (GET_MODE (op1) == DFmode)
1297 {
1298 delay = DELAY_LOAD;
1299 ret = "li.d\t%0,%1";
1300 }
1301
1302 else
1303 {
1304 operands[2] = GEN_INT (CONST_DOUBLE_LOW (op1));
1305 operands[3] = GEN_INT (CONST_DOUBLE_HIGH (op1));
1306 ret = "li\t%M0,%3\n\tli\t%L0,%2";
1307 }
1308 }
1309
1310 else
1311 {
1312 if (GP_REG_P (regno0))
1313 ret = "move\t%0,%.\n\tmove\t%D0,%.";
1314
1315 else if (FP_REG_P (regno0))
1316 {
1317 delay = DELAY_LOAD;
1318 ret = (TARGET_FLOAT64)
1319 ? "dmtc1\t%.,%0"
1320 : "mtc1\t%.,%0\n\tmtc1\t%.,%D0";
1321 }
1322 }
1323 }
1324
1325 else if (code1 == CONST_INT && INTVAL (op1) == 0)
1326 {
1327 if (GP_REG_P (regno0))
1328 ret = "move\t%0,%.\n\tmove\t%D0,%.";
1329
1330 else if (FP_REG_P (regno0))
1331 {
1332 delay = DELAY_LOAD;
1333 ret = (TARGET_FLOAT64)
1334 ? "dmtc1\t%.,%0"
1335 : "mtc1\t%.,%0\n\tmtc1\t%.,%D0";
1336 }
1337 }
1338
1339 else if (code1 == CONST_INT && GET_MODE (op0) == DImode && GP_REG_P (regno0))
1340 {
1341 operands[2] = GEN_INT (INTVAL (operands[1]) >= 0 ? 0 : -1);
1342 ret = "li\t%M0,%2\n\tli\t%L0,%1";
1343 }
1344
1345 else if (code1 == MEM)
1346 {
1347 delay = DELAY_LOAD;
1348
1349 if (TARGET_STATS)
1350 mips_count_memory_refs (op1, 2);
1351
1352 if (FP_REG_P (regno0))
1353 ret = "l.d\t%0,%1";
1354
1355 else if (offsettable_address_p (1, DFmode, XEXP (op1, 0)))
1356 {
1357 operands[2] = adj_offsettable_operand (op1, 4);
1358 if (reg_mentioned_p (op0, op1))
1359 ret = "lw\t%D0,%2\n\tlw\t%0,%1";
1360 else
1361 ret = "lw\t%0,%1\n\tlw\t%D0,%2";
1362 }
1363
1364 if (ret != (char *)0 && MEM_VOLATILE_P (op1))
1365 {
1366 int i = strlen (ret);
1367 if (i > sizeof (volatile_buffer) - sizeof ("%{%}"))
1368 abort ();
1369
1370 sprintf (volatile_buffer, "%%{%s%%}", ret);
1371 ret = volatile_buffer;
1372 }
1373 }
1374 }
1375
1376 else if (code0 == MEM)
1377 {
1378 if (code1 == REG)
1379 {
1380 int regno1 = REGNO (op1) + subreg_word1;
1381
1382 if (FP_REG_P (regno1))
1383 ret = "s.d\t%1,%0";
1384
1385 else if (offsettable_address_p (1, DFmode, XEXP (op0, 0)))
1386 {
1387 operands[2] = adj_offsettable_operand (op0, 4);
1388 ret = "sw\t%1,%0\n\tsw\t%D1,%2";
1389 }
1390 }
1391
1392 else if (code1 == CONST_DOUBLE
1393 && CONST_DOUBLE_HIGH (op1) == 0
1394 && CONST_DOUBLE_LOW (op1) == 0
1395 && offsettable_address_p (1, DFmode, XEXP (op0, 0)))
1396 {
1397 if (TARGET_FLOAT64)
1398 ret = "sd\t%.,%0";
1399 else
1400 {
1401 operands[2] = adj_offsettable_operand (op0, 4);
1402 ret = "sw\t%.,%0\n\tsw\t%.,%2";
1403 }
1404 }
1405
1406 if (TARGET_STATS)
1407 mips_count_memory_refs (op0, 2);
1408
1409 if (ret != (char *)0 && MEM_VOLATILE_P (op0))
1410 {
1411 int i = strlen (ret);
1412 if (i > sizeof (volatile_buffer) - sizeof ("%{%}"))
1413 abort ();
1414
1415 sprintf (volatile_buffer, "%%{%s%%}", ret);
1416 ret = volatile_buffer;
1417 }
1418 }
1419
1420 if (ret == (char *)0)
1421 {
1422 abort_with_insn (insn, "Bad move");
1423 return 0;
1424 }
1425
1426 if (delay != DELAY_NONE)
1427 return mips_fill_delay_slot (ret, delay, operands, insn);
1428
1429 return ret;
1430 }
1431
1432 \f
1433 /* Provide the costs of an addressing mode that contains ADDR.
1434 If ADDR is not a valid address, its cost is irrelevant. */
1435
1436 int
1437 mips_address_cost (addr)
1438 rtx addr;
1439 {
1440 switch (GET_CODE (addr))
1441 {
1442 default:
1443 break;
1444
1445 case LO_SUM:
1446 case HIGH:
1447 return 1;
1448
1449 case LABEL_REF:
1450 return 2;
1451
1452 case CONST:
1453 {
1454 rtx offset = const0_rtx;
1455 addr = eliminate_constant_term (addr, &offset);
1456 if (GET_CODE (addr) == LABEL_REF)
1457 return 2;
1458
1459 if (GET_CODE (addr) != SYMBOL_REF)
1460 return 4;
1461
1462 if (INTVAL (offset) < -32768 || INTVAL (offset) > 32767)
1463 return 2;
1464 }
1465 /* fall through */
1466
1467 case SYMBOL_REF:
1468 return SYMBOL_REF_FLAG (addr) ? 1 : 2;
1469
1470 case PLUS:
1471 {
1472 register rtx plus0 = XEXP (addr, 0);
1473 register rtx plus1 = XEXP (addr, 1);
1474
1475 if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
1476 {
1477 plus0 = XEXP (addr, 1);
1478 plus1 = XEXP (addr, 0);
1479 }
1480
1481 if (GET_CODE (plus0) != REG)
1482 break;
1483
1484 switch (GET_CODE (plus1))
1485 {
1486 default:
1487 break;
1488
1489 case CONST_INT:
1490 {
1491 int value = INTVAL (plus1);
1492 return (value < -32768 || value > 32767) ? 2 : 1;
1493 }
1494
1495 case CONST:
1496 case SYMBOL_REF:
1497 case LABEL_REF:
1498 case HIGH:
1499 case LO_SUM:
1500 return mips_address_cost (plus1) + 1;
1501 }
1502 }
1503 }
1504
1505 return 4;
1506 }
1507
1508 \f
1509 /* Make normal rtx_code into something we can index from an array */
1510
1511 static enum internal_test
1512 map_test_to_internal_test (test_code)
1513 enum rtx_code test_code;
1514 {
1515 enum internal_test test = ITEST_MAX;
1516
1517 switch (test_code)
1518 {
1519 default: break;
1520 case EQ: test = ITEST_EQ; break;
1521 case NE: test = ITEST_NE; break;
1522 case GT: test = ITEST_GT; break;
1523 case GE: test = ITEST_GE; break;
1524 case LT: test = ITEST_LT; break;
1525 case LE: test = ITEST_LE; break;
1526 case GTU: test = ITEST_GTU; break;
1527 case GEU: test = ITEST_GEU; break;
1528 case LTU: test = ITEST_LTU; break;
1529 case LEU: test = ITEST_LEU; break;
1530 }
1531
1532 return test;
1533 }
1534
1535 \f
1536 /* Generate the code to compare two integer values. The return value is:
1537 (reg:SI xx) The pseudo register the comparison is in
1538 (rtx)0 No register, generate a simple branch. */
1539
1540 rtx
1541 gen_int_relational (test_code, result, cmp0, cmp1, p_invert)
1542 enum rtx_code test_code; /* relational test (EQ, etc) */
1543 rtx result; /* result to store comp. or 0 if branch */
1544 rtx cmp0; /* first operand to compare */
1545 rtx cmp1; /* second operand to compare */
1546 int *p_invert; /* NULL or ptr to hold whether branch needs */
1547 /* to reverse its test */
1548 {
1549 struct cmp_info {
1550 enum rtx_code test_code; /* code to use in instruction (LT vs. LTU) */
1551 int const_low; /* low bound of constant we can accept */
1552 int const_high; /* high bound of constant we can accept */
1553 int const_add; /* constant to add (convert LE -> LT) */
1554 int reverse_regs; /* reverse registers in test */
1555 int invert_const; /* != 0 if invert value if cmp1 is constant */
1556 int invert_reg; /* != 0 if invert value if cmp1 is register */
1557 };
1558
1559 static struct cmp_info info[ (int)ITEST_MAX ] = {
1560
1561 { XOR, 0, 65535, 0, 0, 0, 0 }, /* EQ */
1562 { XOR, 0, 65535, 0, 0, 1, 1 }, /* NE */
1563 { LT, -32769, 32766, 1, 1, 1, 0 }, /* GT */
1564 { LT, -32768, 32767, 0, 0, 1, 1 }, /* GE */
1565 { LT, -32768, 32767, 0, 0, 0, 0 }, /* LT */
1566 { LT, -32769, 32766, 1, 1, 0, 1 }, /* LE */
1567 { LTU, -32769, 32766, 1, 1, 1, 0 }, /* GTU */
1568 { LTU, -32768, 32767, 0, 0, 1, 1 }, /* GEU */
1569 { LTU, -32768, 32767, 0, 0, 0, 0 }, /* LTU */
1570 { LTU, -32769, 32766, 1, 1, 0, 1 }, /* LEU */
1571 };
1572
1573 enum internal_test test;
1574 struct cmp_info *p_info;
1575 int branch_p;
1576 int eqne_p;
1577 int invert;
1578 rtx reg;
1579 rtx reg2;
1580
1581 test = map_test_to_internal_test (test_code);
1582 if (test == ITEST_MAX)
1583 abort ();
1584
1585 p_info = &info[ (int)test ];
1586 eqne_p = (p_info->test_code == XOR);
1587
1588 /* Eliminate simple branches */
1589 branch_p = (result == (rtx)0);
1590 if (branch_p)
1591 {
1592 if (GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG)
1593 {
1594 /* Comparisons against zero are simple branches */
1595 if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
1596 return (rtx)0;
1597
1598 /* Test for beq/bne. */
1599 if (eqne_p)
1600 return (rtx)0;
1601 }
1602
1603 /* allocate a pseudo to calculate the value in. */
1604 result = gen_reg_rtx (SImode);
1605 }
1606
1607 /* Make sure we can handle any constants given to us. */
1608 if (GET_CODE (cmp0) == CONST_INT)
1609 cmp0 = force_reg (SImode, cmp0);
1610
1611 if (GET_CODE (cmp1) == CONST_INT)
1612 {
1613 HOST_WIDE_INT value = INTVAL (cmp1);
1614 if (value < p_info->const_low || value > p_info->const_high)
1615 cmp1 = force_reg (SImode, cmp1);
1616 }
1617
1618 /* See if we need to invert the result. */
1619 invert = (GET_CODE (cmp1) == CONST_INT)
1620 ? p_info->invert_const
1621 : p_info->invert_reg;
1622
1623 if (p_invert != (int *)0)
1624 {
1625 *p_invert = invert;
1626 invert = FALSE;
1627 }
1628
1629 /* Comparison to constants, may involve adding 1 to change a LT into LE.
1630 Comparison between two registers, may involve switching operands. */
1631 if (GET_CODE (cmp1) == CONST_INT)
1632 {
1633 if (p_info->const_add != 0)
1634 cmp1 = GEN_INT (INTVAL (cmp1) + p_info->const_add);
1635 }
1636 else if (p_info->reverse_regs)
1637 {
1638 rtx temp = cmp0;
1639 cmp0 = cmp1;
1640 cmp1 = temp;
1641 }
1642
1643 if (test == ITEST_NE && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
1644 reg = cmp0;
1645 else
1646 {
1647 reg = (invert || eqne_p) ? gen_reg_rtx (SImode) : result;
1648 emit_move_insn (reg, gen_rtx (p_info->test_code, SImode, cmp0, cmp1));
1649 }
1650
1651 if (test == ITEST_NE)
1652 {
1653 emit_move_insn (result, gen_rtx (GTU, SImode, reg, const0_rtx));
1654 invert = FALSE;
1655 }
1656
1657 else if (test == ITEST_EQ)
1658 {
1659 reg2 = (invert) ? gen_reg_rtx (SImode) : result;
1660 emit_move_insn (reg2, gen_rtx (LTU, SImode, reg, const1_rtx));
1661 reg = reg2;
1662 }
1663
1664 if (invert)
1665 emit_move_insn (result, gen_rtx (XOR, SImode, reg, const1_rtx));
1666
1667 return result;
1668 }
1669
1670 \f
1671 /* Emit the common code for doing conditional branches.
1672 operand[0] is the label to jump to.
1673 The comparison operands are saved away by cmp{si,sf,df}. */
1674
1675 void
1676 gen_conditional_branch (operands, test_code)
1677 rtx operands[];
1678 enum rtx_code test_code;
1679 {
1680 static enum machine_mode mode_map[(int)CMP_MAX][(int)ITEST_MAX] = {
1681 { /* CMP_SI */
1682 SImode, /* eq */
1683 SImode, /* ne */
1684 SImode, /* gt */
1685 SImode, /* ge */
1686 SImode, /* lt */
1687 SImode, /* le */
1688 SImode, /* gtu */
1689 SImode, /* geu */
1690 SImode, /* ltu */
1691 SImode, /* leu */
1692 },
1693 { /* CMP_SF */
1694 CC_FPmode, /* eq */
1695 CC_REV_FPmode, /* ne */
1696 CC_FPmode, /* gt */
1697 CC_FPmode, /* ge */
1698 CC_FPmode, /* lt */
1699 CC_FPmode, /* le */
1700 VOIDmode, /* gtu */
1701 VOIDmode, /* geu */
1702 VOIDmode, /* ltu */
1703 VOIDmode, /* leu */
1704 },
1705 { /* CMP_DF */
1706 CC_FPmode, /* eq */
1707 CC_REV_FPmode, /* ne */
1708 CC_FPmode, /* gt */
1709 CC_FPmode, /* ge */
1710 CC_FPmode, /* lt */
1711 CC_FPmode, /* le */
1712 VOIDmode, /* gtu */
1713 VOIDmode, /* geu */
1714 VOIDmode, /* ltu */
1715 VOIDmode, /* leu */
1716 },
1717 };
1718
1719 enum machine_mode mode;
1720 enum cmp_type type = branch_type;
1721 rtx cmp0 = branch_cmp[0];
1722 rtx cmp1 = branch_cmp[1];
1723 rtx label1 = gen_rtx (LABEL_REF, VOIDmode, operands[0]);
1724 rtx label2 = pc_rtx;
1725 rtx reg = (rtx)0;
1726 int invert = 0;
1727 enum internal_test test = map_test_to_internal_test (test_code);
1728
1729 if (test == ITEST_MAX)
1730 {
1731 mode = SImode;
1732 goto fail;
1733 }
1734
1735 /* Get the machine mode to use (CCmode, CC_EQmode, CC_FPmode, or CC_REV_FPmode). */
1736 mode = mode_map[(int)type][(int)test];
1737 if (mode == VOIDmode)
1738 goto fail;
1739
1740 switch (branch_type)
1741 {
1742 default:
1743 goto fail;
1744
1745 case CMP_SI:
1746 reg = gen_int_relational (test_code, (rtx)0, cmp0, cmp1, &invert);
1747 if (reg != (rtx)0)
1748 {
1749 cmp0 = reg;
1750 cmp1 = const0_rtx;
1751 test_code = NE;
1752 }
1753
1754 /* Make sure not non-zero constant if ==/!= */
1755 else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
1756 cmp1 = force_reg (SImode, cmp1);
1757
1758 break;
1759
1760 case CMP_DF:
1761 case CMP_SF:
1762 {
1763 rtx reg = gen_rtx (REG, mode, FPSW_REGNUM);
1764 emit_insn (gen_rtx (SET, VOIDmode, reg, gen_rtx (test_code, mode, cmp0, cmp1)));
1765 cmp0 = reg;
1766 cmp1 = const0_rtx;
1767 test_code = NE;
1768 }
1769 break;
1770 }
1771
1772 /* Generate the jump */
1773 if (invert)
1774 {
1775 label2 = label1;
1776 label1 = pc_rtx;
1777 }
1778
1779 emit_jump_insn (gen_rtx (SET, VOIDmode,
1780 pc_rtx,
1781 gen_rtx (IF_THEN_ELSE, VOIDmode,
1782 gen_rtx (test_code, mode, cmp0, cmp1),
1783 label1,
1784 label2)));
1785
1786 return;
1787
1788 fail:
1789 abort_with_insn (gen_rtx (test_code, mode, cmp0, cmp1), "bad test");
1790 }
1791
1792 \f
1793 #define UNITS_PER_SHORT (SHORT_TYPE_SIZE / BITS_PER_UNIT)
1794
1795 /* Internal code to generate the load and store of one word/short/byte.
1796 The load is emitted directly, and the store insn is returned. */
1797
1798 #if 0
1799 static rtx
1800 block_move_load_store (dest_reg, src_reg, p_bytes, p_offset, align, orig_src)
1801 rtx src_reg; /* register holding source memory address */
1802 rtx dest_reg; /* register holding dest. memory address */
1803 int *p_bytes; /* pointer to # bytes remaining */
1804 int *p_offset; /* pointer to current offset */
1805 int align; /* alignment */
1806 rtx orig_src; /* original source for making a reg note */
1807 {
1808 int bytes; /* # bytes remaining */
1809 int offset; /* offset to use */
1810 int size; /* size in bytes of load/store */
1811 enum machine_mode mode; /* mode to use for load/store */
1812 rtx reg; /* temporary register */
1813 rtx src_addr; /* source address */
1814 rtx dest_addr; /* destination address */
1815 rtx insn; /* insn of the load */
1816 rtx orig_src_addr; /* original source address */
1817 rtx (*load_func)(); /* function to generate load insn */
1818 rtx (*store_func)(); /* function to generate destination insn */
1819
1820 bytes = *p_bytes;
1821 if (bytes <= 0 || align <= 0)
1822 abort ();
1823
1824 if (bytes >= UNITS_PER_WORD && align >= UNITS_PER_WORD)
1825 {
1826 mode = SImode;
1827 size = UNITS_PER_WORD;
1828 load_func = gen_movsi;
1829 store_func = gen_movsi;
1830 }
1831
1832 #if 0
1833 /* Don't generate unligned moves here, rather defer those to the
1834 general movestrsi_internal pattern. */
1835 else if (bytes >= UNITS_PER_WORD)
1836 {
1837 mode = SImode;
1838 size = UNITS_PER_WORD;
1839 load_func = gen_movsi_ulw;
1840 store_func = gen_movsi_usw;
1841 }
1842 #endif
1843
1844 else if (bytes >= UNITS_PER_SHORT && align >= UNITS_PER_SHORT)
1845 {
1846 mode = HImode;
1847 size = UNITS_PER_SHORT;
1848 load_func = gen_movhi;
1849 store_func = gen_movhi;
1850 }
1851
1852 else
1853 {
1854 mode = QImode;
1855 size = 1;
1856 load_func = gen_movqi;
1857 store_func = gen_movqi;
1858 }
1859
1860 offset = *p_offset;
1861 *p_offset = offset + size;
1862 *p_bytes = bytes - size;
1863
1864 if (offset == 0)
1865 {
1866 src_addr = src_reg;
1867 dest_addr = dest_reg;
1868 }
1869 else
1870 {
1871 src_addr = gen_rtx (PLUS, Pmode, src_reg, GEN_INT (offset));
1872 dest_addr = gen_rtx (PLUS, Pmode, dest_reg, GEN_INT (offset));
1873 }
1874
1875 reg = gen_reg_rtx (mode);
1876 insn = emit_insn ((*load_func) (reg, gen_rtx (MEM, mode, src_addr)));
1877 orig_src_addr = XEXP (orig_src, 0);
1878 if (CONSTANT_P (orig_src_addr))
1879 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUIV,
1880 plus_constant (orig_src_addr, offset),
1881 REG_NOTES (insn));
1882
1883 return (*store_func) (gen_rtx (MEM, mode, dest_addr), reg);
1884 }
1885 #endif
1886
1887 \f
1888 /* Write a series of loads/stores to move some bytes. Generate load/stores as follows:
1889
1890 load 1
1891 load 2
1892 load 3
1893 store 1
1894 load 4
1895 store 2
1896 load 5
1897 store 3
1898 ...
1899
1900 This way, no NOP's are needed, except at the end, and only
1901 two temp registers are needed. Two delay slots are used
1902 in deference to the R4000. */
1903
1904 #if 0
1905 static void
1906 block_move_sequence (dest_reg, src_reg, bytes, align, orig_src)
1907 rtx dest_reg; /* register holding destination address */
1908 rtx src_reg; /* register holding source address */
1909 int bytes; /* # bytes to move */
1910 int align; /* max alignment to assume */
1911 rtx orig_src; /* original source for making a reg note */
1912 {
1913 int offset = 0;
1914 rtx prev2_store = (rtx)0;
1915 rtx prev_store = (rtx)0;
1916 rtx cur_store = (rtx)0;
1917
1918 while (bytes > 0)
1919 {
1920 /* Is there a store to do? */
1921 if (prev2_store)
1922 emit_insn (prev2_store);
1923
1924 prev2_store = prev_store;
1925 prev_store = cur_store;
1926 cur_store = block_move_load_store (dest_reg, src_reg,
1927 &bytes, &offset,
1928 align, orig_src);
1929 }
1930
1931 /* Finish up last three stores. */
1932 if (prev2_store)
1933 emit_insn (prev2_store);
1934
1935 if (prev_store)
1936 emit_insn (prev_store);
1937
1938 if (cur_store)
1939 emit_insn (cur_store);
1940 }
1941 #endif
1942
1943 \f
1944 /* Write a loop to move a constant number of bytes. Generate load/stores as follows:
1945
1946 do {
1947 temp1 = src[0];
1948 temp2 = src[1];
1949 ...
1950 temp<last> = src[MAX_MOVE_REGS-1];
1951 dest[0] = temp1;
1952 dest[1] = temp2;
1953 ...
1954 dest[MAX_MOVE_REGS-1] = temp<last>;
1955 src += MAX_MOVE_REGS;
1956 dest += MAX_MOVE_REGS;
1957 } while (src != final);
1958
1959 This way, no NOP's are needed, and only MAX_MOVE_REGS+3 temp
1960 registers are needed.
1961
1962 Aligned moves move MAX_MOVE_REGS*4 bytes every (2*MAX_MOVE_REGS)+3
1963 cycles, unaligned moves move MAX_MOVE_REGS*4 bytes every
1964 (4*MAX_MOVE_REGS)+3 cycles, assuming no cache misses. */
1965
1966 #define MAX_MOVE_REGS 4
1967 #define MAX_MOVE_BYTES (MAX_MOVE_REGS * UNITS_PER_WORD)
1968
1969 static void
1970 block_move_loop (dest_reg, src_reg, bytes, align, orig_src)
1971 rtx dest_reg; /* register holding destination address */
1972 rtx src_reg; /* register holding source address */
1973 int bytes; /* # bytes to move */
1974 int align; /* alignment */
1975 rtx orig_src; /* original source for making a reg note */
1976 {
1977 rtx dest_mem = gen_rtx (MEM, BLKmode, dest_reg);
1978 rtx src_mem = gen_rtx (MEM, BLKmode, src_reg);
1979 rtx align_rtx = GEN_INT (align);
1980 rtx label;
1981 rtx final_src;
1982 rtx bytes_rtx;
1983 int leftover;
1984
1985 if (bytes < 2*MAX_MOVE_BYTES)
1986 abort ();
1987
1988 leftover = bytes % MAX_MOVE_BYTES;
1989 bytes -= leftover;
1990
1991 label = gen_label_rtx ();
1992 final_src = gen_reg_rtx (Pmode);
1993 bytes_rtx = GEN_INT (bytes);
1994
1995 if (bytes > 0x7fff)
1996 {
1997 emit_insn (gen_movsi (final_src, bytes_rtx));
1998 emit_insn (gen_addsi3 (final_src, final_src, src_reg));
1999 }
2000 else
2001 emit_insn (gen_addsi3 (final_src, src_reg, bytes_rtx));
2002
2003 emit_label (label);
2004
2005 bytes_rtx = GEN_INT (MAX_MOVE_BYTES);
2006 emit_insn (gen_movstrsi_internal (dest_mem, src_mem, bytes_rtx, align_rtx));
2007 emit_insn (gen_addsi3 (src_reg, src_reg, bytes_rtx));
2008 emit_insn (gen_addsi3 (dest_reg, dest_reg, bytes_rtx));
2009 emit_insn (gen_cmpsi (src_reg, final_src));
2010 emit_jump_insn (gen_bne (label));
2011
2012 if (leftover)
2013 emit_insn (gen_movstrsi_internal (dest_mem, src_mem,
2014 GEN_INT (leftover),
2015 align_rtx));
2016 }
2017
2018 \f
2019 /* Use a library function to move some bytes. */
2020
2021 static void
2022 block_move_call (dest_reg, src_reg, bytes_rtx)
2023 rtx dest_reg;
2024 rtx src_reg;
2025 rtx bytes_rtx;
2026 {
2027 #ifdef TARGET_MEM_FUNCTIONS
2028 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"), 0,
2029 VOIDmode, 3,
2030 dest_reg, Pmode,
2031 src_reg, Pmode,
2032 bytes_rtx, SImode);
2033 #else
2034 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"), 0,
2035 VOIDmode, 3,
2036 src_reg, Pmode,
2037 dest_reg, Pmode,
2038 bytes_rtx, SImode);
2039 #endif
2040 }
2041
2042 \f
2043 /* Expand string/block move operations.
2044
2045 operands[0] is the pointer to the destination.
2046 operands[1] is the pointer to the source.
2047 operands[2] is the number of bytes to move.
2048 operands[3] is the alignment. */
2049
2050 void
2051 expand_block_move (operands)
2052 rtx operands[];
2053 {
2054 rtx bytes_rtx = operands[2];
2055 rtx align_rtx = operands[3];
2056 int constp = (GET_CODE (bytes_rtx) == CONST_INT);
2057 int bytes = (constp ? INTVAL (bytes_rtx) : 0);
2058 int align = INTVAL (align_rtx);
2059 rtx orig_src = operands[1];
2060 rtx src_reg;
2061 rtx dest_reg;
2062
2063 if (constp && bytes <= 0)
2064 return;
2065
2066 if (align > UNITS_PER_WORD)
2067 align = UNITS_PER_WORD;
2068
2069 /* Move the address into scratch registers. */
2070 dest_reg = copy_addr_to_reg (XEXP (operands[0], 0));
2071 src_reg = copy_addr_to_reg (XEXP (orig_src, 0));
2072
2073 if (TARGET_MEMCPY)
2074 block_move_call (dest_reg, src_reg, bytes_rtx);
2075
2076 #if 0
2077 else if (constp && bytes <= 3*align)
2078 block_move_sequence (dest_reg, src_reg, bytes, align, orig_src);
2079 #endif
2080
2081 else if (constp && bytes <= 2*MAX_MOVE_BYTES)
2082 emit_insn (gen_movstrsi_internal (gen_rtx (MEM, BLKmode, dest_reg),
2083 gen_rtx (MEM, BLKmode, src_reg),
2084 bytes_rtx, align_rtx));
2085
2086 else if (constp && align >= UNITS_PER_WORD && optimize)
2087 block_move_loop (dest_reg, src_reg, bytes, align, orig_src);
2088
2089 else if (constp && optimize)
2090 {
2091 /* If the alignment is not word aligned, generate a test at
2092 runtime, to see whether things wound up aligned, and we
2093 can use the faster lw/sw instead ulw/usw. */
2094
2095 rtx temp = gen_reg_rtx (Pmode);
2096 rtx aligned_label = gen_label_rtx ();
2097 rtx join_label = gen_label_rtx ();
2098 int leftover = bytes % MAX_MOVE_BYTES;
2099
2100 bytes -= leftover;
2101
2102 emit_insn (gen_iorsi3 (temp, src_reg, dest_reg));
2103 emit_insn (gen_andsi3 (temp, temp, GEN_INT (UNITS_PER_WORD-1)));
2104 emit_insn (gen_cmpsi (temp, const0_rtx));
2105 emit_jump_insn (gen_beq (aligned_label));
2106
2107 /* Unaligned loop. */
2108 block_move_loop (dest_reg, src_reg, bytes, 1, orig_src);
2109 emit_jump_insn (gen_jump (join_label));
2110 emit_barrier ();
2111
2112 /* Aligned loop. */
2113 emit_label (aligned_label);
2114 block_move_loop (dest_reg, src_reg, bytes, UNITS_PER_WORD, orig_src);
2115 emit_label (join_label);
2116
2117 /* Bytes at the end of the loop. */
2118 if (leftover)
2119 {
2120 #if 0
2121 if (leftover <= 3*align)
2122 block_move_sequence (dest_reg, src_reg, leftover, align, orig_src);
2123
2124 else
2125 #endif
2126 emit_insn (gen_movstrsi_internal (gen_rtx (MEM, BLKmode, dest_reg),
2127 gen_rtx (MEM, BLKmode, src_reg),
2128 GEN_INT (leftover),
2129 GEN_INT (align)));
2130 }
2131 }
2132
2133 else
2134 block_move_call (dest_reg, src_reg, bytes_rtx);
2135 }
2136
2137 \f
2138 /* Emit load/stores for a small constant block_move.
2139
2140 operands[0] is the memory address of the destination.
2141 operands[1] is the memory address of the source.
2142 operands[2] is the number of bytes to move.
2143 operands[3] is the alignment.
2144 operands[4] is a temp register.
2145 operands[5] is a temp register.
2146 ...
2147 operands[3+num_regs] is the last temp register.
2148
2149 The block move type can be one of the following:
2150 BLOCK_MOVE_NORMAL Do all of the block move.
2151 BLOCK_MOVE_NOT_LAST Do all but the last store.
2152 BLOCK_MOVE_LAST Do just the last store. */
2153
2154 char *
2155 output_block_move (insn, operands, num_regs, move_type)
2156 rtx insn;
2157 rtx operands[];
2158 int num_regs;
2159 enum block_move_type move_type;
2160 {
2161 rtx dest_reg = XEXP (operands[0], 0);
2162 rtx src_reg = XEXP (operands[1], 0);
2163 int bytes = INTVAL (operands[2]);
2164 int align = INTVAL (operands[3]);
2165 int num = 0;
2166 int offset = 0;
2167 int use_lwl_lwr = FALSE;
2168 int last_operand = num_regs+4;
2169 int i;
2170 rtx xoperands[10];
2171
2172 struct {
2173 char *load; /* load insn without nop */
2174 char *load_nop; /* load insn with trailing nop */
2175 char *store; /* store insn */
2176 char *final; /* if last_store used: NULL or swr */
2177 char *last_store; /* last store instruction */
2178 int offset; /* current offset */
2179 enum machine_mode mode; /* mode to use on (MEM) */
2180 } load_store[4];
2181
2182 /* Detect a bug in GCC, where it can give us a register
2183 the same as one of the addressing registers. */
2184 for (i = 4; i < last_operand; i++)
2185 {
2186 if (reg_mentioned_p (operands[i], operands[0])
2187 || reg_mentioned_p (operands[i], operands[1]))
2188 {
2189 abort_with_insn (insn, "register passed as address and temp register to block move");
2190 }
2191 }
2192
2193 /* If we are given global or static addresses, and we would be
2194 emitting a few instructions, try to save time by using a
2195 temporary register for the pointer. */
2196 if (bytes > 2*align || move_type != BLOCK_MOVE_NORMAL)
2197 {
2198 if (CONSTANT_P (src_reg))
2199 {
2200 if (TARGET_STATS)
2201 mips_count_memory_refs (operands[1], 1);
2202
2203 src_reg = operands[ 3 + num_regs-- ];
2204 if (move_type != BLOCK_MOVE_LAST)
2205 {
2206 xoperands[1] = operands[1];
2207 xoperands[0] = src_reg;
2208 output_asm_insn ("la\t%0,%1", xoperands);
2209 }
2210 }
2211
2212 if (CONSTANT_P (dest_reg))
2213 {
2214 if (TARGET_STATS)
2215 mips_count_memory_refs (operands[0], 1);
2216
2217 dest_reg = operands[ 3 + num_regs-- ];
2218 if (move_type != BLOCK_MOVE_LAST)
2219 {
2220 xoperands[1] = operands[0];
2221 xoperands[0] = dest_reg;
2222 output_asm_insn ("la\t%0,%1", xoperands);
2223 }
2224 }
2225 }
2226
2227 if (num_regs > (sizeof (load_store) / sizeof (load_store[0])))
2228 num_regs = (sizeof (load_store) / sizeof (load_store[0]));
2229
2230 else if (num_regs < 1)
2231 abort ();
2232
2233 if (TARGET_GAS && move_type != BLOCK_MOVE_LAST && set_noreorder++ == 0)
2234 output_asm_insn (".set\tnoreorder", operands);
2235
2236 while (bytes > 0)
2237 {
2238 load_store[num].offset = offset;
2239
2240 if (bytes >= UNITS_PER_WORD && align >= UNITS_PER_WORD)
2241 {
2242 load_store[num].load = "lw\t%0,%1";
2243 load_store[num].load_nop = "lw\t%0,%1%#";
2244 load_store[num].store = "sw\t%0,%1";
2245 load_store[num].last_store = "sw\t%0,%1";
2246 load_store[num].final = (char *)0;
2247 load_store[num].mode = SImode;
2248 offset += UNITS_PER_WORD;
2249 bytes -= UNITS_PER_WORD;
2250 }
2251
2252 else if (bytes >= UNITS_PER_WORD)
2253 {
2254 #if BYTES_BIG_ENDIAN
2255 load_store[num].load = "lwl\t%0,%1\n\tlwr\t%0,%2";
2256 load_store[num].load_nop = "lwl\t%0,%1\n\tlwr\t%0,%2%#";
2257 load_store[num].store = "swl\t%0,%1\n\tswr\t%0,%2";
2258 load_store[num].last_store = "swr\t%0,%2";
2259 load_store[num].final = "swl\t%0,%1";
2260 #else
2261 load_store[num].load = "lwl\t%0,%2\n\tlwr\t%0,%1";
2262 load_store[num].load_nop = "lwl\t%0,%2\n\tlwr\t%0,%1%#";
2263 load_store[num].store = "swl\t%0,%2\n\tswr\t%0,%1";
2264 load_store[num].last_store = "swr\t%0,%1";
2265 load_store[num].final = "swl\t%0,%2";
2266 #endif
2267 load_store[num].mode = SImode;
2268 offset += UNITS_PER_WORD;
2269 bytes -= UNITS_PER_WORD;
2270 use_lwl_lwr = TRUE;
2271 }
2272
2273 else if (bytes >= UNITS_PER_SHORT && align >= UNITS_PER_SHORT)
2274 {
2275 load_store[num].load = "lh\t%0,%1";
2276 load_store[num].load_nop = "lh\t%0,%1%#";
2277 load_store[num].store = "sh\t%0,%1";
2278 load_store[num].last_store = "sh\t%0,%1";
2279 load_store[num].final = (char *)0;
2280 load_store[num].offset = offset;
2281 load_store[num].mode = HImode;
2282 offset += UNITS_PER_SHORT;
2283 bytes -= UNITS_PER_SHORT;
2284 }
2285
2286 else
2287 {
2288 load_store[num].load = "lb\t%0,%1";
2289 load_store[num].load_nop = "lb\t%0,%1%#";
2290 load_store[num].store = "sb\t%0,%1";
2291 load_store[num].last_store = "sb\t%0,%1";
2292 load_store[num].final = (char *)0;
2293 load_store[num].mode = QImode;
2294 offset++;
2295 bytes--;
2296 }
2297
2298 if (TARGET_STATS && move_type != BLOCK_MOVE_LAST)
2299 {
2300 dslots_load_total++;
2301 dslots_load_filled++;
2302
2303 if (CONSTANT_P (src_reg))
2304 mips_count_memory_refs (src_reg, 1);
2305
2306 if (CONSTANT_P (dest_reg))
2307 mips_count_memory_refs (dest_reg, 1);
2308 }
2309
2310 /* Emit load/stores now if we have run out of registers or are
2311 at the end of the move. */
2312
2313 if (++num == num_regs || bytes == 0)
2314 {
2315 /* If only load/store, we need a NOP after the load. */
2316 if (num == 1)
2317 {
2318 load_store[0].load = load_store[0].load_nop;
2319 if (TARGET_STATS && move_type != BLOCK_MOVE_LAST)
2320 dslots_load_filled--;
2321 }
2322
2323 if (move_type != BLOCK_MOVE_LAST)
2324 {
2325 for (i = 0; i < num; i++)
2326 {
2327 int offset;
2328
2329 if (!operands[i+4])
2330 abort ();
2331
2332 if (GET_MODE (operands[i+4]) != load_store[i].mode)
2333 operands[i+4] = gen_rtx (REG, load_store[i].mode, REGNO (operands[i+4]));
2334
2335 offset = load_store[i].offset;
2336 xoperands[0] = operands[i+4];
2337 xoperands[1] = gen_rtx (MEM, load_store[i].mode,
2338 plus_constant (src_reg, offset));
2339
2340 if (use_lwl_lwr)
2341 xoperands[2] = gen_rtx (MEM, load_store[i].mode,
2342 plus_constant (src_reg, UNITS_PER_WORD-1+offset));
2343
2344 output_asm_insn (load_store[i].load, xoperands);
2345 }
2346 }
2347
2348 for (i = 0; i < num; i++)
2349 {
2350 int last_p = (i == num-1 && bytes == 0);
2351 int offset = load_store[i].offset;
2352
2353 xoperands[0] = operands[i+4];
2354 xoperands[1] = gen_rtx (MEM, load_store[i].mode,
2355 plus_constant (dest_reg, offset));
2356
2357
2358 if (use_lwl_lwr)
2359 xoperands[2] = gen_rtx (MEM, load_store[i].mode,
2360 plus_constant (dest_reg, UNITS_PER_WORD-1+offset));
2361
2362 if (move_type == BLOCK_MOVE_NORMAL)
2363 output_asm_insn (load_store[i].store, xoperands);
2364
2365 else if (move_type == BLOCK_MOVE_NOT_LAST)
2366 {
2367 if (!last_p)
2368 output_asm_insn (load_store[i].store, xoperands);
2369
2370 else if (load_store[i].final != (char *)0)
2371 output_asm_insn (load_store[i].final, xoperands);
2372 }
2373
2374 else if (last_p)
2375 output_asm_insn (load_store[i].last_store, xoperands);
2376 }
2377
2378 num = 0; /* reset load_store */
2379 use_lwl_lwr = FALSE; /* reset whether or not we used lwl/lwr */
2380 }
2381 }
2382
2383 if (TARGET_GAS && move_type != BLOCK_MOVE_LAST && --set_noreorder == 0)
2384 output_asm_insn (".set\treorder", operands);
2385
2386 return "";
2387 }
2388
2389 \f
2390 /* Argument support functions. */
2391
2392 /* Initialize CUMULATIVE_ARGS for a function. */
2393
2394 void
2395 init_cumulative_args (cum, fntype, libname)
2396 CUMULATIVE_ARGS *cum; /* argument info to initialize */
2397 tree fntype; /* tree ptr for function decl */
2398 rtx libname; /* SYMBOL_REF of library name or 0 */
2399 {
2400 tree param, next_param;
2401
2402 if (TARGET_DEBUG_E_MODE)
2403 {
2404 fprintf (stderr, "\ninit_cumulative_args, fntype = 0x%.8lx", (long)fntype);
2405 if (!fntype)
2406 fputc ('\n', stderr);
2407
2408 else
2409 {
2410 tree ret_type = TREE_TYPE (fntype);
2411 fprintf (stderr, ", fntype code = %s, ret code = %s\n",
2412 tree_code_name[ (int)TREE_CODE (fntype) ],
2413 tree_code_name[ (int)TREE_CODE (ret_type) ]);
2414 }
2415 }
2416
2417 cum->gp_reg_found = 0;
2418 cum->arg_number = 0;
2419 cum->arg_words = 0;
2420
2421 /* Determine if this function has variable arguments. This is
2422 indicated by the last argument being 'void_type_mode' if there
2423 are no variable arguments. The standard MIPS calling sequence
2424 passes all arguments in the general purpose registers in this
2425 case. */
2426
2427 for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
2428 param != (tree)0;
2429 param = next_param)
2430 {
2431 next_param = TREE_CHAIN (param);
2432 if (next_param == (tree)0 && TREE_VALUE (param) != void_type_node)
2433 cum->gp_reg_found = 1;
2434 }
2435
2436 /* Determine if the function is returning a structure, if so,
2437 advance by one argument. */
2438
2439 if (fntype
2440 && (TREE_CODE (fntype) == FUNCTION_TYPE || TREE_CODE (fntype) == METHOD_TYPE)
2441 && TREE_TYPE (fntype) != 0)
2442 {
2443 tree ret_type = TREE_TYPE (fntype);
2444 enum tree_code ret_code = TREE_CODE (ret_type);
2445
2446 if (ret_code == RECORD_TYPE || ret_code == UNION_TYPE)
2447 {
2448 cum->gp_reg_found = 1;
2449 cum->arg_number = 1;
2450 cum->arg_words = 1;
2451 }
2452 }
2453 }
2454
2455 /* Advance the argument to the next argument position. */
2456
2457 void
2458 function_arg_advance (cum, mode, type, named)
2459 CUMULATIVE_ARGS *cum; /* current arg information */
2460 enum machine_mode mode; /* current arg mode */
2461 tree type; /* type of the argument or 0 if lib support */
2462 int named; /* whether or not the argument was named */
2463 {
2464 if (TARGET_DEBUG_E_MODE)
2465 fprintf (stderr,
2466 "function_adv( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, 0x%.8x, %d )\n",
2467 cum->gp_reg_found, cum->arg_number, cum->arg_words, GET_MODE_NAME (mode),
2468 type, named);
2469
2470 cum->arg_number++;
2471 switch (mode)
2472 {
2473 default:
2474 error ("Illegal mode given to function_arg_advance");
2475 break;
2476
2477 case VOIDmode:
2478 break;
2479
2480 case BLKmode:
2481 cum->gp_reg_found = 1;
2482 cum->arg_words += (int_size_in_bytes (type) + 3) / 4;
2483 break;
2484
2485 case SFmode:
2486 cum->arg_words++;
2487 break;
2488
2489 case DFmode:
2490 cum->arg_words += 2;
2491 break;
2492
2493 case DImode:
2494 cum->gp_reg_found = 1;
2495 cum->arg_words += 2;
2496 break;
2497
2498 case QImode:
2499 case HImode:
2500 case SImode:
2501 cum->gp_reg_found = 1;
2502 cum->arg_words++;
2503 break;
2504 }
2505 }
2506
2507 /* Return a RTL expression containing the register for the given mode,
2508 or 0 if the argument is too be passed on the stack. */
2509
2510 struct rtx_def *
2511 function_arg (cum, mode, type, named)
2512 CUMULATIVE_ARGS *cum; /* current arg information */
2513 enum machine_mode mode; /* current arg mode */
2514 tree type; /* type of the argument or 0 if lib support */
2515 int named; /* != 0 for normal args, == 0 for ... args */
2516 {
2517 int regbase = -1;
2518 int bias = 0;
2519
2520 if (TARGET_DEBUG_E_MODE)
2521 fprintf (stderr,
2522 "function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, 0x%.8x, %d ) = ",
2523 cum->gp_reg_found, cum->arg_number, cum->arg_words, GET_MODE_NAME (mode),
2524 type, named);
2525
2526 switch (mode)
2527 {
2528 default:
2529 error ("Illegal mode given to function_arg");
2530 break;
2531
2532 case SFmode:
2533 if (cum->gp_reg_found || cum->arg_number >= 2)
2534 regbase = GP_ARG_FIRST;
2535 else {
2536 regbase = (TARGET_SOFT_FLOAT) ? GP_ARG_FIRST : FP_ARG_FIRST;
2537 if (cum->arg_words == 1) /* first arg was float */
2538 bias = 1; /* use correct reg */
2539 }
2540
2541 break;
2542
2543 case DFmode:
2544 cum->arg_words += (cum->arg_words & 1);
2545 regbase = (cum->gp_reg_found || TARGET_SOFT_FLOAT)
2546 ? GP_ARG_FIRST
2547 : FP_ARG_FIRST;
2548 break;
2549
2550 case VOIDmode:
2551 case BLKmode:
2552 case QImode:
2553 case HImode:
2554 case SImode:
2555 regbase = GP_ARG_FIRST;
2556 break;
2557
2558 case DImode:
2559 cum->arg_words += (cum->arg_words & 1);
2560 regbase = GP_ARG_FIRST;
2561 }
2562
2563 if (cum->arg_words >= MAX_ARGS_IN_REGISTERS)
2564 {
2565 if (TARGET_DEBUG_E_MODE)
2566 fprintf (stderr, "<stack>\n");
2567
2568 return 0;
2569 }
2570
2571 if (regbase == -1)
2572 abort ();
2573
2574 if (TARGET_DEBUG_E_MODE)
2575 fprintf (stderr, "%s\n", reg_names[regbase + cum->arg_words + bias]);
2576
2577 return gen_rtx (REG, mode, regbase + cum->arg_words + bias);
2578 }
2579
2580
2581 int
2582 function_arg_partial_nregs (cum, mode, type, named)
2583 CUMULATIVE_ARGS *cum; /* current arg information */
2584 enum machine_mode mode; /* current arg mode */
2585 tree type; /* type of the argument or 0 if lib support */
2586 int named; /* != 0 for normal args, == 0 for ... args */
2587 {
2588 if (mode == BLKmode && cum->arg_words < MAX_ARGS_IN_REGISTERS)
2589 {
2590 int words = (int_size_in_bytes (type) + 3) / 4;
2591
2592 if (words + cum->arg_words < MAX_ARGS_IN_REGISTERS)
2593 return 0; /* structure fits in registers */
2594
2595 if (TARGET_DEBUG_E_MODE)
2596 fprintf (stderr, "function_arg_partial_nregs = %d\n",
2597 MAX_ARGS_IN_REGISTERS - cum->arg_words);
2598
2599 return MAX_ARGS_IN_REGISTERS - cum->arg_words;
2600 }
2601
2602 else if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS-1)
2603 {
2604 if (TARGET_DEBUG_E_MODE)
2605 fprintf (stderr, "function_arg_partial_nregs = 1\n");
2606
2607 return 1;
2608 }
2609
2610 return 0;
2611 }
2612
2613 \f
2614 /* Print the options used in the assembly file. */
2615
2616 static struct {char *name; int value;} target_switches []
2617 = TARGET_SWITCHES;
2618
2619 void
2620 print_options (out)
2621 FILE *out;
2622 {
2623 int line_len;
2624 int len;
2625 int j;
2626 char **p;
2627 int mask = TARGET_DEFAULT;
2628
2629 /* Allow assembly language comparisons with -mdebug eliminating the
2630 compiler version number and switch lists. */
2631
2632 if (TARGET_DEBUG_MODE)
2633 return;
2634
2635 fprintf (out, "\n # %s %s", language_string, version_string);
2636 #ifdef TARGET_VERSION_INTERNAL
2637 TARGET_VERSION_INTERNAL (out);
2638 #endif
2639 #ifdef __GNUC__
2640 fprintf (out, " compiled by GNU C\n\n");
2641 #else
2642 fprintf (out, " compiled by CC\n\n");
2643 #endif
2644
2645 fprintf (out, " # Cc1 defaults:");
2646 line_len = 32767;
2647 for (j = 0; j < sizeof target_switches / sizeof target_switches[0]; j++)
2648 {
2649 if (target_switches[j].name[0] != '\0'
2650 && target_switches[j].value > 0
2651 && (target_switches[j].value & mask) == target_switches[j].value)
2652 {
2653 mask &= ~ target_switches[j].value;
2654 len = strlen (target_switches[j].name) + 1;
2655 if (len + line_len > 79)
2656 {
2657 line_len = 2;
2658 fputs ("\n #", out);
2659 }
2660 fprintf (out, " -m%s", target_switches[j].name);
2661 line_len += len;
2662 }
2663 }
2664
2665 fprintf (out, "\n\n # Cc1 arguments (-G value = %d, Cpu = %s, ISA = %d):",
2666 mips_section_threshold, mips_cpu_string, mips_isa);
2667
2668 line_len = 32767;
2669 for (p = &save_argv[1]; *p != (char *)0; p++)
2670 {
2671 char *arg = *p;
2672 if (*arg == '-')
2673 {
2674 len = strlen (arg) + 1;
2675 if (len + line_len > 79)
2676 {
2677 line_len = 2;
2678 fputs ("\n #", out);
2679 }
2680 fprintf (out, " %s", *p);
2681 line_len += len;
2682 }
2683 }
2684
2685 fputs ("\n\n", out);
2686 }
2687
2688 \f
2689 /* Abort after printing out a specific insn. */
2690
2691 void
2692 abort_with_insn (insn, reason)
2693 rtx insn;
2694 char *reason;
2695 {
2696 error (reason);
2697 debug_rtx (insn);
2698 abort ();
2699 }
2700
2701 /* Write a message to stderr (for use in macros expanded in files that do not
2702 include stdio.h). */
2703
2704 void
2705 trace (s, s1, s2)
2706 char *s, *s1, *s2;
2707 {
2708 fprintf (stderr, s, s1, s2);
2709 }
2710
2711 \f
2712 #ifdef SIGINFO
2713
2714 #include <sys/wait.h>
2715
2716 static void
2717 siginfo (signo)
2718 int signo;
2719 {
2720 char select_pgrp[15];
2721 char *argv[4];
2722 pid_t pid;
2723 pid_t pgrp;
2724 int status;
2725
2726 fprintf (stderr, "compiling '%s' in '%s'\n",
2727 (current_function_name != (char *)0) ? current_function_name : "<toplevel>",
2728 (current_function_file != (char *)0) ? current_function_file : "<no file>");
2729
2730 pgrp = getpgrp ();
2731 if (pgrp != -1)
2732 sprintf (select_pgrp, "-g%d", pgrp);
2733 else
2734 strcpy (select_pgrp, "-a");
2735
2736 /* Spawn a ps to tell about current memory usage, etc. */
2737 argv[0] = "ps";
2738 argv[1] = "-ouser,pid,pri,nice,usertime,systime,pcpu,cp,inblock,oublock,vsize,rss,pmem,ucomm";
2739 argv[2] = select_pgrp;
2740 argv[3] = (char *)0;
2741
2742 pid = vfork ();
2743 if (pid == 0) /* child context */
2744 {
2745 execv ("/usr/bin/ps", argv);
2746 execv ("/usr/sbin/ps", argv);
2747 execvp ("ps", argv);
2748 perror ("ps");
2749 _exit (1);
2750 }
2751
2752 else if (pid > 0) /* parent context */
2753 {
2754 void (*sigint)(int) = signal (SIGINT, SIG_IGN);
2755 void (*sigquit)(int) = signal (SIGQUIT, SIG_IGN);
2756
2757 (void) waitpid (pid, &status, 0);
2758
2759 (void) signal (SIGINT, sigint);
2760 (void) signal (SIGQUIT, sigquit);
2761 }
2762 }
2763 #endif /* SIGINFO */
2764
2765 \f
2766 /* Set up the threshold for data to go into the small data area, instead
2767 of the normal data area, and detect any conflicts in the switches. */
2768
2769 void
2770 override_options ()
2771 {
2772 register int i, start;
2773 register int regno;
2774 register enum machine_mode mode;
2775
2776 if (g_switch_set)
2777 mips_section_threshold = g_switch_value;
2778
2779 else
2780 mips_section_threshold = (TARGET_MIPS_AS) ? 8 : 0;
2781
2782 /* Identify the processor type */
2783 if (mips_cpu_string == (char *)0
2784 || !strcmp (mips_cpu_string, "default")
2785 || !strcmp (mips_cpu_string, "DEFAULT"))
2786 {
2787 mips_cpu_string = "default";
2788 mips_cpu = PROCESSOR_DEFAULT;
2789 }
2790
2791 else
2792 {
2793 char *p = mips_cpu_string;
2794
2795 if (*p == 'r' || *p == 'R')
2796 p++;
2797
2798 /* Since there is no difference between a R2000 and R3000 in
2799 terms of the scheduler, we collapse them into just an R3000. */
2800
2801 mips_cpu = PROCESSOR_DEFAULT;
2802 switch (*p)
2803 {
2804 case '2':
2805 if (!strcmp (p, "2000") || !strcmp (p, "2k") || !strcmp (p, "2K"))
2806 mips_cpu = PROCESSOR_R3000;
2807 break;
2808
2809 case '3':
2810 if (!strcmp (p, "3000") || !strcmp (p, "3k") || !strcmp (p, "3K"))
2811 mips_cpu = PROCESSOR_R3000;
2812 break;
2813
2814 case '4':
2815 if (!strcmp (p, "4000") || !strcmp (p, "4k") || !strcmp (p, "4K"))
2816 mips_cpu = PROCESSOR_R4000;
2817 break;
2818
2819 case '6':
2820 if (!strcmp (p, "6000") || !strcmp (p, "6k") || !strcmp (p, "6K"))
2821 mips_cpu = PROCESSOR_R6000;
2822 break;
2823 }
2824
2825 if (mips_cpu == PROCESSOR_DEFAULT)
2826 {
2827 error ("bad value (%s) for -mcpu= switch", mips_cpu_string);
2828 mips_cpu_string = "default";
2829 }
2830 }
2831
2832 /* Now get the architectural level. */
2833 if (mips_isa_string == (char *)0)
2834 mips_isa = 1;
2835
2836 else if (isdigit (*mips_isa_string))
2837 mips_isa = atoi (mips_isa_string);
2838
2839 else
2840 {
2841 error ("bad value (%s) for -mips switch", mips_isa_string);
2842 mips_isa = 1;
2843 }
2844
2845 if (mips_isa < 0 || mips_isa > 3)
2846 error ("-mips%d not supported", mips_isa);
2847
2848 else if (mips_isa > 1
2849 && (mips_cpu == PROCESSOR_DEFAULT || mips_cpu == PROCESSOR_R3000))
2850 error ("-mcpu=%s does not support -mips%d", mips_cpu_string, mips_isa);
2851
2852 else if (mips_cpu == PROCESSOR_R6000 && mips_isa > 2)
2853 error ("-mcpu=%s does not support -mips%d", mips_cpu_string, mips_isa);
2854
2855 /* make sure sizes of ints/longs/etc. are ok */
2856 if (mips_isa < 3)
2857 {
2858 if (TARGET_INT64)
2859 fatal ("Only the r4000 can support 64 bit ints");
2860
2861 else if (TARGET_LONG64)
2862 fatal ("Only the r4000 can support 64 bit longs");
2863
2864 else if (TARGET_LLONG128)
2865 fatal ("Only the r4000 can support 128 bit long longs");
2866
2867 else if (TARGET_FLOAT64)
2868 fatal ("Only the r4000 can support 64 bit fp registers");
2869 }
2870 else if (TARGET_INT64 || TARGET_LONG64 || TARGET_LLONG128 || TARGET_FLOAT64)
2871 warning ("r4000 64/128 bit types not yet supported");
2872
2873 /* Tell halfpic.c that we have half-pic code if we do. */
2874 if (TARGET_HALF_PIC)
2875 HALF_PIC_INIT ();
2876
2877 /* -mrnames says to use the MIPS software convention for register
2878 names instead of the hardware names (ie, a0 instead of $4).
2879 We do this by switching the names in mips_reg_names, which the
2880 reg_names points into via the REGISTER_NAMES macro. */
2881
2882 if (TARGET_NAME_REGS)
2883 {
2884 if (TARGET_GAS)
2885 {
2886 target_flags &= ~ MASK_NAME_REGS;
2887 error ("Gas does not support the MIPS software register name convention.");
2888 }
2889 else
2890 bcopy ((char *) mips_sw_reg_names, (char *) mips_reg_names, sizeof (mips_reg_names));
2891 }
2892
2893 /* If this is OSF/1, set up a SIGINFO handler so we can see what function
2894 is currently being compiled. */
2895 #ifdef SIGINFO
2896 if (getenv ("GCC_SIGINFO") != (char *)0)
2897 {
2898 struct sigaction action;
2899 action.sa_handler = siginfo;
2900 action.sa_mask = 0;
2901 action.sa_flags = SA_RESTART;
2902 sigaction (SIGINFO, &action, (struct sigaction *)0);
2903 }
2904 #endif
2905
2906 #ifdef _IOLBF
2907 /* If -mstats and -quiet, make stderr line buffered. */
2908 if (quiet_flag && TARGET_STATS)
2909 {
2910 #if defined (MIPS_BSD43) || defined (MIPS_NEWS)
2911 setlinebuf (stderr);
2912 #else
2913 setvbuf (stderr, (char *)0, _IOLBF, BUFSIZ);
2914 #endif
2915 #endif
2916 }
2917
2918 /* Set up the classification arrays now. */
2919 mips_rtx_classify[(int)PLUS] = CLASS_ADD_OP;
2920 mips_rtx_classify[(int)MINUS] = CLASS_ADD_OP;
2921 mips_rtx_classify[(int)DIV] = CLASS_DIVMOD_OP;
2922 mips_rtx_classify[(int)MOD] = CLASS_DIVMOD_OP;
2923 mips_rtx_classify[(int)UDIV] = CLASS_DIVMOD_OP | CLASS_UNSIGNED_OP;
2924 mips_rtx_classify[(int)UMOD] = CLASS_DIVMOD_OP | CLASS_UNSIGNED_OP;
2925 mips_rtx_classify[(int)EQ] = CLASS_CMP_OP | CLASS_EQUALITY_OP | CLASS_FCMP_OP;
2926 mips_rtx_classify[(int)NE] = CLASS_CMP_OP | CLASS_EQUALITY_OP | CLASS_FCMP_OP;
2927 mips_rtx_classify[(int)GT] = CLASS_CMP_OP | CLASS_FCMP_OP;
2928 mips_rtx_classify[(int)GE] = CLASS_CMP_OP | CLASS_FCMP_OP;
2929 mips_rtx_classify[(int)LT] = CLASS_CMP_OP | CLASS_FCMP_OP;
2930 mips_rtx_classify[(int)LE] = CLASS_CMP_OP | CLASS_FCMP_OP;
2931 mips_rtx_classify[(int)GTU] = CLASS_CMP_OP | CLASS_UNSIGNED_OP;
2932 mips_rtx_classify[(int)GEU] = CLASS_CMP_OP | CLASS_UNSIGNED_OP;
2933 mips_rtx_classify[(int)LTU] = CLASS_CMP_OP | CLASS_UNSIGNED_OP;
2934 mips_rtx_classify[(int)LEU] = CLASS_CMP_OP | CLASS_UNSIGNED_OP;
2935
2936 mips_print_operand_punct['?'] = TRUE;
2937 mips_print_operand_punct['#'] = TRUE;
2938 mips_print_operand_punct['&'] = TRUE;
2939 mips_print_operand_punct['!'] = TRUE;
2940 mips_print_operand_punct['*'] = TRUE;
2941 mips_print_operand_punct['@'] = TRUE;
2942 mips_print_operand_punct['.'] = TRUE;
2943 mips_print_operand_punct['('] = TRUE;
2944 mips_print_operand_punct[')'] = TRUE;
2945 mips_print_operand_punct['['] = TRUE;
2946 mips_print_operand_punct[']'] = TRUE;
2947 mips_print_operand_punct['<'] = TRUE;
2948 mips_print_operand_punct['>'] = TRUE;
2949 mips_print_operand_punct['{'] = TRUE;
2950 mips_print_operand_punct['}'] = TRUE;
2951
2952 mips_char_to_class['d'] = GR_REGS;
2953 mips_char_to_class['f'] = ((TARGET_HARD_FLOAT) ? FP_REGS : NO_REGS);
2954 mips_char_to_class['h'] = HI_REG;
2955 mips_char_to_class['l'] = LO_REG;
2956 mips_char_to_class['x'] = MD_REGS;
2957 mips_char_to_class['y'] = GR_REGS;
2958 mips_char_to_class['z'] = ST_REGS;
2959
2960 /* Set up array to map GCC register number to debug register number.
2961 Ignore the special purpose register numbers. */
2962
2963 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2964 mips_dbx_regno[i] = -1;
2965
2966 start = GP_DBX_FIRST - GP_REG_FIRST;
2967 for (i = GP_REG_FIRST; i <= GP_REG_LAST; i++)
2968 mips_dbx_regno[i] = i + start;
2969
2970 start = FP_DBX_FIRST - FP_REG_FIRST;
2971 for (i = FP_REG_FIRST; i <= FP_REG_LAST; i++)
2972 mips_dbx_regno[i] = i + start;
2973
2974 /* Set up array giving whether a given register can hold a given mode.
2975 At present, restrict ints from being in FP registers, because reload
2976 is a little enthusiastic about storing extra values in FP registers,
2977 and this is not good for things like OS kernels. Also, due to the
2978 mandatory delay, it is as fast to load from cached memory as to move
2979 from the FP register. */
2980
2981 for (mode = VOIDmode;
2982 mode != MAX_MACHINE_MODE;
2983 mode = (enum machine_mode)((int)mode + 1))
2984 {
2985 register int size = GET_MODE_SIZE (mode);
2986 register enum mode_class class = GET_MODE_CLASS (mode);
2987
2988 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
2989 {
2990 register int temp;
2991
2992 if (mode == CC_FPmode || mode == CC_REV_FPmode)
2993 temp = (regno == FPSW_REGNUM);
2994
2995 else if (GP_REG_P (regno))
2996 temp = ((regno & 1) == 0 || (size <= UNITS_PER_WORD));
2997
2998 else if (FP_REG_P (regno))
2999 temp = ((TARGET_FLOAT64 || ((regno & 1) == 0))
3000 && (class == MODE_FLOAT
3001 || class == MODE_COMPLEX_FLOAT
3002 || (TARGET_DEBUG_H_MODE && class == MODE_INT)));
3003
3004 else if (MD_REG_P (regno))
3005 temp = (mode == SImode || (regno == MD_REG_FIRST && mode == DImode));
3006
3007 else
3008 temp = FALSE;
3009
3010 mips_hard_regno_mode_ok[(int)mode][regno] = temp;
3011 }
3012 }
3013 }
3014
3015 \f
3016 /*
3017 * The MIPS debug format wants all automatic variables and arguments
3018 * to be in terms of the virtual frame pointer (stack pointer before
3019 * any adjustment in the function), while the MIPS 3.0 linker wants
3020 * the frame pointer to be the stack pointer after the initial
3021 * adjustment. So, we do the adjustment here. The arg pointer (which
3022 * is eliminated) points to the virtual frame pointer, while the frame
3023 * pointer (which may be eliminated) points to the stack pointer after
3024 * the initial adjustments.
3025 */
3026
3027 int
3028 mips_debugger_offset (addr, offset)
3029 rtx addr;
3030 int offset;
3031 {
3032 rtx offset2 = const0_rtx;
3033 rtx reg = eliminate_constant_term (addr, &offset2);
3034
3035 if (!offset)
3036 offset = INTVAL (offset2);
3037
3038 if (reg == stack_pointer_rtx || reg == frame_pointer_rtx)
3039 {
3040 int frame_size = (!current_frame_info.initialized)
3041 ? compute_frame_size (get_frame_size ())
3042 : current_frame_info.total_size;
3043
3044 offset = offset - frame_size;
3045 }
3046 else if (reg != arg_pointer_rtx)
3047 abort_with_insn (addr, "mips_debugger_offset called with non stack/frame/arg pointer.");
3048
3049 return offset;
3050 }
3051
3052 \f
3053 /* A C compound statement to output to stdio stream STREAM the
3054 assembler syntax for an instruction operand X. X is an RTL
3055 expression.
3056
3057 CODE is a value that can be used to specify one of several ways
3058 of printing the operand. It is used when identical operands
3059 must be printed differently depending on the context. CODE
3060 comes from the `%' specification that was used to request
3061 printing of the operand. If the specification was just `%DIGIT'
3062 then CODE is 0; if the specification was `%LTR DIGIT' then CODE
3063 is the ASCII code for LTR.
3064
3065 If X is a register, this macro should print the register's name.
3066 The names can be found in an array `reg_names' whose type is
3067 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
3068
3069 When the machine description has a specification `%PUNCT' (a `%'
3070 followed by a punctuation character), this macro is called with
3071 a null pointer for X and the punctuation character for CODE.
3072
3073 The MIPS specific codes are:
3074
3075 'X' X is CONST_INT, prints 32 bits in hexadecimal format = "0x%08x",
3076 'x' X is CONST_INT, prints 16 bits in hexadecimal format = "0x%04x",
3077 'd' output integer constant in decimal,
3078 'z' if the operand is 0, use $0 instead of normal operand.
3079 'D' print second register of double-word register operand.
3080 'L' print low-order register of double-word register operand.
3081 'M' print high-order register of double-word register operand.
3082 'C' print part of opcode for a branch condition.
3083 'N' print part of opcode for a branch condition, inverted.
3084 '(' Turn on .set noreorder
3085 ')' Turn on .set reorder
3086 '[' Turn on .set noat
3087 ']' Turn on .set at
3088 '<' Turn on .set nomacro
3089 '>' Turn on .set macro
3090 '{' Turn on .set volatile (not GAS)
3091 '}' Turn on .set novolatile (not GAS)
3092 '&' Turn on .set noreorder if filling delay slots
3093 '*' Turn on both .set noreorder and .set nomacro if filling delay slots
3094 '!' Turn on .set nomacro if filling delay slots
3095 '#' Print nop if in a .set noreorder section.
3096 '?' Print 'l' if we are to use a branch likely instead of normal branch.
3097 '@' Print the name of the assembler temporary register (at or $1).
3098 '.' Print the name of the register with a hard-wired zero (zero or $0). */
3099
3100 void
3101 print_operand (file, op, letter)
3102 FILE *file; /* file to write to */
3103 rtx op; /* operand to print */
3104 int letter; /* %<letter> or 0 */
3105 {
3106 register enum rtx_code code;
3107
3108 if (PRINT_OPERAND_PUNCT_VALID_P (letter))
3109 {
3110 switch (letter)
3111 {
3112 default:
3113 error ("PRINT_OPERAND: Unknown punctuation '%c'", letter);
3114 break;
3115
3116 case '?':
3117 if (mips_branch_likely)
3118 putc ('l', file);
3119 break;
3120
3121 case '@':
3122 fputs (reg_names [GP_REG_FIRST + 1], file);
3123 break;
3124
3125 case '.':
3126 fputs (reg_names [GP_REG_FIRST + 0], file);
3127 break;
3128
3129 case '&':
3130 if (final_sequence != 0 && set_noreorder++ == 0)
3131 fputs (".set\tnoreorder\n\t", file);
3132 break;
3133
3134 case '*':
3135 if (final_sequence != 0)
3136 {
3137 if (set_noreorder++ == 0)
3138 fputs (".set\tnoreorder\n\t", file);
3139
3140 if (set_nomacro++ == 0)
3141 fputs (".set\tnomacro\n\t", file);
3142 }
3143 break;
3144
3145 case '!':
3146 if (final_sequence != 0 && set_nomacro++ == 0)
3147 fputs ("\n\t.set\tnomacro", file);
3148 break;
3149
3150 case '#':
3151 if (set_noreorder != 0)
3152 fputs ("\n\tnop", file);
3153
3154 else if (TARGET_GAS || TARGET_STATS)
3155 fputs ("\n\t#nop", file);
3156
3157 break;
3158
3159 case '(':
3160 if (set_noreorder++ == 0)
3161 fputs (".set\tnoreorder\n\t", file);
3162 break;
3163
3164 case ')':
3165 if (set_noreorder == 0)
3166 error ("internal error: %%) found without a %%( in assembler pattern");
3167
3168 else if (--set_noreorder == 0)
3169 fputs ("\n\t.set\treorder", file);
3170
3171 break;
3172
3173 case '[':
3174 if (set_noat++ == 0)
3175 fputs (".set\tnoat\n\t", file);
3176 break;
3177
3178 case ']':
3179 if (set_noat == 0)
3180 error ("internal error: %%] found without a %%[ in assembler pattern");
3181
3182 else if (--set_noat == 0)
3183 fputs ("\n\t.set\tat", file);
3184
3185 break;
3186
3187 case '<':
3188 if (set_nomacro++ == 0)
3189 fputs (".set\tnomacro\n\t", file);
3190 break;
3191
3192 case '>':
3193 if (set_nomacro == 0)
3194 error ("internal error: %%> found without a %%< in assembler pattern");
3195
3196 else if (--set_nomacro == 0)
3197 fputs ("\n\t.set\tmacro", file);
3198
3199 break;
3200
3201 case '{':
3202 if (set_volatile++ == 0)
3203 fprintf (file, "%s.set\tvolatile\n\t", (TARGET_MIPS_AS) ? "" : "#");
3204 break;
3205
3206 case '}':
3207 if (set_volatile == 0)
3208 error ("internal error: %%} found without a %%{ in assembler pattern");
3209
3210 else if (--set_volatile == 0)
3211 fprintf (file, "\n\t%s.set\tnovolatile", (TARGET_MIPS_AS) ? "" : "#");
3212
3213 break;
3214 }
3215 return;
3216 }
3217
3218 if (! op)
3219 {
3220 error ("PRINT_OPERAND null pointer");
3221 return;
3222 }
3223
3224 code = GET_CODE (op);
3225 if (letter == 'C')
3226 switch (code)
3227 {
3228 case EQ: fputs ("eq", file); break;
3229 case NE: fputs ("ne", file); break;
3230 case GT: fputs ("gt", file); break;
3231 case GE: fputs ("ge", file); break;
3232 case LT: fputs ("lt", file); break;
3233 case LE: fputs ("le", file); break;
3234 case GTU: fputs ("gtu", file); break;
3235 case GEU: fputs ("geu", file); break;
3236 case LTU: fputs ("ltu", file); break;
3237 case LEU: fputs ("leu", file); break;
3238
3239 default:
3240 abort_with_insn (op, "PRINT_OPERAND, illegal insn for %%C");
3241 }
3242
3243 else if (letter == 'N')
3244 switch (code)
3245 {
3246 case EQ: fputs ("ne", file); break;
3247 case NE: fputs ("eq", file); break;
3248 case GT: fputs ("le", file); break;
3249 case GE: fputs ("lt", file); break;
3250 case LT: fputs ("ge", file); break;
3251 case LE: fputs ("gt", file); break;
3252 case GTU: fputs ("leu", file); break;
3253 case GEU: fputs ("ltu", file); break;
3254 case LTU: fputs ("geu", file); break;
3255 case LEU: fputs ("gtu", file); break;
3256
3257 default:
3258 abort_with_insn (op, "PRINT_OPERAND, illegal insn for %%N");
3259 }
3260
3261 else if (code == REG)
3262 {
3263 register int regnum = REGNO (op);
3264
3265 if (letter == 'M')
3266 regnum += MOST_SIGNIFICANT_WORD;
3267
3268 else if (letter == 'L')
3269 regnum += LEAST_SIGNIFICANT_WORD;
3270
3271 else if (letter == 'D')
3272 regnum++;
3273
3274 fprintf (file, "%s", reg_names[regnum]);
3275 }
3276
3277 else if (code == MEM)
3278 output_address (XEXP (op, 0));
3279
3280 else if (code == CONST_DOUBLE)
3281 {
3282 #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
3283 union { double d; int i[2]; } u;
3284 u.i[0] = CONST_DOUBLE_LOW (op);
3285 u.i[1] = CONST_DOUBLE_HIGH (op);
3286 if (GET_MODE (op) == SFmode)
3287 {
3288 float f;
3289 f = u.d;
3290 u.d = f;
3291 }
3292 fprintf (file, "%.20e", u.d);
3293 #else
3294 fatal ("CONST_DOUBLE found in cross compilation");
3295 #endif
3296 }
3297
3298 else if ((letter == 'x') && (GET_CODE(op) == CONST_INT))
3299 fprintf (file, "0x%04x", 0xffff & (INTVAL(op)));
3300
3301 else if ((letter == 'X') && (GET_CODE(op) == CONST_INT))
3302 fprintf (file, "0x%08x", INTVAL(op));
3303
3304 else if ((letter == 'd') && (GET_CODE(op) == CONST_INT))
3305 fprintf (file, "%d", (INTVAL(op)));
3306
3307 else if (letter == 'z'
3308 && (GET_CODE (op) == CONST_INT)
3309 && INTVAL (op) == 0)
3310 fputs (reg_names[GP_REG_FIRST], file);
3311
3312 else if (letter == 'd' || letter == 'x' || letter == 'X')
3313 fatal ("PRINT_OPERAND: letter %c was found & insn was not CONST_INT", letter);
3314
3315 else
3316 output_addr_const (file, op);
3317 }
3318
3319 \f
3320 /* A C compound statement to output to stdio stream STREAM the
3321 assembler syntax for an instruction operand that is a memory
3322 reference whose address is ADDR. ADDR is an RTL expression.
3323
3324 On some machines, the syntax for a symbolic address depends on
3325 the section that the address refers to. On these machines,
3326 define the macro `ENCODE_SECTION_INFO' to store the information
3327 into the `symbol_ref', and then check for it here. */
3328
3329 void
3330 print_operand_address (file, addr)
3331 FILE *file;
3332 rtx addr;
3333 {
3334 if (!addr)
3335 error ("PRINT_OPERAND_ADDRESS, null pointer");
3336
3337 else
3338 switch (GET_CODE (addr))
3339 {
3340 default:
3341 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, illegal insn #1");
3342 break;
3343
3344 case REG:
3345 if (REGNO (addr) == ARG_POINTER_REGNUM)
3346 abort_with_insn (addr, "Arg pointer not eliminated.");
3347
3348 fprintf (file, "0(%s)", reg_names [REGNO (addr)]);
3349 break;
3350
3351 case PLUS:
3352 {
3353 register rtx reg = (rtx)0;
3354 register rtx offset = (rtx)0;
3355 register rtx arg0 = XEXP (addr, 0);
3356 register rtx arg1 = XEXP (addr, 1);
3357
3358 if (GET_CODE (arg0) == REG)
3359 {
3360 reg = arg0;
3361 offset = arg1;
3362 if (GET_CODE (offset) == REG)
3363 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, 2 regs");
3364 }
3365 else if (GET_CODE (arg1) == REG)
3366 {
3367 reg = arg1;
3368 offset = arg0;
3369 }
3370 else if (CONSTANT_P (arg0) && CONSTANT_P (arg1))
3371 {
3372 output_addr_const (file, addr);
3373 break;
3374 }
3375 else
3376 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, no regs");
3377
3378 if (!CONSTANT_P (offset))
3379 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, illegal insn #2");
3380
3381 if (REGNO (reg) == ARG_POINTER_REGNUM)
3382 abort_with_insn (addr, "Arg pointer not eliminated.");
3383
3384 output_addr_const (file, offset);
3385 fprintf (file, "(%s)", reg_names [REGNO (reg)]);
3386 }
3387 break;
3388
3389 case LABEL_REF:
3390 case SYMBOL_REF:
3391 case CONST_INT:
3392 case CONST:
3393 output_addr_const (file, addr);
3394 break;
3395 }
3396 }
3397
3398 \f
3399 /* If optimizing for the global pointer, keep track of all of
3400 the externs, so that at the end of the file, we can emit
3401 the appropriate .extern declaration for them, before writing
3402 out the text section. We assume that all names passed to
3403 us are in the permanent obstack, so that they will be valid
3404 at the end of the compilation.
3405
3406 If we have -G 0, or the extern size is unknown, don't bother
3407 emitting the .externs. */
3408
3409 int
3410 mips_output_external (file, decl, name)
3411 FILE *file;
3412 tree decl;
3413 char *name;
3414 {
3415 register struct extern_list *p;
3416 int len;
3417
3418 if (TARGET_GP_OPT
3419 && mips_section_threshold != 0
3420 && ((TREE_CODE (decl)) != FUNCTION_DECL)
3421 && ((len = int_size_in_bytes (TREE_TYPE (decl))) > 0))
3422 {
3423 p = (struct extern_list *)permalloc ((long) sizeof (struct extern_list));
3424 p->next = extern_head;
3425 p->name = name;
3426 p->size = len;
3427 extern_head = p;
3428 }
3429 return 0;
3430 }
3431
3432 \f
3433 /* Compute a string to use as a temporary file name. */
3434
3435 static FILE *
3436 make_temp_file ()
3437 {
3438 FILE *stream;
3439 char *base = getenv ("TMPDIR");
3440 int len;
3441
3442 if (base == (char *)0)
3443 {
3444 #ifdef P_tmpdir
3445 if (access (P_tmpdir, R_OK | W_OK) == 0)
3446 base = P_tmpdir;
3447 else
3448 #endif
3449 if (access ("/usr/tmp", R_OK | W_OK) == 0)
3450 base = "/usr/tmp/";
3451 else
3452 base = "/tmp/";
3453 }
3454
3455 len = strlen (base);
3456 temp_filename = (char *) alloca (len + sizeof("/ccXXXXXX"));
3457 strcpy (temp_filename, base);
3458 if (len > 0 && temp_filename[len-1] != '/')
3459 temp_filename[len++] = '/';
3460
3461 strcpy (temp_filename + len, "ccXXXXXX");
3462 mktemp (temp_filename);
3463
3464 stream = fopen (temp_filename, "w+");
3465 if (!stream)
3466 pfatal_with_name (temp_filename);
3467
3468 unlink (temp_filename);
3469 return stream;
3470 }
3471
3472 \f
3473 /* Emit a new filename to a stream. If this is MIPS ECOFF, watch out
3474 for .file's that start within a function. If we are smuggling stabs, try to
3475 put out a MIPS ECOFF file and a stab. */
3476
3477 void
3478 mips_output_filename (stream, name)
3479 FILE *stream;
3480 char *name;
3481 {
3482 static int first_time = TRUE;
3483 char ltext_label_name[100];
3484
3485 if (first_time)
3486 {
3487 first_time = FALSE;
3488 SET_FILE_NUMBER ();
3489 current_function_file = name;
3490 fprintf (stream, "\t.file\t%d \"%s\"\n", num_source_filenames, name);
3491 if (!TARGET_GAS && write_symbols == DBX_DEBUG)
3492 fprintf (stream, "\t#@stabs\n");
3493 }
3494
3495 else if (!TARGET_GAS && write_symbols == DBX_DEBUG)
3496 {
3497 ASM_GENERATE_INTERNAL_LABEL (ltext_label_name, "Ltext", 0);
3498 fprintf (stream, "%s \"%s\",%d,0,0,%s\n", ASM_STABS_OP,
3499 name, N_SOL, &ltext_label_name[1]);
3500 }
3501
3502 else if (name != current_function_file
3503 && strcmp (name, current_function_file) != 0)
3504 {
3505 if (inside_function && !TARGET_GAS)
3506 {
3507 if (!file_in_function_warning)
3508 {
3509 file_in_function_warning = TRUE;
3510 ignore_line_number = TRUE;
3511 warning ("MIPS ECOFF format does not allow changing filenames within functions with #line");
3512 }
3513
3514 fprintf (stream, "\t#.file\t%d \"%s\"\n", num_source_filenames, name);
3515 }
3516
3517 else
3518 {
3519 SET_FILE_NUMBER ();
3520 current_function_file = name;
3521 fprintf (stream, "\t.file\t%d \"%s\"\n", num_source_filenames, name);
3522 }
3523 }
3524 }
3525
3526 \f
3527 /* Emit a linenumber. For encapsulated stabs, we need to put out a stab
3528 as well as a .loc, since it is possible that MIPS ECOFF might not be
3529 able to represent the location for inlines that come from a different
3530 file. */
3531
3532 void
3533 mips_output_lineno (stream, line)
3534 FILE *stream;
3535 int line;
3536 {
3537 if (!TARGET_GAS && write_symbols == DBX_DEBUG)
3538 {
3539 ++sym_lineno;
3540 fprintf (stream, "$LM%d:\n\t%s %d,0,%d,$LM%d\n",
3541 sym_lineno, ASM_STABN_OP, N_SLINE, line, sym_lineno);
3542 }
3543
3544 else
3545 {
3546 fprintf (stream, "\n\t%s.loc\t%d %d\n",
3547 (ignore_line_number) ? "#" : "",
3548 num_source_filenames, line);
3549
3550 LABEL_AFTER_LOC (stream);
3551 }
3552 }
3553
3554 \f
3555 /* If defined, a C statement to be executed just prior to the
3556 output of assembler code for INSN, to modify the extracted
3557 operands so they will be output differently.
3558
3559 Here the argument OPVEC is the vector containing the operands
3560 extracted from INSN, and NOPERANDS is the number of elements of
3561 the vector which contain meaningful data for this insn. The
3562 contents of this vector are what will be used to convert the
3563 insn template into assembler code, so you can change the
3564 assembler output by changing the contents of the vector.
3565
3566 We use it to check if the current insn needs a nop in front of it
3567 because of load delays, and also to update the delay slot
3568 statistics. */
3569
3570 void
3571 final_prescan_insn (insn, opvec, noperands)
3572 rtx insn;
3573 rtx opvec[];
3574 int noperands;
3575 {
3576 if (dslots_number_nops > 0)
3577 {
3578 rtx pattern = PATTERN (insn);
3579 int length = get_attr_length (insn);
3580
3581 /* Do we need to emit a NOP? */
3582 if (length == 0
3583 || (mips_load_reg != (rtx)0 && reg_mentioned_p (mips_load_reg, pattern))
3584 || (mips_load_reg2 != (rtx)0 && reg_mentioned_p (mips_load_reg2, pattern))
3585 || (mips_load_reg3 != (rtx)0 && reg_mentioned_p (mips_load_reg3, pattern))
3586 || (mips_load_reg4 != (rtx)0 && reg_mentioned_p (mips_load_reg4, pattern)))
3587 fputs ((set_noreorder) ? "\tnop\n" : "\t#nop\n", asm_out_file);
3588
3589 else
3590 dslots_load_filled++;
3591
3592 while (--dslots_number_nops > 0)
3593 fputs ((set_noreorder) ? "\tnop\n" : "\t#nop\n", asm_out_file);
3594
3595 mips_load_reg = (rtx)0;
3596 mips_load_reg2 = (rtx)0;
3597 mips_load_reg3 = (rtx)0;
3598 mips_load_reg4 = (rtx)0;
3599
3600 if (set_noreorder && --set_noreorder == 0)
3601 fputs ("\t.set\treorder\n", asm_out_file);
3602 }
3603
3604 if (TARGET_STATS)
3605 {
3606 enum rtx_code code = GET_CODE (insn);
3607 if (code == JUMP_INSN || code == CALL_INSN)
3608 dslots_jump_total++;
3609 }
3610 }
3611
3612 \f
3613 /* Output at beginning of assembler file.
3614 If we are optimizing to use the global pointer, create a temporary
3615 file to hold all of the text stuff, and write it out to the end.
3616 This is needed because the MIPS assembler is evidently one pass,
3617 and if it hasn't seen the relevant .comm/.lcomm/.extern/.sdata
3618 declaration when the code is processed, it generates a two
3619 instruction sequence. */
3620
3621 void
3622 mips_asm_file_start (stream)
3623 FILE *stream;
3624 {
3625 ASM_OUTPUT_SOURCE_FILENAME (stream, main_input_filename);
3626
3627 /* Versions of the MIPS assembler before 2.20 generate errors
3628 if a branch inside of a .set noreorder section jumps to a
3629 label outside of the .set noreorder section. Revision 2.20
3630 just set nobopt silently rather than fixing the bug. */
3631
3632 if (TARGET_MIPS_AS && optimize && flag_delayed_branch)
3633 fprintf (stream, "\t.set\tnobopt\n");
3634
3635 /* Generate the pseudo ops that the Pyramid based System V.4 wants. */
3636 if (TARGET_ABICALLS)
3637 fprintf (stream, "\t.abicalls\n");
3638
3639 if (TARGET_GP_OPT)
3640 {
3641 asm_out_data_file = stream;
3642 asm_out_text_file = make_temp_file ();
3643 }
3644 else
3645 asm_out_data_file = asm_out_text_file = stream;
3646
3647 if (TARGET_NAME_REGS)
3648 fprintf (asm_out_file, "#include <regdef.h>\n");
3649
3650 print_options (stream);
3651 }
3652
3653 \f
3654 /* If we are optimizing the global pointer, emit the text section now
3655 and any small externs which did not have .comm, etc that are
3656 needed. Also, give a warning if the data area is more than 32K and
3657 -pic because 3 instructions are needed to reference the data
3658 pointers. */
3659
3660 void
3661 mips_asm_file_end (file)
3662 FILE *file;
3663 {
3664 char buffer[8192];
3665 tree name_tree;
3666 struct extern_list *p;
3667 int len;
3668
3669 if (HALF_PIC_P ())
3670 HALF_PIC_FINISH (file);
3671
3672 if (TARGET_GP_OPT)
3673 {
3674 if (extern_head)
3675 fputs ("\n", file);
3676
3677 for (p = extern_head; p != 0; p = p->next)
3678 {
3679 name_tree = get_identifier (p->name);
3680
3681 /* Positively ensure only one .extern for any given symbol. */
3682 if (! TREE_ASM_WRITTEN (name_tree))
3683 {
3684 TREE_ASM_WRITTEN (name_tree) = 1;
3685 fputs ("\t.extern\t", file);
3686 assemble_name (file, p->name);
3687 fprintf (file, ", %d\n", p->size);
3688 }
3689 }
3690
3691 fprintf (file, "\n\t.text\n");
3692 rewind (asm_out_text_file);
3693 if (ferror (asm_out_text_file))
3694 fatal_io_error (temp_filename);
3695
3696 while ((len = fread (buffer, 1, sizeof (buffer), asm_out_text_file)) > 0)
3697 if (fwrite (buffer, 1, len, file) != len)
3698 pfatal_with_name (asm_file_name);
3699
3700 if (len < 0)
3701 pfatal_with_name (temp_filename);
3702
3703 if (fclose (asm_out_text_file) != 0)
3704 pfatal_with_name (temp_filename);
3705 }
3706 }
3707
3708 \f
3709 /* Emit either a label, .comm, or .lcomm directive, and mark
3710 that the symbol is used, so that we don't emit an .extern
3711 for it in mips_asm_file_end. */
3712
3713 void
3714 mips_declare_object (stream, name, init_string, final_string, size)
3715 FILE *stream;
3716 char *name;
3717 char *init_string;
3718 char *final_string;
3719 int size;
3720 {
3721 fputs (init_string, stream); /* "", "\t.comm\t", or "\t.lcomm\t" */
3722 assemble_name (stream, name);
3723 fprintf (stream, final_string, size); /* ":\n", ",%u\n", ",%u\n" */
3724
3725 if (TARGET_GP_OPT && mips_section_threshold != 0)
3726 {
3727 tree name_tree = get_identifier (name);
3728 TREE_ASM_WRITTEN (name_tree) = 1;
3729 }
3730 }
3731
3732 \f
3733 /* Output a double precision value to the assembler. If both the
3734 host and target are IEEE, emit the values in hex. */
3735
3736 void
3737 mips_output_double (stream, value)
3738 FILE *stream;
3739 REAL_VALUE_TYPE value;
3740 {
3741 #ifdef REAL_VALUE_TO_TARGET_DOUBLE
3742 long value_long[2];
3743 REAL_VALUE_TO_TARGET_DOUBLE (value, value_long);
3744
3745 fprintf (stream, "\t.word\t0x%08lx\t\t# %.20g\n\t.word\t0x%08lx\n",
3746 value_long[0], value, value_long[1]);
3747 #else
3748 fprintf (stream, "\t.double\t%.20g\n", value);
3749 #endif
3750 }
3751
3752
3753 /* Output a single precision value to the assembler. If both the
3754 host and target are IEEE, emit the values in hex. */
3755
3756 void
3757 mips_output_float (stream, value)
3758 FILE *stream;
3759 REAL_VALUE_TYPE value;
3760 {
3761 #ifdef REAL_VALUE_TO_TARGET_SINGLE
3762 long value_long;
3763 REAL_VALUE_TO_TARGET_SINGLE (value, value_long);
3764
3765 fprintf (stream, "\t.word\t0x%08lx\t\t# %.12g (float)\n", value_long, value);
3766 #else
3767 fprintf (stream, "\t.float\t%.12g\n", value);
3768 #endif
3769 }
3770
3771 \f
3772 /* Return the bytes needed to compute the frame pointer from the current
3773 stack pointer.
3774
3775 Mips stack frames look like:
3776
3777 Before call After call
3778 +-----------------------+ +-----------------------+
3779 high | | | |
3780 mem. | | | |
3781 | caller's temps. | | caller's temps. |
3782 | | | |
3783 +-----------------------+ +-----------------------+
3784 | | | |
3785 | arguments on stack. | | arguments on stack. |
3786 | | | |
3787 +-----------------------+ +-----------------------+
3788 | 4 words to save | | 4 words to save |
3789 | arguments passed | | arguments passed |
3790 | in registers, even | | in registers, even |
3791 SP->| if not passed. | FP->| if not passed. |
3792 +-----------------------+ +-----------------------+
3793 | |
3794 | GP save for V.4 abi |
3795 | |
3796 +-----------------------+
3797 | |
3798 | fp register save |
3799 | |
3800 +-----------------------+
3801 | |
3802 | gp register save |
3803 | |
3804 +-----------------------+
3805 | |
3806 | local variables |
3807 | |
3808 +-----------------------+
3809 | |
3810 | alloca allocations |
3811 | |
3812 +-----------------------+
3813 | |
3814 | arguments on stack |
3815 | |
3816 +-----------------------+
3817 | 4 words to save |
3818 | arguments passed |
3819 | in registers, even |
3820 low SP->| if not passed. |
3821 memory +-----------------------+
3822
3823 */
3824
3825 unsigned long
3826 compute_frame_size (size)
3827 int size; /* # of var. bytes allocated */
3828 {
3829 int regno;
3830 unsigned long total_size; /* # bytes that the entire frame takes up */
3831 unsigned long var_size; /* # bytes that variables take up */
3832 unsigned long args_size; /* # bytes that outgoing arguments take up */
3833 unsigned long extra_size; /* # extra bytes */
3834 unsigned int gp_reg_rounded; /* # bytes needed to store gp after rounding */
3835 unsigned int gp_reg_size; /* # bytes needed to store gp regs */
3836 unsigned int fp_reg_size; /* # bytes needed to store fp regs */
3837 unsigned long mask; /* mask of saved gp registers */
3838 unsigned long fmask; /* mask of saved fp registers */
3839 int fp_inc; /* 1 or 2 depending on the size of fp regs */
3840 int fp_bits; /* bitmask to use for each fp register */
3841
3842 gp_reg_size = 0;
3843 fp_reg_size = 0;
3844 mask = 0;
3845 fmask = 0;
3846 extra_size = MIPS_STACK_ALIGN (((TARGET_ABICALLS) ? UNITS_PER_WORD : 0));
3847 var_size = MIPS_STACK_ALIGN (size);
3848 args_size = MIPS_STACK_ALIGN (current_function_outgoing_args_size);
3849
3850 /* The MIPS 3.0 linker does not like functions that dynamically
3851 allocate the stack and have 0 for STACK_DYNAMIC_OFFSET, since it
3852 looks like we are trying to create a second frame pointer to the
3853 function, so allocate some stack space to make it happy. */
3854
3855 if (args_size == 0 && current_function_calls_alloca)
3856 args_size = 4*UNITS_PER_WORD;
3857
3858 total_size = var_size + args_size + extra_size;
3859
3860 /* Calculate space needed for gp registers. */
3861 for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
3862 {
3863 if (MUST_SAVE_REGISTER (regno))
3864 {
3865 gp_reg_size += UNITS_PER_WORD;
3866 mask |= 1 << (regno - GP_REG_FIRST);
3867 }
3868 }
3869
3870 /* Calculate space needed for fp registers. */
3871 if (TARGET_FLOAT64)
3872 {
3873 fp_inc = 1;
3874 fp_bits = 1;
3875 }
3876 else
3877 {
3878 fp_inc = 2;
3879 fp_bits = 3;
3880 }
3881
3882 for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += fp_inc)
3883 {
3884 if (regs_ever_live[regno] && !call_used_regs[regno])
3885 {
3886 fp_reg_size += 2*UNITS_PER_WORD;
3887 fmask |= fp_bits << (regno - FP_REG_FIRST);
3888 }
3889 }
3890
3891 gp_reg_rounded = MIPS_STACK_ALIGN (gp_reg_size);
3892 total_size += gp_reg_rounded + fp_reg_size;
3893
3894 if (total_size == extra_size)
3895 total_size = extra_size = 0;
3896
3897 /* Save other computed information. */
3898 current_frame_info.total_size = total_size;
3899 current_frame_info.var_size = var_size;
3900 current_frame_info.args_size = args_size;
3901 current_frame_info.extra_size = extra_size;
3902 current_frame_info.gp_reg_size = gp_reg_size;
3903 current_frame_info.fp_reg_size = fp_reg_size;
3904 current_frame_info.mask = mask;
3905 current_frame_info.fmask = fmask;
3906 current_frame_info.initialized = reload_completed;
3907 current_frame_info.num_gp = gp_reg_size / UNITS_PER_WORD;
3908 current_frame_info.num_fp = fp_reg_size / (2*UNITS_PER_WORD);
3909
3910 if (mask)
3911 {
3912 unsigned long offset = args_size + var_size + gp_reg_size - UNITS_PER_WORD;
3913 current_frame_info.gp_sp_offset = offset;
3914 current_frame_info.gp_save_offset = offset - total_size;
3915 }
3916
3917 if (fmask)
3918 {
3919 unsigned long offset = args_size + var_size + gp_reg_rounded + fp_reg_size - 2*UNITS_PER_WORD;
3920 current_frame_info.fp_sp_offset = offset;
3921 current_frame_info.fp_save_offset = offset - total_size + UNITS_PER_WORD;
3922 }
3923
3924 /* Ok, we're done. */
3925 return total_size;
3926 }
3927
3928 \f
3929 /* Save/restore registers printing out the instructions to a file. */
3930
3931 void
3932 save_restore (file, gp_op, gp_2word_op, fp_op)
3933 FILE *file; /* stream to write to */
3934 char *gp_op; /* operation to do on gp registers */
3935 char *gp_2word_op; /* 2 word op to do on gp registers */
3936 char *fp_op; /* operation to do on fp registers */
3937 {
3938 int regno;
3939 unsigned long mask = current_frame_info.mask;
3940 unsigned long fmask = current_frame_info.fmask;
3941 unsigned long gp_offset;
3942 unsigned long fp_offset;
3943 unsigned long max_offset;
3944 char *base_reg;
3945
3946 if (mask == 0 && fmask == 0)
3947 return;
3948
3949 base_reg = reg_names[STACK_POINTER_REGNUM];
3950 gp_offset = current_frame_info.gp_sp_offset;
3951 fp_offset = current_frame_info.fp_sp_offset;
3952 max_offset = (gp_offset > fp_offset) ? gp_offset : fp_offset;
3953
3954 /* Deal with calling functions with a large structure. */
3955 if (max_offset >= 32768)
3956 {
3957 char *temp = reg_names[MIPS_TEMP2_REGNUM];
3958 fprintf (file, "\tli\t%s,%ld\n", temp, max_offset);
3959 fprintf (file, "\taddu\t%s,%s,%s\n", temp, temp, base_reg);
3960 base_reg = temp;
3961 gp_offset = max_offset - gp_offset;
3962 fp_offset = max_offset - fp_offset;
3963 }
3964
3965 /* Save registers starting from high to low. The debuggers prefer
3966 at least the return register be stored at func+4, and also it
3967 allows us not to need a nop in the epilog if at least one
3968 register is reloaded in addition to return address. */
3969
3970 if (mask || frame_pointer_needed)
3971 {
3972 for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
3973 {
3974 if ((mask & (1L << (regno - GP_REG_FIRST))) != 0
3975 || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed))
3976 {
3977 fprintf (file, "\t%s\t%s,%d(%s)\n",
3978 gp_op, reg_names[regno],
3979 gp_offset, base_reg);
3980
3981 gp_offset -= UNITS_PER_WORD;
3982 }
3983 }
3984 }
3985
3986 if (fmask)
3987 {
3988 int fp_inc = (TARGET_FLOAT64) ? 1 : 2;
3989
3990 for (regno = FP_REG_LAST-1; regno >= FP_REG_FIRST; regno -= fp_inc)
3991 {
3992 if ((fmask & (1L << (regno - FP_REG_FIRST))) != 0)
3993 {
3994 fprintf (file, "\t%s\t%s,%d(%s)\n",
3995 fp_op, reg_names[regno], fp_offset, base_reg);
3996
3997 fp_offset -= 2*UNITS_PER_WORD;
3998 }
3999 }
4000 }
4001 }
4002
4003 \f
4004 /* Common code to emit the insns to save/restore registers. */
4005
4006 static void
4007 save_restore_insns (store_p)
4008 int store_p; /* true if this is prologue */
4009 {
4010 int regno;
4011 rtx base_reg_rtx = stack_pointer_rtx;
4012 unsigned long mask = current_frame_info.mask;
4013 unsigned long fmask = current_frame_info.fmask;
4014 unsigned long gp_offset;
4015 unsigned long fp_offset;
4016 unsigned long max_offset;
4017
4018 if (mask == 0 && fmask == 0)
4019 return;
4020
4021 gp_offset = current_frame_info.gp_sp_offset;
4022 fp_offset = current_frame_info.fp_sp_offset;
4023 max_offset = (gp_offset > fp_offset) ? gp_offset : fp_offset;
4024
4025 /* Deal with calling functions with a large structure. */
4026 if (max_offset >= 32768)
4027 {
4028 base_reg_rtx = gen_rtx (REG, Pmode, MIPS_TEMP2_REGNUM);
4029 emit_move_insn (base_reg_rtx, GEN_INT (max_offset));
4030 emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, stack_pointer_rtx));
4031 gp_offset = max_offset - gp_offset;
4032 fp_offset = max_offset - fp_offset;
4033 }
4034
4035 /* Save registers starting from high to low. The debuggers prefer
4036 at least the return register be stored at func+4, and also it
4037 allows us not to need a nop in the epilog if at least one
4038 register is reloaded in addition to return address. */
4039
4040 if (mask || frame_pointer_needed)
4041 {
4042 for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
4043 {
4044 if ((mask & (1L << (regno - GP_REG_FIRST))) != 0
4045 || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed))
4046 {
4047 rtx reg_rtx = gen_rtx (REG, Pmode, regno);
4048 rtx mem_rtx = gen_rtx (MEM, Pmode,
4049 gen_rtx (PLUS, Pmode, base_reg_rtx,
4050 GEN_INT (gp_offset)));
4051
4052 if (store_p)
4053 emit_move_insn (mem_rtx, reg_rtx);
4054 else
4055 emit_move_insn (reg_rtx, mem_rtx);
4056
4057 gp_offset -= UNITS_PER_WORD;
4058 }
4059 }
4060 }
4061
4062 if (fmask)
4063 {
4064 int fp_inc = (TARGET_FLOAT64) ? 1 : 2;
4065
4066 for (regno = FP_REG_LAST-1; regno >= FP_REG_FIRST; regno -= fp_inc)
4067 {
4068 if ((fmask & (1L << (regno - FP_REG_FIRST))) != 0)
4069 {
4070 rtx reg_rtx = gen_rtx (REG, DFmode, regno);
4071 rtx mem_rtx = gen_rtx (MEM, DFmode,
4072 gen_rtx (PLUS, Pmode, base_reg_rtx,
4073 GEN_INT (fp_offset)));
4074
4075 if (store_p)
4076 emit_move_insn (mem_rtx, reg_rtx);
4077 else
4078 emit_move_insn (reg_rtx, mem_rtx);
4079
4080 fp_offset -= 2*UNITS_PER_WORD;
4081 }
4082 }
4083 }
4084 }
4085
4086 \f
4087 /* Set up the stack and frame (if desired) for the function. */
4088
4089 void
4090 function_prologue (file, size)
4091 FILE *file;
4092 int size;
4093 {
4094 int tsize = current_frame_info.total_size;
4095
4096 ASM_OUTPUT_SOURCE_FILENAME (file, DECL_SOURCE_FILE (current_function_decl));
4097 ASM_OUTPUT_SOURCE_LINE (file, DECL_SOURCE_LINE (current_function_decl));
4098
4099 inside_function = 1;
4100 fputs ("\t.ent\t", file);
4101 assemble_name (file, current_function_name);
4102 fputs ("\n", file);
4103 assemble_name (file, current_function_name);
4104 fputs (":\n", file);
4105
4106 if (TARGET_ABICALLS)
4107 fprintf (file,
4108 "\t.set\tnoreorder\n\t.cpload\t%s\n\t.set\treorder\n",
4109 reg_names[ GP_REG_FIRST + 25 ]);
4110
4111 tsize = current_frame_info.total_size;
4112 if (tsize > 0 && TARGET_ABICALLS)
4113 fprintf (file, "\t.cprestore %d\n", tsize + STARTING_FRAME_OFFSET);
4114
4115 fprintf (file, "\t.frame\t%s,%d,%s\t\t# vars= %d, regs= %d/%d, args = %d, extra= %d\n",
4116 reg_names[ (frame_pointer_needed) ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM ],
4117 tsize,
4118 reg_names[31 + GP_REG_FIRST],
4119 current_frame_info.var_size,
4120 current_frame_info.num_gp,
4121 current_frame_info.num_fp,
4122 current_function_outgoing_args_size,
4123 current_frame_info.extra_size);
4124
4125 fprintf (file, "\t.mask\t0x%08lx,%d\n\t.fmask\t0x%08lx,%d\n",
4126 current_frame_info.mask,
4127 current_frame_info.gp_save_offset,
4128 current_frame_info.fmask,
4129 current_frame_info.fp_save_offset);
4130 }
4131
4132 \f
4133 /* Expand the prologue into a bunch of separate insns. */
4134
4135 void
4136 mips_expand_prologue ()
4137 {
4138 int regno;
4139 int tsize;
4140 tree fndecl = current_function_decl; /* current... is tooo long */
4141 tree fntype = TREE_TYPE (fndecl);
4142 tree fnargs = (TREE_CODE (fntype) != METHOD_TYPE)
4143 ? DECL_ARGUMENTS (fndecl)
4144 : 0;
4145 tree next_arg;
4146 tree cur_arg;
4147 char *arg_name = (char *)0;
4148 CUMULATIVE_ARGS args_so_far;
4149
4150 /* Determine the last argument, and get its name. */
4151 for (cur_arg = fnargs; cur_arg != (tree)0; cur_arg = next_arg)
4152 {
4153 next_arg = TREE_CHAIN (cur_arg);
4154 if (next_arg == (tree)0)
4155 {
4156 if (DECL_NAME (cur_arg))
4157 arg_name = IDENTIFIER_POINTER (DECL_NAME (cur_arg));
4158
4159 break;
4160 }
4161 }
4162
4163 /* If this function is a varargs function, store any registers that
4164 would normally hold arguments ($4 - $7) on the stack. */
4165 if ((TYPE_ARG_TYPES (fntype) != 0
4166 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node))
4167 || (arg_name
4168 && (strcmp (arg_name, "__builtin_va_alist") == 0
4169 || strcmp (arg_name, "va_alist") == 0)))
4170 {
4171 tree parm;
4172
4173 regno = GP_ARG_FIRST;
4174 INIT_CUMULATIVE_ARGS (args_so_far, fntype, (rtx)0);
4175
4176 for (parm = fnargs; (parm && (regno <= GP_ARG_LAST)); parm = TREE_CHAIN (parm))
4177 {
4178 rtx entry_parm;
4179 enum machine_mode passed_mode;
4180 tree type;
4181
4182 type = DECL_ARG_TYPE (parm);
4183 passed_mode = TYPE_MODE (type);
4184 entry_parm = FUNCTION_ARG (args_so_far, passed_mode,
4185 DECL_ARG_TYPE (parm), 1);
4186
4187 if (entry_parm)
4188 {
4189 int words;
4190
4191 /* passed in a register, so will get homed automatically */
4192 if (GET_MODE (entry_parm) == BLKmode)
4193 words = (int_size_in_bytes (type) + 3) / 4;
4194 else
4195 words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
4196
4197 regno = REGNO (entry_parm) + words - 1;
4198 }
4199 else
4200 {
4201 regno = GP_ARG_LAST+1;
4202 break;
4203 }
4204
4205 FUNCTION_ARG_ADVANCE (args_so_far, passed_mode,
4206 DECL_ARG_TYPE (parm), 1);
4207 }
4208
4209 for (; regno <= GP_ARG_LAST; regno++)
4210 {
4211 rtx ptr = stack_pointer_rtx;
4212 if (regno != GP_ARG_FIRST)
4213 ptr = gen_rtx (PLUS, Pmode, ptr,
4214 GEN_INT ((regno - GP_ARG_FIRST) * UNITS_PER_WORD));
4215
4216 emit_move_insn (gen_rtx (MEM, Pmode, ptr), gen_rtx (REG, Pmode, regno));
4217 }
4218 }
4219
4220 tsize = compute_frame_size (get_frame_size ());
4221 if (tsize > 0)
4222 {
4223 rtx tsize_rtx = GEN_INT (tsize);
4224
4225 if (tsize > 32767)
4226 {
4227 rtx tmp_rtx = gen_rtx (REG, SImode, MIPS_TEMP1_REGNUM);
4228 emit_move_insn (tmp_rtx, tsize_rtx);
4229 tsize_rtx = tmp_rtx;
4230 }
4231
4232 emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tsize_rtx));
4233
4234 save_restore_insns (TRUE);
4235
4236 if (frame_pointer_needed)
4237 emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
4238 }
4239 }
4240
4241 \f
4242 /* Do any necessary cleanup after a function to restore stack, frame, and regs. */
4243
4244 void
4245 function_epilogue (file, size)
4246 FILE *file;
4247 int size;
4248 {
4249 int tsize;
4250 char *sp_str = reg_names[STACK_POINTER_REGNUM];
4251 char *t1_str = reg_names[MIPS_TEMP1_REGNUM];
4252 rtx epilogue_delay = current_function_epilogue_delay_list;
4253 int noreorder = !TARGET_MIPS_AS || (epilogue_delay != 0);
4254 int noepilogue = FALSE;
4255 int load_nop = FALSE;
4256 int load_only_r31;
4257
4258 /* The epilogue does not depend on any registers, but the stack
4259 registers, so we assume that if we have 1 pending nop, it can be
4260 ignored, and 2 it must be filled (2 nops occur for integer
4261 multiply and divide). */
4262
4263 if (dslots_number_nops > 0)
4264 {
4265 if (dslots_number_nops == 1)
4266 {
4267 dslots_number_nops = 0;
4268 dslots_load_filled++;
4269 }
4270 else
4271 {
4272 while (--dslots_number_nops > 0)
4273 fputs ((set_noreorder) ? "\tnop\n" : "\t#nop\n", asm_out_file);
4274 }
4275
4276 if (set_noreorder > 0 && --set_noreorder == 0)
4277 fputs ("\t.set\treorder\n", file);
4278 }
4279
4280 if (set_noat != 0)
4281 {
4282 set_noat = 0;
4283 fputs ("\t.set\tat\n", file);
4284 error ("internal gcc error: .set noat left on in epilogue");
4285 }
4286
4287 if (set_nomacro != 0)
4288 {
4289 set_nomacro = 0;
4290 fputs ("\t.set\tmacro\n", file);
4291 error ("internal gcc error: .set nomacro left on in epilogue");
4292 }
4293
4294 if (set_noreorder != 0)
4295 {
4296 set_noreorder = 0;
4297 fputs ("\t.set\treorder\n", file);
4298 error ("internal gcc error: .set noreorder left on in epilogue");
4299 }
4300
4301 if (set_volatile != 0)
4302 {
4303 set_volatile = 0;
4304 fprintf (file, "\t#.set\tnovolatile\n", (TARGET_MIPS_AS) ? "" : "#");
4305 error ("internal gcc error: .set volatile left on in epilogue");
4306 }
4307
4308 size = MIPS_STACK_ALIGN (size);
4309 tsize = (!current_frame_info.initialized)
4310 ? compute_frame_size (size)
4311 : current_frame_info.total_size;
4312
4313 if (tsize == 0 && epilogue_delay == 0)
4314 {
4315 rtx insn = get_last_insn ();
4316
4317 /* If the last insn was a BARRIER, we don't have to write any code
4318 because a jump (aka return) was put there. */
4319 if (GET_CODE (insn) == NOTE)
4320 insn = prev_nonnote_insn (insn);
4321 if (insn && GET_CODE (insn) == BARRIER)
4322 noepilogue = TRUE;
4323
4324 noreorder = FALSE;
4325 }
4326
4327 if (!noepilogue)
4328 {
4329 /* In the reload sequence, we don't need to fill the load delay
4330 slots for most of the loads, also see if we can fill the final
4331 delay slot if not otherwise filled by the reload sequence. */
4332
4333 if (noreorder)
4334 fprintf (file, "\t.set\tnoreorder\n");
4335
4336 if (tsize > 32767)
4337 fprintf (file, "\tli\t%s,%d\n", t1_str, tsize);
4338
4339 if (frame_pointer_needed)
4340 fprintf (file, "\tmove\t%s,%s\t\t\t# sp not trusted here\n",
4341 sp_str, reg_names[FRAME_POINTER_REGNUM]);
4342
4343 save_restore (file, "lw", "ld", "l.d");
4344
4345 load_only_r31 = (current_frame_info.mask == (1 << 31)
4346 && current_frame_info.fmask == 0);
4347
4348 if (noreorder)
4349 {
4350 /* If the only register saved is the return address, we need a
4351 nop, unless we have an instruction to put into it. Otherwise
4352 we don't since reloading multiple registers doesn't reference
4353 the register being loaded. */
4354
4355 if (load_only_r31)
4356 {
4357 if (epilogue_delay)
4358 final_scan_insn (XEXP (epilogue_delay, 0),
4359 file,
4360 1, /* optimize */
4361 -2, /* prescan */
4362 1); /* nopeepholes */
4363 else
4364 {
4365 fprintf (file, "\tnop\n");
4366 load_nop = TRUE;
4367 }
4368 }
4369
4370 fprintf (file, "\tj\t%s\n", reg_names[GP_REG_FIRST + 31]);
4371
4372 if (tsize > 32767)
4373 fprintf (file, "\taddu\t%s,%s,%s\n", sp_str, sp_str, t1_str);
4374
4375 else if (tsize > 0)
4376 fprintf (file, "\taddu\t%s,%s,%d\n", sp_str, sp_str, tsize);
4377
4378 else if (!load_only_r31 && epilogue_delay != 0)
4379 final_scan_insn (XEXP (epilogue_delay, 0),
4380 file,
4381 1, /* optimize */
4382 -2, /* prescan */
4383 1); /* nopeepholes */
4384
4385 fprintf (file, "\t.set\treorder\n");
4386 }
4387
4388 else
4389 {
4390 if (tsize > 32767)
4391 fprintf (file, "\taddu\t%s,%s,%s\n", sp_str, sp_str, t1_str);
4392
4393 else if (tsize > 0)
4394 fprintf (file, "\taddu\t%s,%s,%d\n", sp_str, sp_str, tsize);
4395
4396 fprintf (file, "\tj\t%s\n", reg_names[GP_REG_FIRST + 31]);
4397 }
4398 }
4399
4400 fputs ("\t.end\t", file);
4401 assemble_name (file, current_function_name);
4402 fputs ("\n", file);
4403
4404 if (TARGET_STATS)
4405 {
4406 int num_gp_regs = current_frame_info.gp_reg_size / 4;
4407 int num_fp_regs = current_frame_info.fp_reg_size / 8;
4408 int num_regs = num_gp_regs + num_fp_regs;
4409 char *name = current_function_name;
4410
4411 if (name[0] == '*')
4412 name++;
4413
4414 dslots_load_total += num_regs;
4415
4416 if (!noepilogue)
4417 dslots_jump_total++;
4418
4419 if (noreorder)
4420 {
4421 dslots_load_filled += num_regs;
4422
4423 /* If the only register saved is the return register, we
4424 can't fill this register's delay slot. */
4425
4426 if (load_only_r31 && epilogue_delay == 0)
4427 dslots_load_filled--;
4428
4429 if (tsize > 0 || (!load_only_r31 && epilogue_delay != 0))
4430 dslots_jump_filled++;
4431 }
4432
4433 fprintf (stderr,
4434 "%-20s fp=%c leaf=%c alloca=%c setjmp=%c stack=%4ld arg=%3ld reg=%2d/%d delay=%3d/%3dL %3d/%3dJ refs=%3d/%3d/%3d",
4435 name,
4436 (frame_pointer_needed) ? 'y' : 'n',
4437 ((current_frame_info.mask & (1 << 31)) != 0) ? 'n' : 'y',
4438 (current_function_calls_alloca) ? 'y' : 'n',
4439 (current_function_calls_setjmp) ? 'y' : 'n',
4440 (long)current_frame_info.total_size,
4441 (long)current_function_outgoing_args_size,
4442 num_gp_regs, num_fp_regs,
4443 dslots_load_total, dslots_load_filled,
4444 dslots_jump_total, dslots_jump_filled,
4445 num_refs[0], num_refs[1], num_refs[2]);
4446
4447 if (HALF_PIC_NUMBER_PTRS > prev_half_pic_ptrs)
4448 {
4449 fprintf (stderr, " half-pic=%3d", HALF_PIC_NUMBER_PTRS - prev_half_pic_ptrs);
4450 prev_half_pic_ptrs = HALF_PIC_NUMBER_PTRS;
4451 }
4452
4453 if (HALF_PIC_NUMBER_REFS > prev_half_pic_refs)
4454 {
4455 fprintf (stderr, " pic-ref=%3d", HALF_PIC_NUMBER_REFS - prev_half_pic_refs);
4456 prev_half_pic_refs = HALF_PIC_NUMBER_REFS;
4457 }
4458
4459 fputc ('\n', stderr);
4460 }
4461
4462 /* Reset state info for each function. */
4463 inside_function = FALSE;
4464 ignore_line_number = FALSE;
4465 dslots_load_total = 0;
4466 dslots_jump_total = 0;
4467 dslots_load_filled = 0;
4468 dslots_jump_filled = 0;
4469 num_refs[0] = 0;
4470 num_refs[1] = 0;
4471 num_refs[2] = 0;
4472 mips_load_reg = (rtx)0;
4473 mips_load_reg2 = (rtx)0;
4474 current_frame_info = zero_frame_info;
4475
4476 /* Restore the output file if optimizing the GP (optimizing the GP causes
4477 the text to be diverted to a tempfile, so that data decls come before
4478 references to the data). */
4479
4480 if (TARGET_GP_OPT)
4481 asm_out_file = asm_out_data_file;
4482 }
4483
4484 \f
4485 /* Expand the epilogue into a bunch of separate insns. */
4486
4487 void
4488 mips_expand_epilogue ()
4489 {
4490 int tsize = current_frame_info.total_size;
4491 rtx tsize_rtx = GEN_INT (tsize);
4492
4493 if (tsize > 32767)
4494 {
4495 rtx tmp_rtx = gen_rtx (REG, SImode, MIPS_TEMP1_REGNUM);
4496 emit_move_insn (tmp_rtx, tsize_rtx);
4497 tsize_rtx = tmp_rtx;
4498 }
4499
4500 if (tsize > 0)
4501 {
4502 if (frame_pointer_needed)
4503 emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
4504
4505 save_restore_insns (FALSE);
4506
4507 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tsize_rtx));
4508 }
4509
4510 emit_jump_insn (gen_return_internal (gen_rtx (REG, Pmode, GP_REG_FIRST+31)));
4511 }
4512
4513 \f
4514 /* Define the number of delay slots needed for the function epilogue.
4515
4516 On the mips, we need a slot if either no stack has been allocated,
4517 or the only register saved is the return register. */
4518
4519 int
4520 mips_epilogue_delay_slots ()
4521 {
4522 if (!current_frame_info.initialized)
4523 (void) compute_frame_size (get_frame_size ());
4524
4525 if (current_frame_info.total_size == 0)
4526 return 1;
4527
4528 if (current_frame_info.mask == (1 << 31) && current_frame_info.fmask == 0)
4529 return 1;
4530
4531 return 0;
4532 }
4533
4534 \f
4535 /* Return true if this function is known to have a null epilogue.
4536 This allows the optimizer to omit jumps to jumps if no stack
4537 was created. */
4538
4539 int
4540 simple_epilogue_p ()
4541 {
4542 if (!reload_completed)
4543 return 0;
4544
4545 if (current_frame_info.initialized)
4546 return current_frame_info.total_size == 0;
4547
4548 return (compute_frame_size (get_frame_size ())) == 0;
4549 }
This page took 0.253019 seconds and 5 git commands to generate.