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