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