OSDN Git Service

* Makefile.in (TARGET_H, TARGET_DEF_H): New.
[pf3gnuchains/gcc-fork.git] / gcc / config / ns32k / ns32k.c
1 /* Subroutines for assembler code output on the NS32000.
2    Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000
3    Free Software Foundation, Inc.
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "rtl.h"
25 #include "regs.h"
26 #include "hard-reg-set.h"
27 #include "real.h"
28 #include "insn-config.h"
29 #include "conditions.h"
30 #include "output.h"
31 #include "insn-attr.h"
32 #include "tree.h"
33 #include "function.h"
34 #include "expr.h"
35 #include "flags.h"
36 #include "recog.h"
37 #include "tm_p.h"
38 #include "target.h"
39 #include "target-def.h"
40
41 #ifdef OSF_OS
42 int ns32k_num_files = 0;
43 #endif
44
45 /* This duplicates reg_class_contents in reg_class.c, but maybe that isn't
46    initialized in time. Also this is more convenient as an array of ints.
47    We know that HARD_REG_SET fits in an unsigned int */
48
49 unsigned int ns32k_reg_class_contents[N_REG_CLASSES][1] = REG_CLASS_CONTENTS;
50
51 enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
52 {
53   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
54   GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
55   FLOAT_REG0, LONG_FLOAT_REG0, FLOAT_REGS, FLOAT_REGS,
56   FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,
57   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
58   FP_REGS, FP_REGS, FP_REGS, FP_REGS,
59   FRAME_POINTER_REG, STACK_POINTER_REG
60 };
61
62 const char *const ns32k_out_reg_names[] = OUTPUT_REGISTER_NAMES;
63
64 static rtx gen_indexed_expr PARAMS ((rtx, rtx, rtx));
65 static const char *singlemove_string PARAMS ((rtx *));
66 static void move_tail PARAMS ((rtx[], int, int));
67 static int ns32k_valid_type_attribute_p PARAMS ((tree, tree, tree, tree));
68 \f
69 /* Initialize the GCC target structure.  */
70 #undef TARGET_VALID_TYPE_ATTRIBUTE
71 #define TARGET_VALID_TYPE_ATTRIBUTE ns32k_valid_type_attribute_p
72
73 struct gcc_target target = TARGET_INITIALIZER;
74 \f
75 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ 
76 int
77 hard_regno_mode_ok (regno, mode)
78      int regno;
79      enum machine_mode mode;
80 {
81   int size = GET_MODE_UNIT_SIZE (mode);
82
83   if (FLOAT_MODE_P (mode))
84     {
85       if (size == UNITS_PER_WORD && regno < L1_REGNUM)
86         return 1;
87       if (size == UNITS_PER_WORD * 2
88           && (((regno & 1) == 0 && regno < FRAME_POINTER_REGNUM)))
89         return 1;
90       return 0;
91     }
92   if (size == UNITS_PER_WORD * 2
93       && (regno & 1) == 0 && regno < F0_REGNUM)
94     return 1;
95   if (size <= UNITS_PER_WORD
96       && (regno < F0_REGNUM || regno == FRAME_POINTER_REGNUM
97           || regno == STACK_POINTER_REGNUM))
98     return 1;
99   return 0;
100 }
101
102 int register_move_cost (CLASS1, CLASS2)
103      enum reg_class CLASS1;
104      enum reg_class CLASS2;
105 {
106   if (CLASS1 == NO_REGS || CLASS2 == NO_REGS)
107     return 2;
108   if ((SUBSET_P (CLASS1, FP_REGS) && !SUBSET_P (CLASS2, FP_REGS))
109    || (!SUBSET_P (CLASS1, FP_REGS) && SUBSET_P (CLASS2, FP_REGS)))
110     return 8;
111   if (((CLASS1) == STACK_POINTER_REG && !SUBSET_P (CLASS2,GENERAL_REGS))
112       || ((CLASS2) == STACK_POINTER_REG && !SUBSET_P (CLASS1,GENERAL_REGS)))
113     return 6;
114   if (((CLASS1) == FRAME_POINTER_REG && !SUBSET_P (CLASS2,GENERAL_REGS))
115       || ((CLASS2) == FRAME_POINTER_REG && !SUBSET_P (CLASS1,GENERAL_REGS)))
116     return 6;
117   return 2;
118 }
119
120 #if 0
121 /* We made the insn definitions copy from floating point to general
122   registers via the stack. */
123 int secondary_memory_needed (CLASS1, CLASS2, M)
124      enum reg_class CLASS1;
125      enum reg_class CLASS2;
126      enum machine_mode M;
127 {
128   int ret = ((SUBSET_P (CLASS1, FP_REGS) && !SUBSET_P (CLASS2, FP_REGS))
129    || (!SUBSET_P (CLASS1, FP_REGS) && SUBSET_P (CLASS2, FP_REGS)));
130   return ret;
131 }
132 #endif
133     
134
135 /* ADDRESS_COST calls this.  This function is not optimal
136    for the 32032 & 32332, but it probably is better than
137    the default. */
138
139 int
140 calc_address_cost (operand)
141      rtx operand;
142 {
143   int i;
144   int cost = 0;
145   if (GET_CODE (operand) == MEM)
146     cost += 3;
147   if (GET_CODE (operand) == MULT)
148     cost += 2;
149   switch (GET_CODE (operand))
150     {
151     case REG:
152       cost += 1;
153       break;
154     case POST_DEC:
155     case PRE_DEC:
156       break;
157     case CONST_INT:
158       if (INTVAL (operand) <= 7 && INTVAL (operand) >= -8)
159         break;
160       if (INTVAL (operand) < 0x2000 && INTVAL (operand) >= -0x2000)
161         {
162           cost +=1;
163           break;
164         }
165     case CONST:
166     case LABEL_REF:
167     case SYMBOL_REF:
168       cost +=3;
169       break;
170     case CONST_DOUBLE:
171       cost += 5;
172       break;
173     case MEM:
174       cost += calc_address_cost (XEXP (operand, 0));
175       break;
176     case MULT:
177     case PLUS:
178       for (i = 0; i < GET_RTX_LENGTH (GET_CODE (operand)); i++)
179         {
180           cost += calc_address_cost (XEXP (operand, i));
181         }
182     default:
183       break;
184     }
185   return cost;
186 }
187
188 /* Return the register class of a scratch register needed to copy IN into
189    or out of a register in CLASS in MODE.  If it can be done directly,
190    NO_REGS is returned.  */
191
192 enum reg_class
193 secondary_reload_class (class, mode, in)
194      enum reg_class class;
195      enum machine_mode mode ATTRIBUTE_UNUSED;
196      rtx in;
197 {
198   int regno = true_regnum (in);
199
200   if (regno >= FIRST_PSEUDO_REGISTER)
201     regno = -1;
202
203   if ((class == FRAME_POINTER_REG && regno == STACK_POINTER_REGNUM)
204       || ( class == STACK_POINTER_REG && regno == FRAME_POINTER_REGNUM))
205     return GENERAL_REGS;
206   else
207     return NO_REGS;
208 }
209
210 /* Generate the rtx that comes from an address expression in the md file */
211 /* The expression to be build is BASE[INDEX:SCALE].  To recognize this,
212    scale must be converted from an exponent (from ASHIFT) to a
213    multiplier (for MULT). */
214
215 static rtx
216 gen_indexed_expr (base, index, scale)
217      rtx base, index, scale;
218 {
219   rtx addr;
220
221   /* This generates an invalid addressing mode, if BASE is
222      fp or sp.  This is handled by PRINT_OPERAND_ADDRESS.  */
223   if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT)
224     base = gen_rtx_MEM (SImode, base);
225   addr = gen_rtx_MULT (SImode, index,
226                        GEN_INT (1 << INTVAL (scale)));
227   addr = gen_rtx_PLUS (SImode, base, addr);
228   return addr;
229 }
230
231 \f
232 /* Split one or more DImode RTL references into pairs of SImode
233    references.  The RTL can be REG, offsettable MEM, integer constant, or
234    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
235    split and "num" is its length.  lo_half and hi_half are output arrays
236    that parallel "operands". */
237
238 void
239 split_di (operands, num, lo_half, hi_half)
240      rtx operands[];
241      int num;
242      rtx lo_half[], hi_half[];
243 {
244   while (num--)
245     {
246       if (GET_CODE (operands[num]) == REG)
247         {
248           lo_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]));
249           hi_half[num] = gen_rtx_REG (SImode, REGNO (operands[num]) + 1);
250         }
251       else if (CONSTANT_P (operands[num]))
252         {
253           split_double (operands[num], &lo_half[num], &hi_half[num]);
254         }
255       else if (offsettable_memref_p (operands[num]))
256         {
257           lo_half[num] = operands[num];
258           hi_half[num] = adj_offsettable_operand (operands[num], 4);
259         }
260       else
261         abort ();
262     }
263 }
264 \f
265 /* Return the best assembler insn template
266    for moving operands[1] into operands[0] as a fullword.  */
267
268 static const char *
269 singlemove_string (operands)
270      rtx *operands;
271 {
272   if (GET_CODE (operands[1]) == CONST_INT
273       && INTVAL (operands[1]) <= 7
274       && INTVAL (operands[1]) >= -8)
275     return "movqd %1,%0";
276   return "movd %1,%0";
277 }
278
279 const char *
280 output_move_double (operands)
281      rtx *operands;
282 {
283   enum anon1 { REGOP, OFFSOP, PUSHOP, CNSTOP, RNDOP } optype0, optype1;
284   rtx latehalf[2];
285
286   /* First classify both operands.  */
287
288   if (REG_P (operands[0]))
289     optype0 = REGOP;
290   else if (offsettable_memref_p (operands[0]))
291     optype0 = OFFSOP;
292   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
293     optype0 = PUSHOP;
294   else
295     optype0 = RNDOP;
296
297   if (REG_P (operands[1]))
298     optype1 = REGOP;
299   else if (CONSTANT_P (operands[1])
300            || GET_CODE (operands[1]) == CONST_DOUBLE)
301     optype1 = CNSTOP;
302   else if (offsettable_memref_p (operands[1]))
303     optype1 = OFFSOP;
304   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
305     optype1 = PUSHOP;
306   else
307     optype1 = RNDOP;
308
309   /* Check for the cases that the operand constraints are not
310      supposed to allow to happen.  Abort if we get one,
311      because generating code for these cases is painful.  */
312
313   if (optype0 == RNDOP || optype1 == RNDOP)
314     abort ();
315
316   /* Ok, we can do one word at a time.
317      Normally we do the low-numbered word first,
318      but if either operand is autodecrementing then we
319      do the high-numbered word first.
320
321      In either case, set up in LATEHALF the operands to use
322      for the high-numbered word and in some cases alter the
323      operands in OPERANDS to be suitable for the low-numbered word.  */
324
325   if (optype0 == REGOP)
326     latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
327   else if (optype0 == OFFSOP)
328     latehalf[0] = adj_offsettable_operand (operands[0], 4);
329   else
330     latehalf[0] = operands[0];
331
332   if (optype1 == REGOP)
333     latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
334   else if (optype1 == OFFSOP)
335     latehalf[1] = adj_offsettable_operand (operands[1], 4);
336   else if (optype1 == CNSTOP)
337     split_double (operands[1], &operands[1], &latehalf[1]);
338   else
339     latehalf[1] = operands[1];
340
341   /* If insn is effectively movd N(sp),tos then we will do the
342      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
343      for the low word as well, to compensate for the first decrement of sp.
344      Given this, it doesn't matter which half we do "first".  */
345   if (optype0 == PUSHOP
346       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
347       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
348     operands[1] = latehalf[1];
349
350   /* If one or both operands autodecrementing,
351      do the two words, high-numbered first.  */
352   else if (optype0 == PUSHOP || optype1 == PUSHOP)
353     {
354       output_asm_insn (singlemove_string (latehalf), latehalf);
355       return singlemove_string (operands);
356     }
357
358   /* If the first move would clobber the source of the second one,
359      do them in the other order.  */
360
361   /* Overlapping registers.  */
362   if (optype0 == REGOP && optype1 == REGOP
363       && REGNO (operands[0]) == REGNO (latehalf[1]))
364     {
365       /* Do that word.  */
366       output_asm_insn (singlemove_string (latehalf), latehalf);
367       /* Do low-numbered word.  */
368       return singlemove_string (operands);
369     }
370   /* Loading into a register which overlaps a register used in the address.  */
371   else if (optype0 == REGOP && optype1 != REGOP
372            && reg_overlap_mentioned_p (operands[0], operands[1]))
373     {
374       if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
375           && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
376         {
377           /* If both halves of dest are used in the src memory address,
378              load the destination address into the low reg (operands[0]).
379              Then it works to load latehalf first.  */
380           rtx xops[2];
381           xops[0] = XEXP (operands[1], 0);
382           xops[1] = operands[0];
383           output_asm_insn ("addr %a0,%1", xops);
384           operands[1] = gen_rtx_MEM (DImode, operands[0]);
385           latehalf[1] = adj_offsettable_operand (operands[1], 4);
386           /* The first half has the overlap, Do the late half first.  */
387           output_asm_insn (singlemove_string (latehalf), latehalf);
388           /* Then clobber.  */
389           return singlemove_string (operands);
390         }
391       if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)))
392         {
393           /* The first half has the overlap, Do the late half first.  */
394           output_asm_insn (singlemove_string (latehalf), latehalf);
395           /* Then clobber.  */
396           return singlemove_string (operands);
397         }
398     }
399
400   /* Normal case.  Do the two words, low-numbered first.  */
401
402   output_asm_insn (singlemove_string (operands), operands);
403
404   operands[0] = latehalf[0];
405   operands[1] = latehalf[1];
406   return singlemove_string (operands);
407 }
408
409 \f
410 #define MAX_UNALIGNED_COPY (32)
411 /* Expand string/block move operations.
412
413    operands[0] is the pointer to the destination.
414    operands[1] is the pointer to the source.
415    operands[2] is the number of bytes to move.
416    operands[3] is the alignment.  */
417
418 static void
419 move_tail (operands, bytes, offset)
420      rtx operands[];
421      int bytes;
422      int offset;
423 {
424   if (bytes & 2)
425     {
426       rtx src, dest;
427       dest = change_address (operands[0], HImode,
428                             plus_constant (XEXP (operands[0], 0), offset));
429       src = change_address (operands[1], HImode,
430                            plus_constant (XEXP (operands[1], 0), offset));
431       emit_move_insn (dest, src);
432       offset += 2;
433     }
434   if (bytes & 1)
435     {
436       rtx src, dest;
437       dest = change_address (operands[0], QImode,
438                             plus_constant (XEXP (operands[0], 0), offset));
439       src = change_address (operands[1], QImode,
440                            plus_constant (XEXP (operands[1], 0), offset));
441       emit_move_insn (dest, src);
442     }
443 }
444
445 void
446 expand_block_move (operands)
447      rtx operands[];
448 {
449   rtx bytes_rtx = operands[2];
450   rtx align_rtx = operands[3];
451   int constp    = (GET_CODE (bytes_rtx) == CONST_INT);
452   int bytes     = (constp ? INTVAL (bytes_rtx) : 0);
453   int align     = INTVAL (align_rtx);
454   rtx src_reg = gen_rtx_REG (Pmode, 1);
455   rtx dest_reg = gen_rtx_REG (Pmode, 2);
456   rtx count_reg = gen_rtx_REG (SImode, 0);
457
458   if (constp && bytes <= 0)
459     return;
460
461   if (constp && bytes < 20)
462     {
463       int words = bytes >> 2;
464       if (words)
465         {
466           if (words < 3 || flag_unroll_loops)
467             {
468               int offset = 0;
469               for (; words; words--, offset += 4)
470                 {
471                   rtx src, dest;
472                   dest = change_address (operands[0], SImode,
473                                         plus_constant (XEXP (operands[0], 0), offset));
474                   src = change_address (operands[1], SImode,
475                                        plus_constant (XEXP (operands[1], 0), offset));
476                   emit_move_insn (dest, src);
477                 }
478             }
479           else
480             {
481               /* Use movmd. It is slower than multiple movd's but more
482                  compact. It is also slower than movsd for large copies
483                  but causes less registers reloading so is better than movsd
484                  for small copies. */
485               rtx src, dest;
486               dest = copy_addr_to_reg (XEXP (operands[0], 0));
487               src = copy_addr_to_reg (XEXP (operands[1], 0));
488             
489               emit_insn (gen_movstrsi2(dest, src, GEN_INT (words)));
490             }
491         }
492       move_tail (operands, bytes & 3, bytes & ~3);
493       return;
494     }
495
496   if (align > UNITS_PER_WORD)
497     align = UNITS_PER_WORD;
498
499   /* Move the address into scratch registers.  */
500   emit_insn (gen_rtx_CLOBBER (VOIDmode, dest_reg));
501   emit_move_insn (dest_reg, XEXP (operands[0], 0));
502   operands[0] = gen_rtx_MEM (SImode, dest_reg);
503   emit_insn (gen_rtx_CLOBBER (VOIDmode, src_reg));
504   emit_move_insn (src_reg, XEXP (operands[1], 0));
505   operands[1] = gen_rtx_MEM (SImode, src_reg);
506   emit_insn (gen_rtx_CLOBBER (VOIDmode, count_reg));
507
508   if (constp && (align == UNITS_PER_WORD || bytes < MAX_UNALIGNED_COPY))
509     {
510       /* constant no of bytes and aligned or small enough copy to not bother
511        * aligning. Emit insns to copy by words.
512        */
513       if (bytes >> 2)
514         {
515           emit_move_insn (count_reg, GEN_INT (bytes >> 2));
516           emit_insn (gen_movstrsi1 (GEN_INT (4)));
517         }
518       /* insns to copy rest */
519       move_tail (operands, bytes & 3, 0);
520     }
521   else if (align == UNITS_PER_WORD)
522     {
523       /* insns to copy by words */
524       emit_insn (gen_lshrsi3 (count_reg, bytes_rtx, GEN_INT (2)));
525       emit_insn (gen_movstrsi1 (GEN_INT (4)));
526       if (constp)
527         {
528           move_tail (operands, bytes & 3, 0);
529         }
530       else
531         {
532           /* insns to copy rest */
533           emit_insn (gen_andsi3 (count_reg, bytes_rtx, GEN_INT (3)));
534           emit_insn (gen_movstrsi1 (const1_rtx));
535         }
536     }
537   else
538     {
539       /* Not aligned and we may have a lot to copy so it is worth
540        * aligning.
541        */
542       rtx aligned_label = gen_label_rtx ();
543       rtx bytes_reg;
544
545       bytes_reg = copy_to_mode_reg (SImode, bytes_rtx);
546       if (!constp)
547         {
548           /* Emit insns to test and skip over the alignment if it is
549            * not worth it. This doubles as a test to ensure that the alignment
550            * operation can't copy too many bytes
551            */
552           emit_insn (gen_cmpsi (bytes_reg, GEN_INT (MAX_UNALIGNED_COPY)));
553           emit_jump_insn (gen_blt (aligned_label));
554         }
555
556       /* Emit insns to do alignment at run time */
557       emit_insn (gen_negsi2 (count_reg, src_reg));
558       emit_insn (gen_andsi3 (count_reg, count_reg, GEN_INT (3)));
559       emit_insn (gen_subsi3 (bytes_reg, bytes_reg, count_reg));
560       emit_insn (gen_movstrsi1 (const1_rtx));
561       if (!constp)
562         emit_label (aligned_label);
563
564       /* insns to copy by words */
565       emit_insn (gen_lshrsi3 (count_reg, bytes_reg, GEN_INT (2)));
566       emit_insn (gen_movstrsi1 (GEN_INT (4)));
567
568       /* insns to copy rest */
569       emit_insn (gen_andsi3 (count_reg, bytes_reg, GEN_INT (3)));
570       emit_insn (gen_movstrsi1 (const1_rtx));
571     }
572 }
573 \f
574
575 /* Returns 1 if OP contains a global symbol reference */
576
577 int
578 global_symbolic_reference_mentioned_p (op, f)
579      rtx op;
580      int f;
581 {
582   register const char *fmt;
583   register int i;
584
585   if (GET_CODE (op) == SYMBOL_REF)
586     {
587       if (! SYMBOL_REF_FLAG (op))
588         return 1;
589       else
590         return 0;
591     }
592   else if (f && GET_CODE (op) != CONST)
593     return 0;
594
595   fmt = GET_RTX_FORMAT (GET_CODE (op));
596   for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
597     {
598       if (fmt[i] == 'E')
599         {
600           register int j;
601
602           for (j = XVECLEN (op, i) - 1; j >= 0; j--)
603             if (global_symbolic_reference_mentioned_p (XVECEXP (op, i, j), 0))
604               return 1;
605         }
606       else if (fmt[i] == 'e' 
607                && global_symbolic_reference_mentioned_p (XEXP (op, i), 0))
608         return 1;
609     }
610
611   return 0;
612 }
613
614 \f
615 /* Returns 1 if OP contains a symbol reference */
616
617 int
618 symbolic_reference_mentioned_p (op)
619      rtx op;
620 {
621   register const char *fmt;
622   register int i;
623
624   if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
625     return 1;
626
627   fmt = GET_RTX_FORMAT (GET_CODE (op));
628   for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
629     {
630       if (fmt[i] == 'E')
631         {
632           register int j;
633
634           for (j = XVECLEN (op, i) - 1; j >= 0; j--)
635             if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
636               return 1;
637         }
638       else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
639         return 1;
640     }
641
642   return 0;
643 }
644 \f
645 /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
646    attribute for TYPE.  The attributes in ATTRIBUTES have previously been
647    assigned to TYPE.  */
648
649 static int
650 ns32k_valid_type_attribute_p (type, attributes, identifier, args)
651      tree type;
652      tree attributes ATTRIBUTE_UNUSED;
653      tree identifier;
654      tree args;
655 {
656   if (TREE_CODE (type) != FUNCTION_TYPE
657       && TREE_CODE (type) != FIELD_DECL
658       && TREE_CODE (type) != TYPE_DECL)
659     return 0;
660
661   /* Stdcall attribute says callee is responsible for popping arguments
662      if they are not variable.  */
663   if (is_attribute_p ("stdcall", identifier))
664     return (args == NULL_TREE);
665
666   /* Cdecl attribute says the callee is a normal C declaration */
667   if (is_attribute_p ("cdecl", identifier))
668     return (args == NULL_TREE);
669
670   return 0;
671 }
672
673 /* Return 0 if the attributes for two types are incompatible, 1 if they
674    are compatible, and 2 if they are nearly compatible (which causes a
675    warning to be generated).  */
676
677 int
678 ns32k_comp_type_attributes (type1, type2)
679      tree type1 ATTRIBUTE_UNUSED;
680      tree type2 ATTRIBUTE_UNUSED;
681 {
682   return 1;
683 }
684
685 \f
686 /* Value is the number of bytes of arguments automatically
687    popped when returning from a subroutine call.
688    FUNDECL is the declaration node of the function (as a tree),
689    FUNTYPE is the data type of the function (as a tree),
690    or for a library call it is an identifier node for the subroutine name.
691    SIZE is the number of bytes of arguments passed on the stack.
692
693    On the ns32k, the RET insn may be used to pop them if the number
694      of args is fixed, but if the number is variable then the caller
695      must pop them all.  RET can't be used for library calls now
696      because the library is compiled with the Unix compiler.
697    Use of RET is a selectable option, since it is incompatible with
698    standard Unix calling sequences.  If the option is not selected,
699    the caller must always pop the args.
700
701    The attribute stdcall is equivalent to RET on a per module basis.  */
702
703 int
704 ns32k_return_pops_args (fundecl, funtype, size)
705      tree fundecl ATTRIBUTE_UNUSED;
706      tree funtype;
707      int size;
708 {
709   int rtd = TARGET_RTD;
710
711   if (TREE_CODE (funtype) == IDENTIFIER_NODE)
712     return rtd ? size : 0;
713
714   /* Cdecl functions override -mrtd, and never pop the stack */
715   if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
716     return 0;
717
718   /* Stdcall functions will pop the stack if not variable args */
719   if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype)))
720     rtd = 1;
721
722   if (rtd)
723     {
724       if (TYPE_ARG_TYPES (funtype) == NULL_TREE
725           || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node))
726         return size;
727     }
728
729   return 0;
730 }
731 \f
732 /* PRINT_OPERAND is defined to call this function,
733    which is easier to debug than putting all the code in
734    a macro definition in ns32k.h.  */
735
736 /* XXX time 12% of cpu time is in fprintf for non optimizing */
737 void
738 print_operand (file, x, code)
739      FILE *file;
740      rtx x;
741      int code;
742 {
743   if (code == '$')
744     PUT_IMMEDIATE_PREFIX (file);
745   else if (code == '?')
746     PUT_EXTERNAL_PREFIX (file);
747   else if (GET_CODE (x) == REG)
748     fprintf (file, "%s", ns32k_out_reg_names[REGNO (x)]);
749   else if (GET_CODE (x) == MEM)
750     {
751       output_address (XEXP (x, 0));
752     }
753   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
754     {
755       if (GET_MODE (x) == DFmode)
756         { 
757           union { double d; int i[2]; } u;
758           u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
759           PUT_IMMEDIATE_PREFIX (file);
760 #ifdef SEQUENT_ASM
761           /* Sequent likes its floating point constants as integers */
762           fprintf (file, "0Dx%08x%08x", u.i[1], u.i[0]);
763 #else
764 #ifdef ENCORE_ASM
765           fprintf (file, "0f%.20e", u.d); 
766 #else
767           fprintf (file, "0d%.20e", u.d); 
768 #endif
769 #endif
770         }
771       else
772         { 
773           union { double d; int i[2]; } u;
774           u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
775           PUT_IMMEDIATE_PREFIX (file);
776 #ifdef SEQUENT_ASM
777           /* We have no way of winning if we can't get the bits
778              for a sequent floating point number.  */
779 #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
780           abort ();
781 #endif
782           {
783             union { float f; long l; } uu;
784             uu.f = u.d;
785             fprintf (file, "0Fx%08x", uu.l);
786           }
787 #else
788           fprintf (file, "0f%.20e", u.d); 
789 #endif
790         }
791     }
792   else
793     {
794       if (flag_pic
795           && GET_CODE (x) == CONST
796           && symbolic_reference_mentioned_p (x))
797         {
798           fprintf (stderr, "illegal constant for pic-mode: \n");
799           print_rtl (stderr, x);
800           fprintf (stderr, "\nGET_CODE (x) == %d, CONST == %d, symbolic_reference_mentioned_p (x) == %d\n",
801                   GET_CODE (x), CONST, symbolic_reference_mentioned_p (x));
802           abort ();
803         }
804       else if (flag_pic
805                && (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
806         {
807           output_addr_const (file, x);
808           fprintf (file, "(sb)");
809         }
810       else
811         {
812 #ifdef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
813           if (GET_CODE (x) == CONST_INT)
814 #endif
815             PUT_IMMEDIATE_PREFIX (file);
816           output_addr_const (file, x);
817         }
818     }
819 }
820 \f
821 /* PRINT_OPERAND_ADDRESS is defined to call this function,
822    which is easier to debug than putting all the code in
823    a macro definition in ns32k.h .  */
824
825 /* Completely rewritten to get this to work with Gas for PC532 Mach.
826    This function didn't work and I just wasn't able (nor very willing) to
827    figure out how it worked.
828    90-11-25 Tatu Yl|nen <ylo@cs.hut.fi> */
829
830 void
831 print_operand_address (file, addr)
832      register FILE *file;
833      register rtx addr;
834 {
835   static char scales[] = { 'b', 'w', 'd', 0, 'q', };
836   rtx offset, base, indexexp, tmp;
837   int scale;
838   extern int flag_pic;
839
840   if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC)
841     {
842       fprintf (file, "tos");
843       return;
844     }
845
846   offset = NULL;
847   base = NULL;
848   indexexp = NULL;
849   while (addr != NULL)
850     {
851       if (GET_CODE (addr) == PLUS)
852         {
853           if (GET_CODE (XEXP (addr, 0)) == PLUS)
854             {
855               tmp = XEXP (addr, 1);
856               addr = XEXP (addr, 0);
857             }
858           else
859             {
860               tmp = XEXP (addr,0);
861               addr = XEXP (addr,1);
862             }
863         }
864       else
865         {
866           tmp = addr;
867           addr = NULL;
868         }
869       switch (GET_CODE (tmp))
870         {
871         case PLUS:
872           abort ();
873         case MEM:
874           if (base)
875             {
876               indexexp = base;
877               base = tmp;
878             }
879           else
880             base = tmp;
881           break;
882         case REG:
883           if (REGNO (tmp) < F0_REGNUM)
884             if (base)
885               {
886                 indexexp = tmp;
887               }
888             else
889               base = tmp;
890           else
891             if (base)
892               {
893                 indexexp = base;
894                 base = tmp;
895               }
896             else
897               base = tmp;
898           break;
899         case MULT:
900           indexexp = tmp;
901           break;
902         case SYMBOL_REF:
903           if (flag_pic && ! CONSTANT_POOL_ADDRESS_P (tmp)
904               && ! SYMBOL_REF_FLAG (tmp))
905             {
906               if (base)
907                 {
908                   if (indexexp)
909                     abort ();
910                   indexexp = base;
911                 }
912               base = tmp;
913               break;
914             }
915         case CONST:
916           if (flag_pic && GET_CODE (tmp) == CONST)
917             {
918               rtx sym, off, tmp1;
919               tmp1 = XEXP (tmp,0);
920               if (GET_CODE (tmp1)  != PLUS)
921                 abort ();
922
923               sym = XEXP (tmp1,0);
924               if (GET_CODE (sym) != SYMBOL_REF)
925                 {
926                   off = sym;
927                   sym = XEXP (tmp1,1);
928                 }
929               else
930                 off = XEXP (tmp1,1);
931               if (GET_CODE (sym) == SYMBOL_REF)
932                 {
933                   if (GET_CODE (off) != CONST_INT)
934                     abort ();
935
936                   if (CONSTANT_POOL_ADDRESS_P (sym)
937                       || SYMBOL_REF_FLAG (sym))
938                     {
939                       SYMBOL_REF_FLAG (tmp) = 1;
940                     }
941                   else
942                     {
943                       if (base)
944                         {
945                           if (indexexp)
946                             abort ();
947
948                           indexexp = base;
949                         }
950
951                       if (offset != 0)
952                         abort ();
953
954                       base = sym;
955                       offset = off;
956                       break;
957                     }
958                 }
959             }
960         case CONST_INT:
961         case LABEL_REF:
962           if (offset)
963             offset = gen_rtx_PLUS (SImode, tmp, offset);
964           else
965             offset = tmp;
966           break;
967         default:
968           abort ();
969         }
970     }
971   if (! offset)
972     offset = const0_rtx;
973
974   if (base
975 #ifndef INDEX_RATHER_THAN_BASE
976       && (flag_pic || TARGET_HIMEM)
977       && GET_CODE (base) != SYMBOL_REF 
978       && GET_CODE (offset) != CONST_INT
979 #else
980   /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix.  */
981 #endif
982       && !indexexp && GET_CODE (base) == REG
983       && REG_OK_FOR_INDEX_P (base))
984     {
985       indexexp = base;
986       base = NULL;
987     }
988
989   /* now, offset, base and indexexp are set */
990 #ifndef BASE_REG_NEEDED
991   if (! base)
992     {
993 #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
994       if (GET_CODE (offset) == CONST_INT)
995 #endif
996         PUT_ABSOLUTE_PREFIX (file);
997     }
998 #endif
999
1000   output_addr_const (file, offset);
1001   if (base) /* base can be (REG ...) or (MEM ...) */
1002     switch (GET_CODE (base))
1003       {
1004         /* now we must output base.  Possible alternatives are:
1005            (rN)       (REG ...)
1006            (sp)       (REG ...)
1007            (fp)       (REG ...)
1008            (pc)       (REG ...)  used for SYMBOL_REF and LABEL_REF, output
1009            (disp(fp)) (MEM ...)       just before possible [rX:y]
1010            (disp(sp)) (MEM ...)
1011            (disp(sb)) (MEM ...)
1012            */
1013       case REG:
1014         fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]);
1015         break;
1016       case SYMBOL_REF:
1017         if (! flag_pic)
1018           abort ();
1019
1020         fprintf (file, "(");
1021         output_addr_const (file, base);
1022         fprintf (file, "(sb))");
1023         break;
1024       case MEM:
1025         addr = XEXP (base,0);
1026         base = NULL;
1027         offset = NULL;
1028         while (addr != NULL)
1029           {
1030             if (GET_CODE (addr) == PLUS)
1031               {
1032                 if (GET_CODE (XEXP (addr, 0)) == PLUS)
1033                   {
1034                     tmp = XEXP (addr, 1);
1035                     addr = XEXP (addr, 0);
1036                   }
1037                 else
1038                   {
1039                     tmp = XEXP (addr, 0);
1040                     addr = XEXP (addr, 1);
1041                   }
1042               }
1043             else
1044               {
1045                 tmp = addr;
1046                 addr = NULL;
1047               }
1048             switch (GET_CODE (tmp))
1049               {
1050               case REG:
1051                 base = tmp;
1052                 break;
1053               case CONST:
1054               case CONST_INT:
1055               case SYMBOL_REF:
1056               case LABEL_REF:
1057                 if (offset)
1058                   offset = gen_rtx_PLUS (SImode, tmp, offset);
1059                 else
1060                   offset = tmp;
1061                 break;
1062               default:
1063                 abort ();
1064               }
1065           }
1066         if (! offset)
1067           offset = const0_rtx;
1068         fprintf (file, "(");
1069         output_addr_const (file, offset);
1070         if (base)
1071           fprintf (file, "(%s)", ns32k_out_reg_names[REGNO (base)]);
1072         else if (TARGET_SB)
1073           fprintf (file, "(sb)");
1074         else
1075           abort ();
1076         fprintf (file, ")");
1077         break;
1078       default:
1079         abort ();
1080       }
1081 #ifdef PC_RELATIVE
1082   else if (GET_CODE (offset) != CONST_INT)
1083     fprintf (file, "(pc)");
1084 #ifdef BASE_REG_NEEDED
1085   else if (TARGET_SB)
1086     fprintf (file, "(sb)");
1087   else
1088     abort ();
1089 #endif
1090 #endif /* PC_RELATIVE */
1091
1092   /* now print index if we have one */
1093   if (indexexp)
1094     {
1095       if (GET_CODE (indexexp) == MULT)
1096         {
1097           scale = INTVAL (XEXP (indexexp, 1)) >> 1;
1098           indexexp = XEXP (indexexp, 0);
1099         }
1100       else
1101         scale = 0;
1102       if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= F0_REGNUM)
1103         abort ();
1104
1105 #ifdef UTEK_ASM
1106       fprintf (file, "[%c`%s]",
1107                scales[scale],
1108                ns32k_out_reg_names[REGNO (indexexp)]);
1109 #else
1110       fprintf (file, "[%s:%c]",
1111                ns32k_out_reg_names[REGNO (indexexp)],
1112                scales[scale]);
1113 #endif
1114     }
1115 }
1116 \f
1117 /* National 32032 shifting is so bad that we can get
1118    better performance in many common cases by using other
1119    techniques.  */
1120 const char *
1121 output_shift_insn (operands)
1122      rtx *operands;
1123 {
1124   if (GET_CODE (operands[2]) == CONST_INT
1125       && INTVAL (operands[2]) > 0
1126       && INTVAL (operands[2]) <= 3)
1127     {
1128       if (GET_CODE (operands[0]) == REG)
1129         {
1130           if (GET_CODE (operands[1]) == REG)
1131             {
1132               if (REGNO (operands[0]) == REGNO (operands[1]))
1133                 {
1134                   if (operands[2] == const1_rtx)
1135                     return "addd %0,%0";
1136                   else if (INTVAL (operands[2]) == 2)
1137                     return "addd %0,%0\n\taddd %0,%0";
1138                 }
1139               if (operands[2] == const1_rtx)
1140                 return "movd %1,%0\n\taddd %0,%0";
1141             
1142               operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
1143               return "addr %a1,%0";
1144             }
1145           if (operands[2] == const1_rtx)
1146             return "movd %1,%0\n\taddd %0,%0";
1147         }
1148       else if (GET_CODE (operands[1]) == REG)
1149         {
1150           operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
1151           return "addr %a1,%0";
1152         }
1153       else if (INTVAL (operands[2]) == 1
1154                && GET_CODE (operands[1]) == MEM
1155                && rtx_equal_p (operands [0], operands[1]))
1156         {
1157           rtx temp = XEXP (operands[1], 0);
1158         
1159           if (GET_CODE (temp) == REG
1160               || (GET_CODE (temp) == PLUS
1161                   && GET_CODE (XEXP (temp, 0)) == REG
1162                   && GET_CODE (XEXP (temp, 1)) == CONST_INT))
1163             return "addd %0,%0";
1164         }
1165       else return "ashd %2,%0";
1166     }
1167   return "ashd %2,%0";
1168 }
1169
1170 const char *
1171 output_move_dconst (n, s)
1172         int n;
1173         const char *s;
1174 {
1175   static char r[32];
1176
1177   if (n > -9 && n < 8)
1178     strcpy (r, "movqd ");
1179   else if (n > 0 && n < 256)
1180     strcpy (r, "movzbd ");
1181   else if (n > 0 && n < 65536)
1182     strcpy (r, "movzwd ");
1183   else if (n < 0 && n > -129)
1184     strcpy (r, "movxbd ");
1185   else if (n < 0 && n > -32769)
1186     strcpy (r, "movxwd ");
1187   else
1188     strcpy (r, "movd ");
1189   strcat (r, s);
1190   return r;
1191 }