OSDN Git Service

(not_qsort): New function.
[pf3gnuchains/gcc-fork.git] / gcc / config / vax / vax.c
1 /* Subroutines for insn-output.c for Vax.
2    Copyright (C) 1987 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include <stdio.h>
21 #include "config.h"
22 #include "rtl.h"
23 #include "regs.h"
24 #include "hard-reg-set.h"
25 #include "real.h"
26 #include "insn-config.h"
27 #include "conditions.h"
28 #include "insn-flags.h"
29 #include "output.h"
30 #include "insn-attr.h"
31
32
33 /* This is like nonimmediate_operand with a restriction on the type of MEM.  */
34
35 void
36 split_quadword_operands (operands, low, n)
37      rtx *operands, *low;
38      int n;
39 {
40   int i;
41   /* Split operands.  */
42
43   low[0] = low[1] = low[2] = 0;
44   for (i = 0; i < 3; i++)
45     {
46       if (low[i])
47         /* it's already been figured out */;
48       else if (GET_CODE (operands[i]) == MEM
49                && (GET_CODE (XEXP (operands[i], 0)) == POST_INC))
50         {
51           rtx addr = XEXP (operands[i], 0);
52           operands[i] = low[i] = gen_rtx (MEM, SImode, addr);
53           if (which_alternative == 0 && i == 0)
54             {
55               addr = XEXP (operands[i], 0);
56               operands[i+1] = low[i+1] = gen_rtx (MEM, SImode, addr);
57             }
58         }
59       else
60         {
61           low[i] = operand_subword (operands[i], 0, 0, DImode);
62           operands[i] = operand_subword (operands[i], 1, 0, DImode);
63         }
64     }
65 }
66 \f
67 print_operand_address (file, addr)
68      FILE *file;
69      register rtx addr;
70 {
71   register rtx reg1, reg2, breg, ireg;
72   rtx offset;
73
74  retry:
75   switch (GET_CODE (addr))
76     {
77     case MEM:
78       fprintf (file, "*");
79       addr = XEXP (addr, 0);
80       goto retry;
81
82     case REG:
83       fprintf (file, "(%s)", reg_names[REGNO (addr)]);
84       break;
85
86     case PRE_DEC:
87       fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
88       break;
89
90     case POST_INC:
91       fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
92       break;
93
94     case PLUS:
95       /* There can be either two or three things added here.  One must be a
96          REG.  One can be either a REG or a MULT of a REG and an appropriate
97          constant, and the third can only be a constant or a MEM.
98
99          We get these two or three things and put the constant or MEM in
100          OFFSET, the MULT or REG in IREG, and the REG in BREG.  If we have
101          a register and can't tell yet if it is a base or index register,
102          put it into REG1.  */
103
104       reg1 = 0; ireg = 0; breg = 0; offset = 0;
105
106       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
107           || GET_CODE (XEXP (addr, 0)) == MEM)
108         {
109           offset = XEXP (addr, 0);
110           addr = XEXP (addr, 1);
111         }
112       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
113                || GET_CODE (XEXP (addr, 1)) == MEM)
114         {
115           offset = XEXP (addr, 1);
116           addr = XEXP (addr, 0);
117         }
118       else if (GET_CODE (XEXP (addr, 1)) == MULT)
119         {
120           ireg = XEXP (addr, 1);
121           addr = XEXP (addr, 0);
122         }
123       else if (GET_CODE (XEXP (addr, 0)) == MULT)
124         {
125           ireg = XEXP (addr, 0);
126           addr = XEXP (addr, 1);
127         }
128       else if (GET_CODE (XEXP (addr, 1)) == REG)
129         {
130           reg1 = XEXP (addr, 1);
131           addr = XEXP (addr, 0);
132         }
133       else if (GET_CODE (XEXP (addr, 0)) == REG)
134         {
135           reg1 = XEXP (addr, 0);
136           addr = XEXP (addr, 1);
137         }
138       else
139         abort ();
140
141       if (GET_CODE (addr) == REG)
142         {
143           if (reg1)
144             ireg = addr;
145           else
146             reg1 = addr;
147         }
148       else if (GET_CODE (addr) == MULT)
149         ireg = addr;
150       else if (GET_CODE (addr) == PLUS)
151         {
152           if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
153               || GET_CODE (XEXP (addr, 0)) == MEM)
154             {
155               if (offset)
156                 {
157                   if (GET_CODE (offset) == CONST_INT)
158                     offset = plus_constant (XEXP (addr, 0), INTVAL (offset));
159                   else if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
160                     offset = plus_constant (offset, INTVAL (XEXP (addr, 0)));
161                   else
162                     abort ();
163                 }
164               offset = XEXP (addr, 0);
165             }
166           else if (GET_CODE (XEXP (addr, 0)) == REG)
167             {
168               if (reg1)
169                 ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
170               else
171                 reg1 = XEXP (addr, 0);
172             }
173           else if (GET_CODE (XEXP (addr, 0)) == MULT)
174             {
175               if (ireg)
176                 abort ();
177               ireg = XEXP (addr, 0);
178             }
179           else
180             abort ();
181
182           if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
183               || GET_CODE (XEXP (addr, 1)) == MEM)
184             {
185               if (offset)
186                 {
187                   if (GET_CODE (offset) == CONST_INT)
188                     offset = plus_constant (XEXP (addr, 1), INTVAL (offset));
189                   else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
190                     offset = plus_constant (offset, INTVAL (XEXP (addr, 1)));
191                   else
192                     abort ();
193                 }
194               offset = XEXP (addr, 1);
195             }
196           else if (GET_CODE (XEXP (addr, 1)) == REG)
197             {
198               if (reg1)
199                 ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
200               else
201                 reg1 = XEXP (addr, 1);
202             }
203           else if (GET_CODE (XEXP (addr, 1)) == MULT)
204             {
205               if (ireg)
206                 abort ();
207               ireg = XEXP (addr, 1);
208             }
209           else
210             abort ();
211         }
212       else
213         abort ();
214
215       /* If REG1 is non-zero, figure out if it is a base or index register.  */
216       if (reg1)
217         {
218           if (breg != 0 || (offset && GET_CODE (offset) == MEM))
219             {
220               if (ireg)
221                 abort ();
222               ireg = reg1;
223             }
224           else
225             breg = reg1;
226         }
227
228       if (offset != 0)
229         output_address (offset);
230
231       if (breg != 0)
232         fprintf (file, "(%s)", reg_names[REGNO (breg)]);
233
234       if (ireg != 0)
235         {
236           if (GET_CODE (ireg) == MULT)
237             ireg = XEXP (ireg, 0);
238           if (GET_CODE (ireg) != REG)
239             abort ();
240           fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
241         }
242       break;
243
244     default:
245       output_addr_const (file, addr);
246     }
247 }
248 \f
249 char *
250 rev_cond_name (op)
251      rtx op;
252 {
253   switch (GET_CODE (op))
254     {
255     case EQ:
256       return "neq";
257     case NE:
258       return "eql";
259     case LT:
260       return "geq";
261     case LE:
262       return "gtr";
263     case GT:
264       return "leq";
265     case GE:
266       return "lss";
267     case LTU:
268       return "gequ";
269     case LEU:
270       return "gtru";
271     case GTU:
272       return "lequ";
273     case GEU:
274       return "lssu";
275
276     default:
277       abort ();
278     }
279 }
280
281 int
282 vax_float_literal(c)
283     register rtx c;
284 {
285   register enum machine_mode mode;
286   int i;
287   union {double d; int i[2];} val;
288
289   if (GET_CODE (c) != CONST_DOUBLE)
290     return 0;
291
292   mode = GET_MODE (c);
293
294   if (c == const_tiny_rtx[(int) mode][0]
295       || c == const_tiny_rtx[(int) mode][1]
296       || c == const_tiny_rtx[(int) mode][2])
297     return 1;
298
299 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
300
301   val.i[0] = CONST_DOUBLE_LOW (c);
302   val.i[1] = CONST_DOUBLE_HIGH (c);
303
304   for (i = 0; i < 7; i ++)
305     if (val.d == 1 << i || val.d == 1 / (1 << i))
306       return 1;
307 #endif
308   return 0;
309 }
310
311
312 /* Return the cost in cycles of a memory address, relative to register
313    indirect.
314
315    Each of the following adds the indicated number of cycles:
316
317    1 - symbolic address
318    1 - pre-decrement
319    1 - indexing and/or offset(register)
320    2 - indirect */
321
322
323 int vax_address_cost(addr)
324     register rtx addr;
325 {
326   int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
327   rtx plus_op0 = 0, plus_op1 = 0;
328  restart:
329   switch (GET_CODE (addr))
330     {
331     case PRE_DEC:
332       predec = 1;
333     case REG:
334     case SUBREG:
335     case POST_INC:
336       reg = 1;
337       break;
338     case MULT:
339       indexed = 1;      /* 2 on VAX 2 */
340       break;
341     case CONST_INT:
342       /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
343       if (offset == 0)
344         offset = (unsigned)(INTVAL(addr)+128) > 256;
345       break;
346     case CONST:
347     case SYMBOL_REF:
348       offset = 1;       /* 2 on VAX 2 */
349       break;
350     case LABEL_REF:     /* this is probably a byte offset from the pc */
351       if (offset == 0)
352         offset = 1;
353       break;
354     case PLUS:
355       if (plus_op0)
356         plus_op1 = XEXP (addr, 0);
357       else
358         plus_op0 = XEXP (addr, 0);
359       addr = XEXP (addr, 1);
360       goto restart;
361     case MEM:
362       indir = 2;        /* 3 on VAX 2 */
363       addr = XEXP (addr, 0);
364       goto restart;
365     }
366
367   /* Up to 3 things can be added in an address.  They are stored in
368      plus_op0, plus_op1, and addr.  */
369
370   if (plus_op0)
371     {
372       addr = plus_op0;
373       plus_op0 = 0;
374       goto restart;
375     }
376   if (plus_op1)
377     {
378       addr = plus_op1;
379       plus_op1 = 0;
380       goto restart;
381     }
382   /* Indexing and register+offset can both be used (except on a VAX 2)
383      without increasing execution time over either one alone. */
384   if (reg && indexed && offset)
385     return reg + indir + offset + predec;
386   return reg + indexed + indir + offset + predec;
387 }
388
389
390 /* Cost of an expression on a VAX.  This version has costs tuned for the
391    CVAX chip (found in the VAX 3 series) with comments for variations on
392    other models.  */
393
394 int
395 vax_rtx_cost (x)
396     register rtx x;
397 {
398   register enum rtx_code code = GET_CODE (x);
399   enum machine_mode mode = GET_MODE (x);
400   register int c;
401   int i = 0;                            /* may be modified in switch */
402   char *fmt = GET_RTX_FORMAT (code);    /* may be modified in switch */
403
404   switch (code)
405     {
406     case POST_INC:
407       return 2;
408     case PRE_DEC:
409       return 3;
410     case MULT:
411       switch (mode)
412         {
413         case DFmode:
414           c = 16;               /* 4 on VAX 9000 */
415           break;
416         case SFmode:
417           c = 9;                /* 4 on VAX 9000, 12 on VAX 2 */
418           break;
419         case DImode:
420           c = 16;               /* 6 on VAX 9000, 28 on VAX 2 */
421           break;
422         case SImode:
423         case HImode:
424         case QImode:
425           c = 10;               /* 3-4 on VAX 9000, 20-28 on VAX 2 */
426           break;
427         }
428       break;
429     case UDIV:
430       c = 17;
431       break;
432     case DIV:
433       if (mode == DImode)
434         c = 30; /* highly variable */
435       else if (mode == DFmode)
436         /* divide takes 28 cycles if the result is not zero, 13 otherwise */
437         c = 24;
438       else
439         c = 11;                 /* 25 on VAX 2 */
440       break;
441     case MOD:
442       c = 23;
443       break;
444     case UMOD:
445       c = 29;
446       break;
447     case FLOAT:
448       c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
449       /* 4 on VAX 9000 */
450       break;
451     case FIX:
452       c = 7;                    /* 17 on VAX 2 */
453       break;
454     case LSHIFT:
455     case ASHIFT:
456     case LSHIFTRT:
457     case ASHIFTRT:
458       if (mode == DImode)
459         c = 12;
460       else
461         c = 10;                 /* 6 on VAX 9000 */
462       break;
463     case ROTATE:
464     case ROTATERT:
465       c = 6;                    /* 5 on VAX 2, 4 on VAX 9000 */
466       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
467         fmt = "e";      /* all constant rotate counts are short */
468       break;
469     case PLUS:
470       /* Check for small negative integer operand: subl2 can be used with
471          a short positive constant instead.  */
472       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
473         if ((unsigned)(INTVAL (XEXP (x, 1)) + 63) < 127)
474           fmt = "e";
475     case MINUS:
476       c = (mode == DFmode) ? 13 : 8;    /* 6/8 on VAX 9000, 16/15 on VAX 2 */
477     case IOR:
478     case XOR:
479       c = 3;
480       break;
481     case AND:
482       /* AND is special because the first operand is complemented. */
483       c = 3;
484       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
485         {
486           if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
487             c = 4;
488           fmt = "e";
489           i = 1;
490         }
491       break;
492     case NEG:
493       if (mode == DFmode)
494         return 9;
495       else if (mode == SFmode)
496         return 6;
497       else if (mode == DImode)
498         return 4;
499     case NOT:
500       return 2;
501     case ZERO_EXTRACT:
502     case SIGN_EXTRACT:
503       c = 15;
504       break;
505     case MEM:
506       if (mode == DImode || mode == DFmode)
507         c = 5;                          /* 7 on VAX 2 */
508       else
509         c = 3;                          /* 4 on VAX 2 */
510       x = XEXP (x, 0);
511       if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
512         return c;
513       return c + vax_address_cost (x);
514     default:
515       c = 3;
516       break;
517     }
518
519
520   /* Now look inside the expression.  Operands which are not registers or
521      short constants add to the cost.
522
523      FMT and I may have been adjusted in the switch above for instructions
524      which require special handling */
525
526   while (*fmt++ == 'e')
527     {
528       register rtx op = XEXP (x, i++);
529       code = GET_CODE (op);
530
531       /* A NOT is likely to be found as the first operand of an AND
532          (in which case the relevant cost is of the operand inside
533          the not) and not likely to be found anywhere else.  */
534       if (code == NOT)
535         op = XEXP (op, 0), code = GET_CODE (op);
536
537       switch (code)
538         {
539         case CONST_INT:
540           if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
541             c += 1;             /* 2 on VAX 2 */
542           break;
543         case CONST:
544         case LABEL_REF:
545         case SYMBOL_REF:
546           c += 1;               /* 2 on VAX 2 */
547           break;
548         case CONST_DOUBLE:
549           if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
550             {
551               /* Registers are faster than floating point constants -- even
552                  those constants which can be encoded in a single byte.  */
553               if (vax_float_literal (op))
554                 c++;
555               else
556                 c += (GET_MODE (x) == DFmode) ? 3 : 2;
557             }
558           else
559             {
560               if (CONST_DOUBLE_HIGH (op) != 0
561                   || (unsigned)CONST_DOUBLE_LOW (op) > 63)
562                 c += 2;
563             }
564           break;
565         case MEM:
566           c += 1;               /* 2 on VAX 2 */
567           if (GET_CODE (XEXP (op, 0)) != REG)
568             c += vax_address_cost (XEXP (op, 0));
569           break;
570         case REG:
571         case SUBREG:
572           break;
573         default:
574           c += 1;
575           break;
576         }
577     }
578   return c;
579 }
580 \f
581 #ifdef VMS
582 /* Additional support code for VMS. */
583
584 #ifdef QSORT_WORKAROUND
585   /*
586         Do not use VAXCRTL's qsort() due to a severe bug:  once you've
587         sorted something which has a size that's an exact multiple of 4
588         and is longword aligned, you cannot safely sort anything which
589         is either not a multiple of 4 in size or not longword aligned.
590         A static "move-by-longword" optimization flag inside qsort() is
591         never reset.  This is known of affect VMS V4.6 through VMS V5.5-1.
592
593         In this work-around an insertion sort is used for simplicity.
594         The qsort code from glibc should probably be used instead.
595    */
596 void
597 not_qsort (array, count, size, compare)
598      void *array;
599      unsigned count, size;
600      int (*compare)();
601 {
602
603   if (size == sizeof (short))
604     {
605       register int i;
606       register short *next, *prev;
607       short tmp, *base = array;
608
609       for (next = base, i = count - 1; i > 0; i--)
610         {
611           prev = next++;
612           if ((*compare)(next, prev) < 0)
613             {
614               tmp = *next;
615               do  *(prev + 1) = *prev;
616                 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
617               *(prev + 1) = tmp;
618             }
619         }
620     }
621   else if (size == sizeof (long))
622     {
623       register int i;
624       register long *next, *prev;
625       long tmp, *base = array;
626
627       for (next = base, i = count - 1; i > 0; i--)
628         {
629           prev = next++;
630           if ((*compare)(next, prev) < 0)
631             {
632               tmp = *next;
633               do  *(prev + 1) = *prev;
634                 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
635               *(prev + 1) = tmp;
636             }
637         }
638     }
639   else  /* arbitrary size */
640     {
641 #ifdef USE_C_ALLOCA
642       extern void *alloca ();
643 #endif
644       register int i;
645       register char *next, *prev, *tmp = alloca (size), *base = array;
646
647       for (next = base, i = count - 1; i > 0; i--)
648         {   /* count-1 forward iterations */
649           prev = next,  next += size;           /* increment front pointer */
650           if ((*compare)(next, prev) < 0)
651             {   /* found element out of order; move others up then re-insert */
652               memcpy (tmp, next, size);         /* save smaller element */
653               do { memcpy (prev + size, prev, size); /* move larger elem. up */
654                    prev -= size;                /* decrement back pointer */
655                  } while (prev >= base ? (*compare)(tmp, prev) < 0 : 0);
656               memcpy (prev + size, tmp, size);  /* restore small element */
657             }
658         }
659 #ifdef USE_C_ALLOCA
660       alloca (0);
661 #endif
662     }
663
664   return;
665 }
666 #endif /* QSORT_WORKAROUND */
667
668 #endif /* VMS */