OSDN Git Service

(hard_regno_mode_ok): Don't abort if unknown mode,
[pf3gnuchains/gcc-fork.git] / gcc / config / ns32k / ns32k.c
1 /* Subroutines for assembler code output on the NS32000.
2    Copyright (C) 1988 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 /* Some output-actions in ns32k.md need these.  */
21 #include <stdio.h>
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 "output.h"
31 #include "insn-attr.h"
32
33 #ifdef OSF_OS
34 int ns32k_num_files = 0;
35 #endif
36
37 void
38 trace (s, s1, s2)
39      char *s, *s1, *s2;
40 {
41   fprintf (stderr, s, s1, s2);
42 }
43
44 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ 
45
46 int
47 hard_regno_mode_ok (regno, mode)
48      int regno;
49      enum machine_mode mode;
50 {
51   switch (mode)
52     {
53     case QImode:
54     case HImode:
55     case PSImode:
56     case SImode:
57     case PDImode:
58     case VOIDmode:
59     case BLKmode:
60       if (regno < 8 || regno == 16 || regno == 17)
61         return 1;
62       else
63         return 0;
64
65     case DImode:
66       if (regno < 8 && (regno & 1) == 0)
67         return 1;
68       else
69         return 0;
70
71     case SFmode:
72     case SCmode:
73       if (TARGET_32081)
74         {
75           if (regno < 16)
76             return 1;
77           else
78             return 0;
79         }
80       else
81         {
82           if (regno < 8)
83             return 1;
84           else 
85             return 0;
86         }
87
88     case DFmode:
89     case DCmode:
90       if ((regno & 1) == 0)
91         {       
92           if (TARGET_32081)
93             {
94               if (regno < 16)
95                 return 1;
96               else
97                 return 0;
98             }
99           else
100             {
101               if (regno < 8)
102                 return 1;
103               else
104                 return 0;
105             }
106         }
107       else
108         return 0;
109     }
110
111   /* Used to abort here, but simply saying "no" handles TImode
112      much better.  */
113   return 0;
114 }
115
116 /* ADDRESS_COST calls this.  This function is not optimal
117    for the 32032 & 32332, but it probably is better than
118    the default. */
119
120 int
121 calc_address_cost (operand)
122      rtx operand;
123 {
124   int i;
125   int cost = 0;
126   
127   if (GET_CODE (operand) == MEM)
128     cost += 3;
129   if (GET_CODE (operand) == MULT)
130     cost += 2;
131 #if 0
132   if (GET_CODE (operand) == REG)
133     cost += 1;                  /* not really, but the documentation
134                                    says different amount of registers
135                                    shouldn't return the same costs */
136 #endif
137   switch (GET_CODE (operand))
138     {
139     case REG:
140     case CONST:
141     case CONST_INT:
142     case CONST_DOUBLE:
143     case SYMBOL_REF:
144     case LABEL_REF:
145     case POST_DEC:
146     case PRE_DEC:
147       break;
148     case MULT:
149     case MEM:
150     case PLUS:
151       for (i = 0; i < GET_RTX_LENGTH (GET_CODE (operand)); i++)
152         {
153           cost += calc_address_cost (XEXP (operand, i));
154         }
155     default:
156       break;
157     }
158   return cost;
159 }
160
161 /* Return the register class of a scratch register needed to copy IN into
162    or out of a register in CLASS in MODE.  If it can be done directly,
163    NO_REGS is returned.  */
164
165 enum reg_class
166 secondary_reload_class (class, mode, in)
167      enum reg_class class;
168      enum machine_mode mode;
169      rtx in;
170 {
171   int regno = true_regnum (in);
172
173   if (regno >= FIRST_PSEUDO_REGISTER)
174     regno = -1;
175
176   /* We can place anything into GENERAL_REGS and can put GENERAL_REGS
177      into anything.  */
178   if (class == GENERAL_REGS || (regno >= 0 && regno < 8))
179     return NO_REGS;
180
181   /* Constants, memory, and FP registers can go into FP registers.  */
182   if ((regno == -1 || (regno >= 8 && regno < 16)) && (class == FLOAT_REGS))
183     return NO_REGS;
184
185 #if 0 /* This isn't strictly true (can't move fp to sp or vice versa),
186          so it's cleaner to use PREFERRED_RELOAD_CLASS
187          to make the right things happen.  */
188   if (regno >= 16 && class == GEN_AND_MEM_REGS)
189     return NO_REGS;
190 #endif
191
192   /* Otherwise, we need GENERAL_REGS. */
193   return GENERAL_REGS;
194 }
195 /* Generate the rtx that comes from an address expression in the md file */
196 /* The expression to be build is BASE[INDEX:SCALE].  To recognize this,
197    scale must be converted from an exponent (from ASHIFT) to a
198    multiplier (for MULT). */
199 rtx
200 gen_indexed_expr (base, index, scale)
201      rtx base, index, scale;
202 {
203   rtx addr;
204
205   /* This generates an illegal addressing mode, if BASE is
206      fp or sp.  This is handled by PRINT_OPERAND_ADDRESS.  */
207   if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT)
208     base = gen_rtx (MEM, SImode, base);
209   addr = gen_rtx (MULT, SImode, index,
210                   gen_rtx (CONST_INT, VOIDmode, 1 << INTVAL (scale)));
211   addr = gen_rtx (PLUS, SImode, base, addr);
212   return addr;
213 }
214
215 /* Return 1 if OP is a valid operand of mode MODE.  This
216    predicate rejects operands which do not have a mode
217    (such as CONST_INT which are VOIDmode).  */
218 int
219 reg_or_mem_operand (op, mode)
220      register rtx op;
221      enum machine_mode mode;
222 {
223   return (GET_MODE (op) == mode
224           && (GET_CODE (op) == REG
225               || GET_CODE (op) == SUBREG
226               || GET_CODE (op) == MEM));
227 }
228 \f
229 /* Return the best assembler insn template
230    for moving operands[1] into operands[0] as a fullword.  */
231
232 static char *
233 singlemove_string (operands)
234      rtx *operands;
235 {
236   if (GET_CODE (operands[1]) == CONST_INT
237       && INTVAL (operands[1]) <= 7
238       && INTVAL (operands[1]) >= -8)
239     return "movqd %1,%0";
240   return "movd %1,%0";
241 }
242
243 char *
244 output_move_double (operands)
245      rtx *operands;
246 {
247   enum anon1 { REGOP, OFFSOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
248   rtx latehalf[2];
249
250   /* First classify both operands.  */
251
252   if (REG_P (operands[0]))
253     optype0 = REGOP;
254   else if (offsettable_memref_p (operands[0]))
255     optype0 = OFFSOP;
256   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
257     optype0 = POPOP;
258   else
259     optype0 = RNDOP;
260
261   if (REG_P (operands[1]))
262     optype1 = REGOP;
263   else if (CONSTANT_ADDRESS_P (operands[1])
264            || GET_CODE (operands[1]) == CONST_DOUBLE)
265     optype1 = CNSTOP;
266   else if (offsettable_memref_p (operands[1]))
267     optype1 = OFFSOP;
268   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
269     optype1 = POPOP;
270   else
271     optype1 = RNDOP;
272
273   /* Check for the cases that the operand constraints are not
274      supposed to allow to happen.  Abort if we get one,
275      because generating code for these cases is painful.  */
276
277   if (optype0 == RNDOP || optype1 == RNDOP)
278     abort ();
279
280   /* Ok, we can do one word at a time.
281      Normally we do the low-numbered word first,
282      but if either operand is autodecrementing then we
283      do the high-numbered word first.
284
285      In either case, set up in LATEHALF the operands to use
286      for the high-numbered word and in some cases alter the
287      operands in OPERANDS to be suitable for the low-numbered word.  */
288
289   if (optype0 == REGOP)
290     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
291   else if (optype0 == OFFSOP)
292     latehalf[0] = adj_offsettable_operand (operands[0], 4);
293   else
294     latehalf[0] = operands[0];
295
296   if (optype1 == REGOP)
297     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
298   else if (optype1 == OFFSOP)
299     latehalf[1] = adj_offsettable_operand (operands[1], 4);
300   else if (optype1 == CNSTOP)
301     {
302       if (CONSTANT_ADDRESS_P (operands[1]))
303         latehalf[1] = const0_rtx;
304       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
305         split_double (operands[1], &operands[1], &latehalf[1]);
306     }
307   else
308     latehalf[1] = operands[1];
309
310   /* If one or both operands autodecrementing,
311      do the two words, high-numbered first.  */
312
313   if (optype0 == POPOP || optype1 == POPOP)
314     {
315       output_asm_insn (singlemove_string (latehalf), latehalf);
316       return singlemove_string (operands);
317     }
318
319   /* Not autodecrementing.  Do the two words, low-numbered first.  */
320
321   output_asm_insn (singlemove_string (operands), operands);
322
323   operands[0] = latehalf[0];
324   operands[1] = latehalf[1];
325   return singlemove_string (operands);
326 }
327
328 int
329 check_reg (oper, reg)
330      rtx oper;
331      int reg;
332 {
333   register int i;
334
335   if (oper == 0)
336     return 0;
337   switch (GET_CODE(oper))
338     {
339     case REG:
340       return (REGNO(oper) == reg) ? 1 : 0;
341     case MEM:
342       return check_reg(XEXP(oper, 0), reg);
343     case PLUS:
344     case MULT:
345       return check_reg(XEXP(oper, 0), reg) || check_reg(XEXP(oper, 1), reg);
346     }
347   return 0;
348 }
349 \f
350 /* PRINT_OPERAND is defined to call this function,
351    which is easier to debug than putting all the code in
352    a macro definition in ns32k.h.  */
353
354 void
355 print_operand (file, x, code)
356      FILE *file;
357      rtx x;
358      char code;
359 {
360   if (code == '$')
361     PUT_IMMEDIATE_PREFIX (file);
362   else if (code == '?')
363     PUT_EXTERNAL_PREFIX (file);
364   else if (GET_CODE (x) == REG)
365     fprintf (file, "%s", reg_names[REGNO (x)]);
366   else if (GET_CODE (x) == MEM)
367     {
368       rtx tmp = XEXP (x, 0);
369 #if ! (defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC))
370       if (GET_CODE (tmp) != CONST_INT)
371         {
372           char *out = XSTR (tmp, 0);
373           if (out[0] == '*')
374             {
375               PUT_ABSOLUTE_PREFIX (file);
376               fprintf (file, "%s", &out[1]);
377             }
378           else
379             ASM_OUTPUT_LABELREF (file, out);
380         }
381       else
382 #endif
383         output_address (XEXP (x, 0));
384     }
385   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != DImode)
386     {
387       if (GET_MODE (x) == DFmode)
388         { 
389           union { double d; int i[2]; } u;
390           u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
391           PUT_IMMEDIATE_PREFIX(file);
392 #ifdef SEQUENT_ASM
393           /* Sequent likes it's floating point constants as integers */
394           fprintf (file, "0Dx%08x%08x", u.i[1], u.i[0]);
395 #else
396 #ifdef ENCORE_ASM
397           fprintf (file, "0f%.20e", u.d); 
398 #else
399           fprintf (file, "0d%.20e", u.d); 
400 #endif
401 #endif
402         }
403       else
404         { 
405           union { double d; int i[2]; } u;
406           u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
407           PUT_IMMEDIATE_PREFIX (file);
408 #ifdef SEQUENT_ASM
409           /* We have no way of winning if we can't get the bits
410              for a sequent floating point number.  */
411 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
412           abort ();
413 #endif
414           {
415             union { float f; long l; } uu;
416             uu.f = u.d;
417             fprintf (file, "0Fx%08x", uu.l);
418           }
419 #else
420           fprintf (file, "0f%.20e", u.d); 
421 #endif
422         }
423     }
424   else
425     {
426 #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
427       if (GET_CODE (x) == CONST_INT)
428 #endif
429         PUT_IMMEDIATE_PREFIX (file);
430       output_addr_const (file, x);
431     }
432 }
433 \f
434 /* PRINT_OPERAND_ADDRESS is defined to call this function,
435    which is easier to debug than putting all the code in
436    a macro definition in ns32k.h .  */
437
438 /* Completely rewritten to get this to work with Gas for PC532 Mach.
439    This function didn't work and I just wasn't able (nor very willing) to
440    figure out how it worked.
441    90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */
442
443 print_operand_address (file, addr)
444      register FILE *file;
445      register rtx addr;
446 {
447   static char scales[] = { 'b', 'w', 'd', 0, 'q', };
448   rtx offset, base, indexexp, tmp;
449   int scale;
450
451   if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC)
452     {
453       fprintf (file, "tos");
454       return;
455     }
456
457   offset = NULL;
458   base = NULL;
459   indexexp = NULL;
460   while (addr != NULL)
461     {
462       if (GET_CODE (addr) == PLUS)
463         {
464           if (GET_CODE (XEXP (addr, 0)) == PLUS)
465             {
466               tmp = XEXP (addr, 1);
467               addr = XEXP (addr, 0);
468             }
469           else
470             {
471               tmp = XEXP (addr,0);
472               addr = XEXP (addr,1);
473             }
474         }
475       else
476         {
477           tmp = addr;
478           addr = NULL;
479         }
480       switch (GET_CODE (tmp))
481         {
482         case PLUS:
483           abort ();
484         case MEM:
485           if (base)
486             {
487               indexexp = base;
488               base = tmp;
489             }
490           else
491             base = tmp;
492           break;
493         case REG:
494           if (REGNO (tmp) < 8)
495             if (base)
496               {
497                 indexexp = tmp;
498               }
499             else
500               base = tmp;
501           else
502             if (base)
503               {
504                 indexexp = base;
505                 base = tmp;
506               }
507             else
508               base = tmp;
509           break;
510         case MULT:
511           indexexp = tmp;
512           break;
513         case CONST:
514         case CONST_INT:
515         case SYMBOL_REF:
516         case LABEL_REF:
517           if (offset)
518             offset = gen_rtx (PLUS, SImode, tmp, offset);
519           else
520             offset = tmp;
521           break;
522         default:
523           abort ();
524         }
525     }
526   if (! offset)
527     offset = const0_rtx;
528
529 #ifdef INDEX_RATHER_THAN_BASE
530   /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix.  */
531   if (base && !indexexp && GET_CODE (base) == REG
532       && REG_OK_FOR_INDEX_P (base))
533     {
534       indexexp = base;
535       base = 0;
536     }
537 #endif
538
539   /* now, offset, base and indexexp are set */
540   if (! base)
541     {
542 #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
543       if (GET_CODE (offset) == CONST_INT)
544 /*      if (! (GET_CODE (offset) == LABEL_REF
545              || GET_CODE (offset) == SYMBOL_REF)) */
546 #endif
547         PUT_ABSOLUTE_PREFIX (file);
548     }
549
550   output_addr_const (file, offset);
551   if (base) /* base can be (REG ...) or (MEM ...) */
552     switch (GET_CODE (base))
553       {
554         /* now we must output base.  Possible alternatives are:
555            (rN)       (REG ...)
556            (sp)       (REG ...)
557            (fp)       (REG ...)
558            (pc)       (REG ...)  used for SYMBOL_REF and LABEL_REF, output
559            (disp(fp)) (MEM ...)       just before possible [rX:y]
560            (disp(sp)) (MEM ...)
561            (disp(sb)) (MEM ...)
562            */
563       case REG:
564         fprintf (file, "(%s)", reg_names[REGNO (base)]);
565         break;
566       case MEM:
567         addr = XEXP(base,0);
568         base = NULL;
569         offset = NULL;
570         while (addr != NULL)
571           {
572             if (GET_CODE (addr) == PLUS)
573               {
574                 if (GET_CODE (XEXP (addr, 0)) == PLUS)
575                   {
576                     tmp = XEXP (addr, 1);
577                     addr = XEXP (addr, 0);
578                   }
579                 else
580                   {
581                     tmp = XEXP (addr, 0);
582                     addr = XEXP (addr, 1);
583                   }
584               }
585             else
586               {
587                 tmp = addr;
588                 addr = NULL;
589               }
590             switch (GET_CODE (tmp))
591               {
592               case REG:
593                 base = tmp;
594                 break;
595               case CONST:
596               case CONST_INT:
597               case SYMBOL_REF:
598               case LABEL_REF:
599                 if (offset)
600                   offset = gen_rtx (PLUS, SImode, tmp, offset);
601                 else
602                   offset = tmp;
603                 break;
604               default:
605                 abort ();
606               }
607           }
608         if (! offset)
609           offset = const0_rtx;
610         fprintf (file, "(");
611         output_addr_const (file, offset);
612         if (base)
613           fprintf (file, "(%s)", reg_names[REGNO (base)]);
614 #ifdef BASE_REG_NEEDED
615         else if (TARGET_SB)
616           fprintf (file, "(sb)");
617         else
618           abort ();
619 #endif
620         fprintf (file, ")");
621         break;
622
623       default:
624         abort ();
625       }
626 #ifdef PC_RELATIVE
627   else                          /* no base */
628     if (GET_CODE (offset) == LABEL_REF || GET_CODE (offset) == SYMBOL_REF)
629       fprintf (file, "(pc)");
630 #endif
631 #ifdef BASE_REG_NEEDED          /* this is defined if the assembler always
632                                    needs a base register */
633     else if (TARGET_SB)
634       fprintf (file, "(sb)");
635     else
636       abort ();
637 #endif
638   /* now print index if we have one */
639   if (indexexp)
640     {
641       if (GET_CODE (indexexp) == MULT)
642         {
643           scale = INTVAL (XEXP (indexexp, 1)) >> 1;
644           indexexp = XEXP (indexexp, 0);
645         }
646       else
647         scale = 0;
648       if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= 8)
649         abort ();
650
651 #ifdef UTEK_ASM
652       fprintf (file, "[%c`%s]",
653                scales[scale],
654                reg_names[REGNO (indexexp)]);
655 #else
656       fprintf (file, "[%s:%c]",
657                reg_names[REGNO (indexexp)],
658                scales[scale]);
659 #endif
660     }
661 }
662 \f
663 /* National 32032 shifting is so bad that we can get
664    better performance in many common cases by using other
665    techniques.  */
666 char *
667 output_shift_insn (operands)
668      rtx *operands;
669 {
670   if (GET_CODE (operands[2]) == CONST_INT
671       && INTVAL (operands[2]) > 0
672       && INTVAL (operands[2]) <= 3)
673     if (GET_CODE (operands[0]) == REG)
674       {
675         if (GET_CODE (operands[1]) == REG)
676           {
677             if (REGNO (operands[0]) == REGNO (operands[1]))
678               {
679                 if (operands[2] == const1_rtx)
680                   return "addd %0,%0";
681                 else if (INTVAL (operands[2]) == 2)
682                   return "addd %0,%0\n\taddd %0,%0";
683               }
684             if (operands[2] == const1_rtx)
685               return "movd %1,%0\n\taddd %0,%0";
686             
687             operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
688             return "addr %a1,%0";
689           }
690         if (operands[2] == const1_rtx)
691           return "movd %1,%0\n\taddd %0,%0";
692       }
693     else if (GET_CODE (operands[1]) == REG)
694       {
695         operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
696         return "addr %a1,%0";
697       }
698     else if (INTVAL (operands[2]) == 1
699              && GET_CODE (operands[1]) == MEM
700              && rtx_equal_p (operands [0], operands[1]))
701       {
702         rtx temp = XEXP (operands[1], 0);
703         
704         if (GET_CODE (temp) == REG
705             || (GET_CODE (temp) == PLUS
706                 && GET_CODE (XEXP (temp, 0)) == REG
707                 && GET_CODE (XEXP (temp, 1)) == CONST_INT))
708           return "addd %0,%0";
709       }
710     else return "ashd %2,%0";
711   return "ashd %2,%0";
712 }