OSDN Git Service

* 1750a.md, arm.c, clipper.c, clipper.md: Use GEN_INT consistently.
[pf3gnuchains/gcc-fork.git] / gcc / config / pdp11 / pdp11.c
1 /* Subroutines for gcc2 for pdp11.
2    Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
3    Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
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 1, 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 <stdio.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 "insn-flags.h"
31 #include "output.h"
32 #include "insn-attr.h"
33 #include "flags.h"
34
35 /*
36 #define FPU_REG_P(X)    ((X)>=8 && (X)<14)
37 #define CPU_REG_P(X)    ((X)>=0 && (X)<8)
38 */
39
40 /* this is the current value returned by the macro FIRST_PARM_OFFSET 
41    defined in tm.h */
42 int current_first_parm_offset;
43
44 /* This is where the condition code register lives.  */
45 /* rtx cc0_reg_rtx; - no longer needed? */
46
47 static rtx find_addr_reg (); 
48
49 /* Nonzero if OP is a valid second operand for an arithmetic insn.  */
50
51 int
52 arith_operand (op, mode)
53      rtx op;
54      enum machine_mode mode;
55 {
56   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
57 }
58
59 int
60 const_immediate_operand (op, mode)
61      rtx op;
62      enum machine_mode mode;
63 {
64   return (GET_CODE (op) == CONST_INT);
65 }
66
67 int 
68 immediate15_operand (op, mode)
69      rtx op;
70      enum machine_mode mode;
71 {
72     return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
73 }
74
75 int
76 expand_shift_operand (op, mode)
77   rtx op;
78   enum machine_mode mode;
79 {
80     return (GET_CODE (op) == CONST_INT 
81             && abs (INTVAL(op)) > 1 
82             && abs (INTVAL(op)) <= 4);
83 }
84
85 /*
86    stream is a stdio stream to output the code to.
87    size is an int: how many units of temporary storage to allocate.
88    Refer to the array `regs_ever_live' to determine which registers
89    to save; `regs_ever_live[I]' is nonzero if register number I
90    is ever used in the function.  This macro is responsible for
91    knowing which registers should not be saved even if used.  
92 */
93
94 void 
95 output_function_prologue(stream, size)
96   FILE *stream;
97   int size;
98 {                                                              
99     int fsize = ((size) + 1) & ~1;                                      
100     int regno, nregs, i;                                                
101     int offset = 0;
102
103     int via_ac = -1;
104     
105     fprintf (stream, "\n\t;     /* function prologue %s*/\n", current_function_name);           
106
107     /* if we are outputting code for main, 
108        the switch FPU to right mode if TARGET_FPU */
109     if ( (strcmp ("main", current_function_name) == 0)
110          && TARGET_FPU)
111     {
112         fprintf(stream, "\t;/* switch cpu to double float, single integer */\n");
113         fprintf(stream, "\tsetd\n");
114         fprintf(stream, "\tseti\n\n");
115     }
116     
117     if (frame_pointer_needed)                                   
118     {                                                           
119         fprintf(stream, "\tmov fp, -(sp)\n");                   
120         fprintf(stream, "\tmov sp, fp\n");                              
121     }                                                           
122     else                                                                
123     {                                                           
124         /* DON'T SAVE FP */
125     }                                                           
126
127     /* make frame */
128     if (fsize)                                                  
129         fprintf (stream, "\tsub $%d, sp\n", fsize);                     
130
131     /* save CPU registers  */
132     for (regno = 0; regno < 8; regno++)                         
133         if (regs_ever_live[regno] && ! call_used_regs[regno])   
134             if (! ((regno == FRAME_POINTER_REGNUM)                      
135                    && frame_pointer_needed))                            
136                 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);        
137     /* fpu regs saving */
138     
139     /* via_ac specifies the ac to use for saving ac4, ac5 */
140     via_ac = -1;
141     
142     for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++) 
143     {
144         /* ac0 - ac3 */                                         
145         if (LOAD_FPU_REG_P(regno)
146             && regs_ever_live[regno] 
147             && ! call_used_regs[regno])
148         {
149             fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[regno]);
150             via_ac = regno;
151         }
152         
153         /* maybe make ac4, ac5 call used regs?? */
154         /* ac4 - ac5 */
155         if (NO_LOAD_FPU_REG_P(regno)
156             && regs_ever_live[regno]
157             && ! call_used_regs[regno])
158         {
159             if (via_ac == -1)
160                 abort();
161             
162             fprintf (stream, "\tfldd %s, %s\n", reg_names[regno], reg_names[via_ac]);
163             fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[via_ac]);
164         }
165     }
166
167     fprintf (stream, "\t;/* end of prologue */\n\n");           
168 }
169
170 /*
171    The function epilogue should not depend on the current stack pointer!
172    It should use the frame pointer only.  This is mandatory because
173    of alloca; we also take advantage of it to omit stack adjustments
174    before returning.  */
175
176 /* maybe we can make leaf functions faster by switching to the
177    second register file - this way we don't have to save regs!
178    leaf functions are ~ 50% of all functions (dynamically!) 
179
180    set/clear bit 11 (dec. 2048) of status word for switching register files - 
181    but how can we do this? the pdp11/45 manual says bit may only 
182    be set (p.24), but not cleared!
183
184    switching to kernel is probably more expensive, so we'll leave it 
185    like this and not use the second set of registers... 
186
187    maybe as option if you want to generate code for kernel mode? */
188
189
190 void 
191 output_function_epilogue(stream, size)
192   FILE *stream;
193   int size;
194 {                                                               
195     extern int may_call_alloca;
196
197     int fsize = ((size) + 1) & ~1;                                      
198     int nregs, regno, i, j, k, adjust_fp;                               
199
200     int via_ac;
201     
202     fprintf (stream, "\n\t;     /*function epilogue */\n");             
203
204     if (frame_pointer_needed)                                   
205     {                                                           
206         /* hope this is safe - m68k does it also .... */                
207         regs_ever_live[FRAME_POINTER_REGNUM] = 0;                       
208                                                                 
209         for (i =7, j = 0 ; i >= 0 ; i--)                                
210             if (regs_ever_live[i] && ! call_used_regs[i])               
211                 j++;
212         
213         /* remember # of pushed bytes for CPU regs */
214         k = 2*j;
215         
216         for (i =7 ; i >= 0 ; i--)                                       
217             if (regs_ever_live[i] && ! call_used_regs[i])               
218                 fprintf(stream, "\tmov %d(fp), %s\n",-fsize-2*j--, reg_names[i]);
219
220         /* get ACs */                                           
221         via_ac = FIRST_PSEUDO_REGISTER -1;
222         
223         for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
224             if (regs_ever_live[i] && ! call_used_regs[i])
225             {
226                 via_ac = i;
227                 k += 8;
228             }
229         
230         for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
231         {
232             if (LOAD_FPU_REG_P(i)
233                 && regs_ever_live[i]
234                 && ! call_used_regs[i])
235             {
236                 fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[i]);
237                 k -= 8;
238             }
239             
240             if (NO_LOAD_FPU_REG_P(i)
241                 && regs_ever_live[i]
242                 && ! call_used_regs[i])
243             {
244                 if (! LOAD_FPU_REG_P(via_ac))
245                     abort();
246                     
247                 fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[via_ac]);
248                 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
249                 k -= 8;
250             }
251         }
252         
253         fprintf(stream, "\tmov fp, sp\n");                              
254         fprintf (stream, "\tmov (sp)+, fp\n");                          
255     }                                                           
256     else                                                                
257     {              
258         via_ac = FIRST_PSEUDO_REGISTER -1;
259         
260         /* get ACs */
261         for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
262             if (regs_ever_live[i] && call_used_regs[i])
263                 via_ac = i;
264         
265         for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
266         {
267             if (LOAD_FPU_REG_P(i)
268                 && regs_ever_live[i]
269                 && ! call_used_regs[i])
270               fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[i]);
271             
272             if (NO_LOAD_FPU_REG_P(i)
273                 && regs_ever_live[i]
274                 && ! call_used_regs[i])
275             {
276                 if (! LOAD_FPU_REG_P(via_ac))
277                     abort();
278                     
279                 fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[via_ac]);
280                 fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
281             }
282         }
283
284         for (i=7; i >= 0; i--)                                  
285             if (regs_ever_live[i] && !call_used_regs[i])                
286                 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);     
287                                                                 
288         if (fsize)                                              
289             fprintf((stream), "\tadd $%d, sp\n", fsize);                
290     }                   
291                                         
292     fprintf (stream, "\trts pc\n");                                     
293     fprintf (stream, "\t;/* end of epilogue*/\n\n\n");          
294 }
295         
296 /* Return the best assembler insn template
297    for moving operands[1] into operands[0] as a fullword.  */
298 static char *
299 singlemove_string (operands)
300      rtx *operands;
301 {
302   if (operands[1] != const0_rtx)
303     return "mov %1,%0";
304
305   return "clr %0";
306 }
307
308 \f
309 /* Output assembler code to perform a doubleword move insn
310    with operands OPERANDS.  */
311
312 char *
313 output_move_double (operands)
314      rtx *operands;
315 {
316   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
317   rtx latehalf[2];
318   rtx addreg0 = 0, addreg1 = 0;
319
320   /* First classify both operands.  */
321
322   if (REG_P (operands[0]))
323     optype0 = REGOP;
324   else if (offsettable_memref_p (operands[0]))
325     optype0 = OFFSOP;
326   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
327     optype0 = POPOP;
328   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
329     optype0 = PUSHOP;
330   else if (GET_CODE (operands[0]) == MEM)
331     optype0 = MEMOP;
332   else
333     optype0 = RNDOP;
334
335   if (REG_P (operands[1]))
336     optype1 = REGOP;
337   else if (CONSTANT_P (operands[1]))
338 #if 0
339            || GET_CODE (operands[1]) == CONST_DOUBLE)
340 #endif
341     optype1 = CNSTOP;
342   else if (offsettable_memref_p (operands[1]))
343     optype1 = OFFSOP;
344   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
345     optype1 = POPOP;
346   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
347     optype1 = PUSHOP;
348   else if (GET_CODE (operands[1]) == MEM)
349     optype1 = MEMOP;
350   else
351     optype1 = RNDOP;
352
353   /* Check for the cases that the operand constraints are not
354      supposed to allow to happen.  Abort if we get one,
355      because generating code for these cases is painful.  */
356
357   if (optype0 == RNDOP || optype1 == RNDOP)
358     abort ();
359
360   /* If one operand is decrementing and one is incrementing
361      decrement the former register explicitly
362      and change that operand into ordinary indexing.  */
363
364   if (optype0 == PUSHOP && optype1 == POPOP)
365     {
366       operands[0] = XEXP (XEXP (operands[0], 0), 0);
367       output_asm_insn ("sub $4,%0", operands);
368       operands[0] = gen_rtx (MEM, SImode, operands[0]);
369       optype0 = OFFSOP;
370     }
371   if (optype0 == POPOP && optype1 == PUSHOP)
372     {
373       operands[1] = XEXP (XEXP (operands[1], 0), 0);
374       output_asm_insn ("sub $4,%1", operands);
375       operands[1] = gen_rtx (MEM, SImode, operands[1]);
376       optype1 = OFFSOP;
377     }
378
379   /* If an operand is an unoffsettable memory ref, find a register
380      we can increment temporarily to make it refer to the second word.  */
381
382   if (optype0 == MEMOP)
383     addreg0 = find_addr_reg (XEXP (operands[0], 0));
384
385   if (optype1 == MEMOP)
386     addreg1 = find_addr_reg (XEXP (operands[1], 0));
387
388   /* Ok, we can do one word at a time.
389      Normally we do the low-numbered word first,
390      but if either operand is autodecrementing then we
391      do the high-numbered word first.
392
393      In either case, set up in LATEHALF the operands to use
394      for the high-numbered word and in some cases alter the
395      operands in OPERANDS to be suitable for the low-numbered word.  */
396
397   if (optype0 == REGOP)
398     latehalf[0] = gen_rtx (REG, HImode, REGNO (operands[0]) + 1);
399   else if (optype0 == OFFSOP)
400     latehalf[0] = adj_offsettable_operand (operands[0], 2);
401   else
402     latehalf[0] = operands[0];
403
404   if (optype1 == REGOP)
405     latehalf[1] = gen_rtx (REG, HImode, REGNO (operands[1]) + 1);
406   else if (optype1 == OFFSOP)
407     latehalf[1] = adj_offsettable_operand (operands[1], 2);
408   else if (optype1 == CNSTOP)
409     {
410         if (CONSTANT_P (operands[1]))
411         {
412             /* now the mess begins, high word is in lower word??? 
413
414                that's what ashc makes me think, but I don't remember :-( */
415             latehalf[1] = GEN_INT (INTVAL(operands[1])>>16);
416             operands[1] = GEN_INT (INTVAL(operands[1])&0xff);
417         }
418       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
419         {
420             /* immediate 32 bit values not allowed */
421             abort();
422         }
423     }
424   else
425     latehalf[1] = operands[1];
426
427   /* If insn is effectively movd N(sp),-(sp) then we will do the
428      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
429      for the low word as well, to compensate for the first decrement of sp.  */
430   if (optype0 == PUSHOP
431       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
432       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
433     operands[1] = latehalf[1];
434
435   /* If one or both operands autodecrementing,
436      do the two words, high-numbered first.  */
437
438   /* Likewise,  the first move would clobber the source of the second one,
439      do them in the other order.  This happens only for registers;
440      such overlap can't happen in memory unless the user explicitly
441      sets it up, and that is an undefined circumstance.  */
442
443   if (optype0 == PUSHOP || optype1 == PUSHOP
444       || (optype0 == REGOP && optype1 == REGOP
445           && REGNO (operands[0]) == REGNO (latehalf[1])))
446     {
447       /* Make any unoffsettable addresses point at high-numbered word.  */
448       if (addreg0)
449         output_asm_insn ("add $2,%0", &addreg0);
450       if (addreg1)
451         output_asm_insn ("add $2,%0", &addreg1);
452
453       /* Do that word.  */
454       output_asm_insn (singlemove_string (latehalf), latehalf);
455
456       /* Undo the adds we just did.  */
457       if (addreg0)
458         output_asm_insn ("sub $2,%0", &addreg0);
459       if (addreg1)
460         output_asm_insn ("sub $2,%0", &addreg1);
461
462       /* Do low-numbered word.  */
463       return singlemove_string (operands);
464     }
465
466   /* Normal case: do the two words, low-numbered first.  */
467
468   output_asm_insn (singlemove_string (operands), operands);
469
470   /* Make any unoffsettable addresses point at high-numbered word.  */
471   if (addreg0)
472     output_asm_insn ("add $2,%0", &addreg0);
473   if (addreg1)
474     output_asm_insn ("add $2,%0", &addreg1);
475
476   /* Do that word.  */
477   output_asm_insn (singlemove_string (latehalf), latehalf);
478
479   /* Undo the adds we just did.  */
480   if (addreg0)
481     output_asm_insn ("sub $2,%0", &addreg0);
482   if (addreg1)
483     output_asm_insn ("sub $2,%0", &addreg1);
484
485   return "";
486 }
487 /* Output assembler code to perform a quadword move insn
488    with operands OPERANDS.  */
489
490 char *
491 output_move_quad (operands)
492      rtx *operands;
493 {
494   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
495   rtx latehalf[2];
496   rtx addreg0 = 0, addreg1 = 0;
497
498   output_asm_insn(";; movdi/df: %1 -> %0", operands);
499   
500   if (REG_P (operands[0]))
501     optype0 = REGOP;
502   else if (offsettable_memref_p (operands[0]))
503     optype0 = OFFSOP;
504   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
505     optype0 = POPOP;
506   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
507     optype0 = PUSHOP;
508   else if (GET_CODE (operands[0]) == MEM)
509     optype0 = MEMOP;
510   else
511     optype0 = RNDOP;
512
513   if (REG_P (operands[1]))
514     optype1 = REGOP;
515   else if (CONSTANT_P (operands[1])
516            || GET_CODE (operands[1]) == CONST_DOUBLE)
517     optype1 = CNSTOP;
518   else if (offsettable_memref_p (operands[1]))
519     optype1 = OFFSOP;
520   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
521     optype1 = POPOP;
522   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
523     optype1 = PUSHOP;
524   else if (GET_CODE (operands[1]) == MEM)
525     optype1 = MEMOP;
526   else
527     optype1 = RNDOP;
528
529   /* Check for the cases that the operand constraints are not
530      supposed to allow to happen.  Abort if we get one,
531      because generating code for these cases is painful.  */
532
533   if (optype0 == RNDOP || optype1 == RNDOP)
534     abort ();
535   
536   /* check if we move a CPU reg to an FPU reg, or vice versa! */
537   if (optype0 == REGOP && optype1 == REGOP)
538       /* bogus - 64 bit cannot reside in CPU! */
539       if (CPU_REG_P(REGNO(operands[0]))
540           || CPU_REG_P (REGNO(operands[1])))
541           abort();
542   
543   if (optype0 == REGOP || optype1 == REGOP)
544   {
545       /* check for use of clrd???? 
546          if you ever allow ac4 and ac5 (now we require secondary load) 
547          you must check whether 
548          you want to load into them or store from them - 
549          then dump ac0 into $help$ movce ac4/5 to ac0, do the 
550          store from ac0, and restore ac0 - if you can find 
551          an unused ac[0-3], use that and you save a store and a load!*/
552
553       if (FPU_REG_P(REGNO(operands[0])))
554       {
555           if (GET_CODE(operands[1]) == CONST_DOUBLE)
556           {
557               union { double d; int i[2]; } u;
558               u.i[0] = CONST_DOUBLE_LOW (operands[1]); 
559               u.i[1] = CONST_DOUBLE_HIGH (operands[1]); 
560               
561               if (u.d == 0.0)
562                   return "clrd %0";
563           }
564               
565           return "ldd %1, %0";
566       }
567       
568       if (FPU_REG_P(REGNO(operands[1])))
569           return "std %1, %0";
570   }
571       
572   /* If one operand is decrementing and one is incrementing
573      decrement the former register explicitly
574      and change that operand into ordinary indexing.  */
575
576   if (optype0 == PUSHOP && optype1 == POPOP)
577     {
578       operands[0] = XEXP (XEXP (operands[0], 0), 0);
579       output_asm_insn ("sub $8,%0", operands);
580       operands[0] = gen_rtx (MEM, DImode, operands[0]);
581       optype0 = OFFSOP;
582     }
583   if (optype0 == POPOP && optype1 == PUSHOP)
584     {
585       operands[1] = XEXP (XEXP (operands[1], 0), 0);
586       output_asm_insn ("sub $8,%1", operands);
587       operands[1] = gen_rtx (MEM, SImode, operands[1]);
588       optype1 = OFFSOP;
589     }
590
591   /* If an operand is an unoffsettable memory ref, find a register
592      we can increment temporarily to make it refer to the second word.  */
593
594   if (optype0 == MEMOP)
595     addreg0 = find_addr_reg (XEXP (operands[0], 0));
596
597   if (optype1 == MEMOP)
598     addreg1 = find_addr_reg (XEXP (operands[1], 0));
599
600   /* Ok, we can do one word at a time.
601      Normally we do the low-numbered word first,
602      but if either operand is autodecrementing then we
603      do the high-numbered word first.
604
605      In either case, set up in LATEHALF the operands to use
606      for the high-numbered word and in some cases alter the
607      operands in OPERANDS to be suitable for the low-numbered word.  */
608
609   if (optype0 == REGOP)
610     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
611   else if (optype0 == OFFSOP)
612     latehalf[0] = adj_offsettable_operand (operands[0], 4);
613   else
614     latehalf[0] = operands[0];
615
616   if (optype1 == REGOP)
617     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
618   else if (optype1 == OFFSOP)
619     latehalf[1] = adj_offsettable_operand (operands[1], 4);
620   else if (optype1 == CNSTOP)
621     {
622       if (GET_CODE (operands[1]) == CONST_DOUBLE)
623         {
624             /* floats only. not yet supported!
625
626              -- compute it into PDP float format, - internally,
627              just use IEEE and ignore possible problems ;-)
628
629              we might get away with it !!!! */
630
631             abort();
632             
633 #ifndef HOST_WORDS_BIG_ENDIAN
634           latehalf[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
635           operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
636 #else /* HOST_WORDS_BIG_ENDIAN */
637           latehalf[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
638           operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
639 #endif /* HOST_WORDS_BIG_ENDIAN */
640         }
641       else if (GET_CODE(operands[1]) == CONST_INT)
642       {
643           latehalf[1] = GEN_INT (0);
644       }
645       else
646           abort();
647       
648     }
649   else
650     latehalf[1] = operands[1];
651
652   /* If insn is effectively movd N(sp),-(sp) then we will do the
653      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
654      for the low word as well, to compensate for the first decrement of sp.  */
655   if (optype0 == PUSHOP
656       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
657       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
658     operands[1] = latehalf[1];
659
660   /* If one or both operands autodecrementing,
661      do the two words, high-numbered first.  */
662
663   /* Likewise,  the first move would clobber the source of the second one,
664      do them in the other order.  This happens only for registers;
665      such overlap can't happen in memory unless the user explicitly
666      sets it up, and that is an undefined circumstance.  */
667
668   if (optype0 == PUSHOP || optype1 == PUSHOP
669       || (optype0 == REGOP && optype1 == REGOP
670           && REGNO (operands[0]) == REGNO (latehalf[1])))
671     {
672       /* Make any unoffsettable addresses point at high-numbered word.  */
673       if (addreg0)
674         output_asm_insn ("add $4,%0", &addreg0);
675       if (addreg1)
676         output_asm_insn ("add $4,%0", &addreg1);
677
678       /* Do that word.  */
679       output_asm_insn(output_move_double(latehalf), latehalf);
680
681       /* Undo the adds we just did.  */
682       if (addreg0)
683         output_asm_insn ("sub $4,%0", &addreg0);
684       if (addreg1)
685         output_asm_insn ("sub $4,%0", &addreg1);
686
687       /* Do low-numbered word.  */
688       return output_move_double (operands);
689     }
690
691   /* Normal case: do the two words, low-numbered first.  */
692
693   output_asm_insn (output_move_double (operands), operands);
694
695   /* Make any unoffsettable addresses point at high-numbered word.  */
696   if (addreg0)
697     output_asm_insn ("add $4,%0", &addreg0);
698   if (addreg1)
699     output_asm_insn ("add $4,%0", &addreg1);
700
701   /* Do that word.  */
702   output_asm_insn (output_move_double (latehalf), latehalf);
703
704   /* Undo the adds we just did.  */
705   if (addreg0)
706     output_asm_insn ("sub $4,%0", &addreg0);
707   if (addreg1)
708     output_asm_insn ("sub $4,%0", &addreg1);
709
710   return "";
711 }
712
713 \f
714 /* Return a REG that occurs in ADDR with coefficient 1.
715    ADDR can be effectively incremented by incrementing REG.  */
716
717 static rtx
718 find_addr_reg (addr)
719      rtx addr;
720 {
721   while (GET_CODE (addr) == PLUS)
722     {
723       if (GET_CODE (XEXP (addr, 0)) == REG)
724         addr = XEXP (addr, 0);
725       if (GET_CODE (XEXP (addr, 1)) == REG)
726         addr = XEXP (addr, 1);
727       if (CONSTANT_P (XEXP (addr, 0)))
728         addr = XEXP (addr, 1);
729       if (CONSTANT_P (XEXP (addr, 1)))
730         addr = XEXP (addr, 0);
731     }
732   if (GET_CODE (addr) == REG)
733     return addr;
734   return 0;
735 }
736 \f
737 /* Output an ascii string.  */
738 output_ascii (file, p, size)
739      FILE *file;
740      char *p;
741      int size;
742 {
743   int i;
744
745   fprintf (file, "\t.byte \"");
746
747   for (i = 0; i < size; i++)
748     {
749       register int c = p[i];
750       if (c == '\"' || c == '\\')
751         putc ('\\', file);
752       if (c >= ' ' && c < 0177)
753         putc (c, file);
754       else
755         {
756           fprintf (file, "\\%03o", c);
757           /* After an octal-escape, if a digit follows,
758              terminate one string constant and start another.
759              The Vax assembler fails to stop reading the escape
760              after three digits, so this is the only way we
761              can get it to parse the data properly.  */
762           if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9')
763             fprintf (file, "\"\n\tstring \"");
764         }
765     }
766   fprintf (file, "\"\n");
767 }
768
769
770 /* --- stole from out-vax, needs changes */
771
772 print_operand_address (file, addr)
773      FILE *file;
774      register rtx addr;
775 {
776   register rtx reg1, reg2, breg, ireg;
777   rtx offset;
778
779  retry:
780
781   switch (GET_CODE (addr))
782     {
783     case MEM:
784       fprintf (file, "@");
785       addr = XEXP (addr, 0);
786       goto retry;
787
788     case REG:
789       fprintf (file, "(%s)", reg_names[REGNO (addr)]);
790       break;
791
792     case PRE_DEC:
793       fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
794       break;
795
796     case POST_INC:
797       fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
798       break;
799
800     case PLUS:
801       reg1 = 0; reg2 = 0;
802       ireg = 0; breg = 0;
803       offset = 0;
804       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
805           || GET_CODE (XEXP (addr, 0)) == MEM)
806         {
807           offset = XEXP (addr, 0);
808           addr = XEXP (addr, 1);
809         }
810       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
811                || GET_CODE (XEXP (addr, 1)) == MEM)
812         {
813           offset = XEXP (addr, 1);
814           addr = XEXP (addr, 0);
815         }
816       if (GET_CODE (addr) != PLUS)
817         ;
818       else if (GET_CODE (XEXP (addr, 0)) == MULT)
819         {
820           reg1 = XEXP (addr, 0);
821           addr = XEXP (addr, 1);
822         }
823       else if (GET_CODE (XEXP (addr, 1)) == MULT)
824         {
825           reg1 = XEXP (addr, 1);
826           addr = XEXP (addr, 0);
827         }
828       else if (GET_CODE (XEXP (addr, 0)) == REG)
829         {
830           reg1 = XEXP (addr, 0);
831           addr = XEXP (addr, 1);
832         }
833       else if (GET_CODE (XEXP (addr, 1)) == REG)
834         {
835           reg1 = XEXP (addr, 1);
836           addr = XEXP (addr, 0);
837         }
838       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
839         {
840           if (reg1 == 0)
841             reg1 = addr;
842           else
843             reg2 = addr;
844           addr = 0;
845         }
846       if (offset != 0)
847         {
848           if (addr != 0) abort ();
849           addr = offset;
850         }
851       if (reg1 != 0 && GET_CODE (reg1) == MULT)
852         {
853           breg = reg2;
854           ireg = reg1;
855         }
856       else if (reg2 != 0 && GET_CODE (reg2) == MULT)
857         {
858           breg = reg1;
859           ireg = reg2;
860         }
861       else if (reg2 != 0 || GET_CODE (addr) == MEM)
862         {
863           breg = reg2;
864           ireg = reg1;
865         }
866       else
867         {
868           breg = reg1;
869           ireg = reg2;
870         }
871       if (addr != 0)
872         output_address (addr);
873       if (breg != 0)
874         {
875           if (GET_CODE (breg) != REG)
876             abort ();
877           fprintf (file, "(%s)", reg_names[REGNO (breg)]);
878         }
879       if (ireg != 0)
880         {
881           if (GET_CODE (ireg) == MULT)
882             ireg = XEXP (ireg, 0);
883           if (GET_CODE (ireg) != REG)
884             abort ();
885           abort();
886           fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
887         }
888       break;
889
890     default:
891       output_addr_const (file, addr);
892     }
893 }
894
895 /* register move costs, indexed by regs */
896
897 static int move_costs[N_REG_CLASSES][N_REG_CLASSES] = 
898 {
899              /* NO  MUL  GEN  LFPU  NLFPU FPU ALL */
900
901 /* NO */     {  0,   0,   0,    0,    0,    0,   0},
902 /* MUL */    {  0,   2,   2,   10,   22,   22,  22},
903 /* GEN */    {  0,   2,   2,   10,   22,   22,  22},
904 /* LFPU */   {  0,  10,  10,    2,    2,    2,  10},
905 /* NLFPU */  {  0,  22,  22,    2,    2,    2,  22},
906 /* FPU */    {  0,  22,  22,    2,    2,    2,  22},
907 /* ALL */    {  0,  22,  22,   10,   22,   22,  22}
908 }  ;
909
910
911 /* -- note that some moves are tremendously expensive, 
912    because they require lots of tricks! do we have to 
913    charge the costs incurred by secondary reload class 
914    -- as we do here with 22 -- or not ? */
915
916 int 
917 register_move_cost(c1, c2)
918   enum reg_class c1, c2;
919 {
920     return move_costs[(int)c1][(int)c2];
921 }
922
923 char *
924 output_jump(pos, neg, length)
925   int length;
926   char *pos, *neg;
927 {
928     static int x = 0;
929     
930     static char buf[1000];
931
932 #if 0
933 /* currently we don't need this, because the tstdf and cmpdf 
934    copy the condition code immediately, and other float operations are not 
935    yet recognized as changing the FCC - if so, then the length-cost of all
936    jump insns increases by one, because we have to potentially copy the 
937    FCC! */
938     if (cc_status.flags & CC_IN_FPU)
939         output_asm_insn("cfcc", NULL);
940 #endif
941         
942     switch (length)
943     {
944       case 1:
945         
946         strcpy(buf, pos);
947         strcat(buf, " %l0");
948         
949         return buf;
950         
951       case 3:
952         
953         sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);
954         
955         x++;
956         
957         return buf;
958         
959       default:
960         
961         abort();
962     }
963     
964 }
965
966 void
967 notice_update_cc_on_set(exp, insn)
968   rtx exp;
969   rtx insn;
970 {
971     if (GET_CODE (SET_DEST (exp)) == CC0)
972     { 
973         cc_status.flags = 0;                                    
974         cc_status.value1 = SET_DEST (exp);                      
975         cc_status.value2 = SET_SRC (exp);                       
976
977 /*
978         if (GET_MODE(SET_SRC(exp)) == DFmode)
979             cc_status.flags |= CC_IN_FPU;
980 */      
981     }                                                   
982     else if ((GET_CODE (SET_DEST (exp)) == REG          
983               || GET_CODE (SET_DEST (exp)) == MEM)              
984              && GET_CODE (SET_SRC (exp)) != PC          
985              && (GET_MODE (SET_DEST(exp)) == HImode             
986                  || GET_MODE (SET_DEST(exp)) == QImode) 
987                 && (GET_CODE (SET_SRC(exp)) == PLUS             
988                     || GET_CODE (SET_SRC(exp)) == MINUS 
989                     || GET_CODE (SET_SRC(exp)) == AND   
990                     || GET_CODE (SET_SRC(exp)) == IOR   
991                     || GET_CODE (SET_SRC(exp)) == XOR   
992                     || GET_CODE (SET_SRC(exp)) == NOT   
993                     || GET_CODE (SET_SRC(exp)) == NEG   
994                         || GET_CODE (SET_SRC(exp)) == REG       
995                     || GET_CODE (SET_SRC(exp)) == MEM)) 
996     { 
997         cc_status.flags = 0;                                    
998         cc_status.value1 = SET_SRC (exp);                       
999         cc_status.value2 = SET_DEST (exp);                      
1000         
1001         if (cc_status.value1 && GET_CODE (cc_status.value1) == REG      
1002             && cc_status.value2                                 
1003             && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1004             cc_status.value2 = 0;                                       
1005         if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM      
1006             && cc_status.value2                                 
1007             && GET_CODE (cc_status.value2) == MEM)                      
1008             cc_status.value2 = 0;                                       
1009     }                                                   
1010     else if (GET_CODE (SET_SRC (exp)) == CALL)          
1011     { 
1012         CC_STATUS_INIT; 
1013     }
1014     else if (GET_CODE (SET_DEST (exp)) == REG)                  
1015         /* what's this ? */                                     
1016     { 
1017         if ((cc_status.value1                                   
1018              && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1019             cc_status.value1 = 0;                               
1020         if ((cc_status.value2                                   
1021              && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1022             cc_status.value2 = 0;                               
1023     }                                                   
1024     else if (SET_DEST(exp) == pc_rtx)
1025     { 
1026         /* jump */
1027     }
1028     else /* if (GET_CODE (SET_DEST (exp)) == MEM)       */      
1029     {  
1030         /* the last else is a bit paranoiac, but since nearly all instructions 
1031            play with condition codes, it's reasonable! */
1032
1033         CC_STATUS_INIT; /* paranoia*/ 
1034     }                   
1035 }
1036
1037
1038 int simple_memory_operand(op, mode)
1039   rtx op;
1040   enum machine_mode mode;
1041 {
1042     rtx addr, plus0, plus1;
1043     int offset = 0;
1044
1045     /* Eliminate non-memory operations */
1046     if (GET_CODE (op) != MEM)
1047         return FALSE;
1048
1049 #if 0
1050     /* dword operations really put out 2 instructions, so eliminate them.  */
1051     if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1052         return FALSE;
1053 #endif
1054
1055     /* Decode the address now.  */
1056
1057   indirection:
1058     
1059     addr = XEXP (op, 0);
1060
1061     switch (GET_CODE (addr))
1062     {
1063       case REG:
1064         /* (R0) - no extra cost */
1065         return 1;
1066         
1067       case PRE_DEC:
1068       case POST_INC:
1069         /* -(R0), (R0)+ - cheap! */
1070         return 0;
1071         
1072       case MEM:
1073         /* cheap - is encoded in addressing mode info! 
1074
1075            -- except for @(R0), which has to be @0(R0) !!! */
1076
1077         if (GET_CODE (XEXP (addr, 0)) == REG)
1078             return 0;
1079         
1080         op=addr;
1081         goto indirection;
1082         
1083       case CONST_INT:
1084       case LABEL_REF:          
1085       case CONST:
1086       case SYMBOL_REF:
1087         /* @#address - extra cost */
1088         return 0;
1089
1090       case PLUS:
1091         /* X(R0) - extra cost */
1092         return 0;
1093     }
1094     
1095     return FALSE;
1096 }
1097
1098
1099 /*
1100  * output a block move:
1101  *
1102  * operands[0]  ... to
1103  * operands[1]  ... from
1104  * operands[2]  ... length
1105  * operands[3]  ... alignment
1106  * operands[4]  ... scratch register
1107  */
1108
1109  
1110 char *
1111 output_block_move(operands)
1112   rtx *operands;
1113 {
1114     static int count = 0;
1115     char buf[200];
1116     
1117     if (GET_CODE(operands[2]) == CONST_INT
1118         && TARGET_TIME)
1119     {
1120         if (INTVAL(operands[2]) < 16
1121             && INTVAL(operands[3]) == 1)
1122         {
1123             register int i;
1124             
1125             for (i = 1; i <= INTVAL(operands[2]); i++)
1126                 output_asm_insn("movb (%1)+, (%0)+", operands);
1127
1128             return "";
1129         }
1130         else if (INTVAL(operands[2]) < 32)
1131         {
1132             register int i;
1133             
1134             for (i = 1; i <= INTVAL(operands[2])/2; i++)
1135                 output_asm_insn("mov (%1)+, (%0)+", operands);
1136             
1137             /* may I assume that moved quantity is 
1138                multiple of alignment ???
1139
1140                I HOPE SO !
1141             */
1142
1143             return "";
1144         }
1145         
1146
1147         /* can do other clever things, maybe... */
1148     }
1149
1150     if (CONSTANT_P(operands[2]) )
1151     {
1152         /* just move count to scratch */
1153         output_asm_insn("mov %2, %4", operands);
1154     }
1155     else
1156     {
1157         /* just clobber the register */
1158         operands[4] = operands[2];
1159     }
1160     
1161
1162     /* switch over alignment */
1163     switch (INTVAL(operands[3]))
1164     {
1165       case 1:
1166         
1167         /* 
1168           x:
1169           movb (%1)+, (%0)+
1170           
1171           if (TARGET_45)
1172              sob %4,x
1173           else
1174              dec %4
1175              bgt x
1176
1177         */
1178
1179         sprintf(buf, "\nmovestrhi%d:", count);
1180         output_asm_insn(buf, NULL);
1181         
1182         output_asm_insn("movb (%1)+, (%0)+", operands);
1183         
1184         if (TARGET_45)
1185         {
1186             sprintf(buf, "sob %%4, movestrhi%d", count);
1187             output_asm_insn(buf, operands);
1188         }
1189         else
1190         {
1191             output_asm_insn("dec %4", operands);
1192             
1193             sprintf(buf, "bgt movestrhi%d", count);
1194             output_asm_insn(buf, NULL);
1195         }
1196         
1197         count ++;
1198         break;
1199         
1200       case 2:
1201         
1202         /* 
1203            asr %4
1204
1205            x:
1206
1207            mov (%1)+, (%0)+
1208
1209            if (TARGET_45)
1210              sob %4, x
1211            else
1212              dec %4
1213              bgt x
1214         */
1215
1216       generate_compact_code:
1217
1218         output_asm_insn("asr %4", operands);
1219
1220         sprintf(buf, "\nmovestrhi%d:", count);
1221         output_asm_insn(buf, NULL);
1222         
1223         output_asm_insn("mov (%1)+, (%0)+", operands);
1224         
1225         if (TARGET_45)
1226         {
1227             sprintf(buf, "sob %%4, movestrhi%d", count);
1228             output_asm_insn(buf, operands);
1229         }
1230         else
1231         {
1232             output_asm_insn("dec %4", operands);
1233             
1234             sprintf(buf, "bgt movestrhi%d", count);
1235             output_asm_insn(buf, NULL);
1236         }
1237         
1238         count ++;
1239         break;
1240
1241       case 4:
1242         
1243         /*
1244
1245            asr %4
1246            asr %4
1247
1248            x:
1249
1250            mov (%1)+, (%0)+
1251            mov (%1)+, (%0)+
1252
1253            if (TARGET_45)
1254              sob %4, x
1255            else
1256              dec %4
1257              bgt x
1258         */
1259
1260         if (TARGET_SPACE)
1261             goto generate_compact_code;
1262         
1263         output_asm_insn("asr %4", operands);
1264         output_asm_insn("asr %4", operands);
1265
1266         sprintf(buf, "\nmovestrhi%d:", count);
1267         output_asm_insn(buf, NULL);
1268         
1269         output_asm_insn("mov (%1)+, (%0)+", operands);
1270         output_asm_insn("mov (%1)+, (%0)+", operands);
1271         
1272         if (TARGET_45)
1273         {
1274             sprintf(buf, "sob %%4, movestrhi%d", count);
1275             output_asm_insn(buf, operands);
1276         }
1277         else
1278         {
1279             output_asm_insn("dec %4", operands);
1280             
1281             sprintf(buf, "bgt movestrhi%d", count);
1282             output_asm_insn(buf, NULL);
1283         }
1284         
1285         count ++;
1286         break;
1287        
1288       default:
1289         
1290         /*
1291            
1292            asr %4
1293            asr %4
1294            asr %4
1295
1296            x:
1297
1298            mov (%1)+, (%0)+
1299            mov (%1)+, (%0)+
1300            mov (%1)+, (%0)+
1301            mov (%1)+, (%0)+
1302            
1303            if (TARGET_45)
1304              sob %4, x
1305            else
1306              dec %4
1307              bgt x
1308         */
1309
1310
1311         if (TARGET_SPACE)
1312             goto generate_compact_code;
1313         
1314         output_asm_insn("asr %4", operands);
1315         output_asm_insn("asr %4", operands);
1316         output_asm_insn("asr %4", operands);
1317
1318         sprintf(buf, "\nmovestrhi%d:", count);
1319         output_asm_insn(buf, NULL);
1320         
1321         output_asm_insn("mov (%1)+, (%0)+", operands);
1322         output_asm_insn("mov (%1)+, (%0)+", operands);
1323         output_asm_insn("mov (%1)+, (%0)+", operands);
1324         output_asm_insn("mov (%1)+, (%0)+", operands);
1325         
1326         if (TARGET_45)
1327         {
1328             sprintf(buf, "sob %%4, movestrhi%d", count);
1329             output_asm_insn(buf, operands);
1330         }
1331         else
1332         {
1333             output_asm_insn("dec %4", operands);
1334             
1335             sprintf(buf, "bgt movestrhi%d", count);
1336             output_asm_insn(buf, NULL);
1337         }
1338         
1339         count ++;
1340         break;
1341         
1342         ;
1343         
1344     }
1345     
1346     return "";
1347 }
1348
1349 /* for future use */
1350 int
1351 comparison_operator_index(op)
1352   rtx op;
1353 {
1354     switch (GET_CODE(op))
1355     {
1356       case NE:
1357         return 0;
1358         
1359       case EQ:
1360         return 1;
1361         
1362       case GE:
1363         return 2;
1364         
1365       case GT:
1366         return 3;
1367         
1368       case LE:
1369         return 4;
1370         
1371       case LT:
1372         return 5;
1373         
1374       case GEU:
1375         return 6;
1376         
1377       case GTU:
1378         return 7;
1379
1380       case LEU:
1381         return 8;
1382         
1383       case LTU:
1384         return 9;
1385         
1386       default:
1387         return -1;
1388     }
1389 }    
1390         
1391 /* tests whether the rtx is a comparison operator */
1392 int
1393 comp_operator (op, mode)
1394   rtx op;
1395   enum machine_mode mode;
1396 {
1397     return comparison_operator_index(op) >= 0;
1398 }
1399
1400     
1401 int
1402 legitimate_address_p (mode, address)
1403   enum machine_mode mode;
1404   rtx address;
1405 {
1406 /* #define REG_OK_STRICT */
1407     GO_IF_LEGITIMATE_ADDRESS(mode, address, win);
1408     
1409     return 0;
1410     
1411   win:
1412     return 1;
1413
1414 /* #undef REG_OK_STRICT */
1415 }