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