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