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