OSDN Git Service

(output_move_double): Handle reg[n,n+1] = mem[reg[n] + reg[n+1]].
[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   /* If the first move would clobber the source of the second one,
320      do them in the other order.  */
321
322   /* Overlapping registers.  */
323   if (optype0 == REGOP && optype1 == REGOP
324       && REGNO (op0) == REGNO (latehalf[1]))
325     {
326       /* Do that word.  */
327       output_asm_insn (singlemove_string (latehalf), latehalf);
328       /* Do low-numbered word.  */
329       return singlemove_string (operands);
330     }
331   /* Loading into a register which overlaps a register used in the address.  */
332   else if (optype0 == REGOP && optype1 != REGOP
333            && reg_overlap_mentioned_p (op0, op1))
334     {
335       if (reg_mentioned_p (op0, XEXP (op1, 0))
336           && reg_mentioned_p (latehalf[0], XEXP (op1, 0)))
337         {
338           /* If both halves of dest are used in the src memory address,
339              add the two regs and put them in the low reg (op0).
340              Then it works to load latehalf first.  */
341           rtx xops[2];
342           xops[0] = latehalf[0];
343           xops[1] = op0;
344           output_asm_insn ("addd %0,%1", xops);
345           operands[1] = gen_rtx (MEM, DImode, op0);
346           latehalf[1] = adj_offsettable_operand (operands[1], 4);
347         }
348       /* Do the late half first.  */
349       output_asm_insn (singlemove_string (latehalf), latehalf);
350       /* Then clobber.  */
351       return singlemove_string (operands);
352     }
353
354   /* Normal case.  Do the two words, low-numbered first.  */
355
356   output_asm_insn (singlemove_string (operands), operands);
357
358   operands[0] = latehalf[0];
359   operands[1] = latehalf[1];
360   return singlemove_string (operands);
361 }
362
363 int
364 check_reg (oper, reg)
365      rtx oper;
366      int reg;
367 {
368   register int i;
369
370   if (oper == 0)
371     return 0;
372   switch (GET_CODE(oper))
373     {
374     case REG:
375       return (REGNO(oper) == reg) ? 1 : 0;
376     case MEM:
377       return check_reg(XEXP(oper, 0), reg);
378     case PLUS:
379     case MULT:
380       return check_reg(XEXP(oper, 0), reg) || check_reg(XEXP(oper, 1), reg);
381     }
382   return 0;
383 }
384 \f
385 /* PRINT_OPERAND is defined to call this function,
386    which is easier to debug than putting all the code in
387    a macro definition in ns32k.h.  */
388
389 void
390 print_operand (file, x, code)
391      FILE *file;
392      rtx x;
393      char code;
394 {
395   if (code == '$')
396     PUT_IMMEDIATE_PREFIX (file);
397   else if (code == '?')
398     PUT_EXTERNAL_PREFIX (file);
399   else if (GET_CODE (x) == REG)
400     fprintf (file, "%s", reg_names[REGNO (x)]);
401   else if (GET_CODE (x) == MEM)
402     {
403       rtx tmp = XEXP (x, 0);
404 #if ! (defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC))
405       if (GET_CODE (tmp) != CONST_INT)
406         {
407           char *out = XSTR (tmp, 0);
408           if (out[0] == '*')
409             {
410               PUT_ABSOLUTE_PREFIX (file);
411               fprintf (file, "%s", &out[1]);
412             }
413           else
414             ASM_OUTPUT_LABELREF (file, out);
415         }
416       else
417 #endif
418         output_address (XEXP (x, 0));
419     }
420   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != DImode)
421     {
422       if (GET_MODE (x) == DFmode)
423         { 
424           union { double d; int i[2]; } u;
425           u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
426           PUT_IMMEDIATE_PREFIX(file);
427 #ifdef SEQUENT_ASM
428           /* Sequent likes it's floating point constants as integers */
429           fprintf (file, "0Dx%08x%08x", u.i[1], u.i[0]);
430 #else
431 #ifdef ENCORE_ASM
432           fprintf (file, "0f%.20e", u.d); 
433 #else
434           fprintf (file, "0d%.20e", u.d); 
435 #endif
436 #endif
437         }
438       else
439         { 
440           union { double d; int i[2]; } u;
441           u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
442           PUT_IMMEDIATE_PREFIX (file);
443 #ifdef SEQUENT_ASM
444           /* We have no way of winning if we can't get the bits
445              for a sequent floating point number.  */
446 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
447           abort ();
448 #endif
449           {
450             union { float f; long l; } uu;
451             uu.f = u.d;
452             fprintf (file, "0Fx%08x", uu.l);
453           }
454 #else
455           fprintf (file, "0f%.20e", u.d); 
456 #endif
457         }
458     }
459   else
460     {
461 #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
462       if (GET_CODE (x) == CONST_INT)
463 #endif
464         PUT_IMMEDIATE_PREFIX (file);
465       output_addr_const (file, x);
466     }
467 }
468 \f
469 /* PRINT_OPERAND_ADDRESS is defined to call this function,
470    which is easier to debug than putting all the code in
471    a macro definition in ns32k.h .  */
472
473 /* Completely rewritten to get this to work with Gas for PC532 Mach.
474    This function didn't work and I just wasn't able (nor very willing) to
475    figure out how it worked.
476    90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */
477
478 print_operand_address (file, addr)
479      register FILE *file;
480      register rtx addr;
481 {
482   static char scales[] = { 'b', 'w', 'd', 0, 'q', };
483   rtx offset, base, indexexp, tmp;
484   int scale;
485
486   if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC)
487     {
488       fprintf (file, "tos");
489       return;
490     }
491
492   offset = NULL;
493   base = NULL;
494   indexexp = NULL;
495   while (addr != NULL)
496     {
497       if (GET_CODE (addr) == PLUS)
498         {
499           if (GET_CODE (XEXP (addr, 0)) == PLUS)
500             {
501               tmp = XEXP (addr, 1);
502               addr = XEXP (addr, 0);
503             }
504           else
505             {
506               tmp = XEXP (addr,0);
507               addr = XEXP (addr,1);
508             }
509         }
510       else
511         {
512           tmp = addr;
513           addr = NULL;
514         }
515       switch (GET_CODE (tmp))
516         {
517         case PLUS:
518           abort ();
519         case MEM:
520           if (base)
521             {
522               indexexp = base;
523               base = tmp;
524             }
525           else
526             base = tmp;
527           break;
528         case REG:
529           if (REGNO (tmp) < 8)
530             if (base)
531               {
532                 indexexp = tmp;
533               }
534             else
535               base = tmp;
536           else
537             if (base)
538               {
539                 indexexp = base;
540                 base = tmp;
541               }
542             else
543               base = tmp;
544           break;
545         case MULT:
546           indexexp = tmp;
547           break;
548         case CONST:
549         case CONST_INT:
550         case SYMBOL_REF:
551         case LABEL_REF:
552           if (offset)
553             offset = gen_rtx (PLUS, SImode, tmp, offset);
554           else
555             offset = tmp;
556           break;
557         default:
558           abort ();
559         }
560     }
561   if (! offset)
562     offset = const0_rtx;
563
564 #ifdef INDEX_RATHER_THAN_BASE
565   /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix.  */
566   if (base && !indexexp && GET_CODE (base) == REG
567       && REG_OK_FOR_INDEX_P (base))
568     {
569       indexexp = base;
570       base = 0;
571     }
572 #endif
573
574   /* now, offset, base and indexexp are set */
575   if (! base)
576     {
577 #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
578       if (GET_CODE (offset) == CONST_INT)
579 /*      if (! (GET_CODE (offset) == LABEL_REF
580              || GET_CODE (offset) == SYMBOL_REF)) */
581 #endif
582         PUT_ABSOLUTE_PREFIX (file);
583     }
584
585   output_addr_const (file, offset);
586   if (base) /* base can be (REG ...) or (MEM ...) */
587     switch (GET_CODE (base))
588       {
589         /* now we must output base.  Possible alternatives are:
590            (rN)       (REG ...)
591            (sp)       (REG ...)
592            (fp)       (REG ...)
593            (pc)       (REG ...)  used for SYMBOL_REF and LABEL_REF, output
594            (disp(fp)) (MEM ...)       just before possible [rX:y]
595            (disp(sp)) (MEM ...)
596            (disp(sb)) (MEM ...)
597            */
598       case REG:
599         fprintf (file, "(%s)", reg_names[REGNO (base)]);
600         break;
601       case MEM:
602         addr = XEXP(base,0);
603         base = NULL;
604         offset = NULL;
605         while (addr != NULL)
606           {
607             if (GET_CODE (addr) == PLUS)
608               {
609                 if (GET_CODE (XEXP (addr, 0)) == PLUS)
610                   {
611                     tmp = XEXP (addr, 1);
612                     addr = XEXP (addr, 0);
613                   }
614                 else
615                   {
616                     tmp = XEXP (addr, 0);
617                     addr = XEXP (addr, 1);
618                   }
619               }
620             else
621               {
622                 tmp = addr;
623                 addr = NULL;
624               }
625             switch (GET_CODE (tmp))
626               {
627               case REG:
628                 base = tmp;
629                 break;
630               case CONST:
631               case CONST_INT:
632               case SYMBOL_REF:
633               case LABEL_REF:
634                 if (offset)
635                   offset = gen_rtx (PLUS, SImode, tmp, offset);
636                 else
637                   offset = tmp;
638                 break;
639               default:
640                 abort ();
641               }
642           }
643         if (! offset)
644           offset = const0_rtx;
645         fprintf (file, "(");
646         output_addr_const (file, offset);
647         if (base)
648           fprintf (file, "(%s)", reg_names[REGNO (base)]);
649 #ifdef BASE_REG_NEEDED
650         else if (TARGET_SB)
651           fprintf (file, "(sb)");
652         else
653           abort ();
654 #endif
655         fprintf (file, ")");
656         break;
657
658       default:
659         abort ();
660       }
661 #ifdef PC_RELATIVE
662   else                          /* no base */
663     if (GET_CODE (offset) == LABEL_REF || GET_CODE (offset) == SYMBOL_REF)
664       fprintf (file, "(pc)");
665 #endif
666 #ifdef BASE_REG_NEEDED          /* this is defined if the assembler always
667                                    needs a base register */
668     else if (TARGET_SB)
669       fprintf (file, "(sb)");
670     else
671       abort ();
672 #endif
673   /* now print index if we have one */
674   if (indexexp)
675     {
676       if (GET_CODE (indexexp) == MULT)
677         {
678           scale = INTVAL (XEXP (indexexp, 1)) >> 1;
679           indexexp = XEXP (indexexp, 0);
680         }
681       else
682         scale = 0;
683       if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= 8)
684         abort ();
685
686 #ifdef UTEK_ASM
687       fprintf (file, "[%c`%s]",
688                scales[scale],
689                reg_names[REGNO (indexexp)]);
690 #else
691       fprintf (file, "[%s:%c]",
692                reg_names[REGNO (indexexp)],
693                scales[scale]);
694 #endif
695     }
696 }
697 \f
698 /* National 32032 shifting is so bad that we can get
699    better performance in many common cases by using other
700    techniques.  */
701 char *
702 output_shift_insn (operands)
703      rtx *operands;
704 {
705   if (GET_CODE (operands[2]) == CONST_INT
706       && INTVAL (operands[2]) > 0
707       && INTVAL (operands[2]) <= 3)
708     if (GET_CODE (operands[0]) == REG)
709       {
710         if (GET_CODE (operands[1]) == REG)
711           {
712             if (REGNO (operands[0]) == REGNO (operands[1]))
713               {
714                 if (operands[2] == const1_rtx)
715                   return "addd %0,%0";
716                 else if (INTVAL (operands[2]) == 2)
717                   return "addd %0,%0\n\taddd %0,%0";
718               }
719             if (operands[2] == const1_rtx)
720               return "movd %1,%0\n\taddd %0,%0";
721             
722             operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
723             return "addr %a1,%0";
724           }
725         if (operands[2] == const1_rtx)
726           return "movd %1,%0\n\taddd %0,%0";
727       }
728     else if (GET_CODE (operands[1]) == REG)
729       {
730         operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
731         return "addr %a1,%0";
732       }
733     else if (INTVAL (operands[2]) == 1
734              && GET_CODE (operands[1]) == MEM
735              && rtx_equal_p (operands [0], operands[1]))
736       {
737         rtx temp = XEXP (operands[1], 0);
738         
739         if (GET_CODE (temp) == REG
740             || (GET_CODE (temp) == PLUS
741                 && GET_CODE (XEXP (temp, 0)) == REG
742                 && GET_CODE (XEXP (temp, 1)) == CONST_INT))
743           return "addd %0,%0";
744       }
745     else return "ashd %2,%0";
746   return "ashd %2,%0";
747 }