OSDN Git Service

* config/arc/arc-protos.h arc_select_cc_mode, gen_compare_reg):
[pf3gnuchains/gcc-fork.git] / gcc / config / pdp11 / pdp11.c
1 /* Subroutines for gcc2 for pdp11.
2    Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2004, 2005,
3    2006, 2007 Free Software Foundation, Inc.
4    Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "real.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "function.h"
33 #include "output.h"
34 #include "insn-attr.h"
35 #include "flags.h"
36 #include "recog.h"
37 #include "tree.h"
38 #include "expr.h"
39 #include "toplev.h"
40 #include "tm_p.h"
41 #include "target.h"
42 #include "target-def.h"
43
44 /*
45 #define FPU_REG_P(X)    ((X)>=8 && (X)<14)
46 #define CPU_REG_P(X)    ((X)>=0 && (X)<8)
47 */
48
49 /* this is the current value returned by the macro FIRST_PARM_OFFSET 
50    defined in tm.h */
51 int current_first_parm_offset;
52
53 /* Routines to encode/decode pdp11 floats */
54 static void encode_pdp11_f (const struct real_format *fmt,
55                             long *, const REAL_VALUE_TYPE *);
56 static void decode_pdp11_f (const struct real_format *,
57                             REAL_VALUE_TYPE *, const long *);
58 static void encode_pdp11_d (const struct real_format *fmt,
59                             long *, const REAL_VALUE_TYPE *);
60 static void decode_pdp11_d (const struct real_format *,
61                             REAL_VALUE_TYPE *, const long *);
62
63 /* These two are taken from the corresponding vax descriptors
64    in real.c, changing only the encode/decode routine pointers.  */
65 const struct real_format pdp11_f_format =
66   {
67     encode_pdp11_f,
68     decode_pdp11_f,
69     2,
70     1,
71     24,
72     24,
73     -127,
74     127,
75     15,
76     false,
77     false,
78     false,
79     false,
80     false,
81     false
82   };
83
84 const struct real_format pdp11_d_format =
85   {
86     encode_pdp11_d,
87     decode_pdp11_d,
88     2,
89     1,
90     56,
91     56,
92     -127,
93     127,
94     15,
95     false,
96     false,
97     false,
98     false,
99     false,
100     false
101   };
102
103 static void
104 encode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
105                 const REAL_VALUE_TYPE *r)
106 {
107   (*vax_f_format.encode) (fmt, buf, r);
108   buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
109 }
110
111 static void
112 decode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED,
113                 REAL_VALUE_TYPE *r, const long *buf)
114 {
115   long tbuf;
116   tbuf = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
117   (*vax_f_format.decode) (fmt, r, &tbuf);
118 }
119
120 static void
121 encode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
122                 const REAL_VALUE_TYPE *r)
123 {
124   (*vax_d_format.encode) (fmt, buf, r);
125   buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
126   buf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
127 }
128
129 static void
130 decode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED,
131                 REAL_VALUE_TYPE *r, const long *buf)
132 {
133   long tbuf[2];
134   tbuf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
135   tbuf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
136   (*vax_d_format.decode) (fmt, r, tbuf);
137 }
138
139 /* This is where the condition code register lives.  */
140 /* rtx cc0_reg_rtx; - no longer needed? */
141
142 static bool pdp11_handle_option (size_t, const char *, int);
143 static rtx find_addr_reg (rtx); 
144 static const char *singlemove_string (rtx *);
145 static bool pdp11_assemble_integer (rtx, unsigned int, int);
146 static void pdp11_output_function_prologue (FILE *, HOST_WIDE_INT);
147 static void pdp11_output_function_epilogue (FILE *, HOST_WIDE_INT);
148 static bool pdp11_rtx_costs (rtx, int, int, int *);
149 static bool pdp11_return_in_memory (const_tree, const_tree);
150 \f
151 /* Initialize the GCC target structure.  */
152 #undef TARGET_ASM_BYTE_OP
153 #define TARGET_ASM_BYTE_OP NULL
154 #undef TARGET_ASM_ALIGNED_HI_OP
155 #define TARGET_ASM_ALIGNED_HI_OP NULL
156 #undef TARGET_ASM_ALIGNED_SI_OP
157 #define TARGET_ASM_ALIGNED_SI_OP NULL
158 #undef TARGET_ASM_INTEGER
159 #define TARGET_ASM_INTEGER pdp11_assemble_integer
160
161 #undef TARGET_ASM_FUNCTION_PROLOGUE
162 #define TARGET_ASM_FUNCTION_PROLOGUE pdp11_output_function_prologue
163 #undef TARGET_ASM_FUNCTION_EPILOGUE
164 #define TARGET_ASM_FUNCTION_EPILOGUE pdp11_output_function_epilogue
165
166 #undef TARGET_ASM_OPEN_PAREN
167 #define TARGET_ASM_OPEN_PAREN "["
168 #undef TARGET_ASM_CLOSE_PAREN
169 #define TARGET_ASM_CLOSE_PAREN "]"
170
171 #undef TARGET_DEFAULT_TARGET_FLAGS
172 #define TARGET_DEFAULT_TARGET_FLAGS \
173   (MASK_FPU | MASK_45 | MASK_ABSHI_BUILTIN | TARGET_UNIX_ASM_DEFAULT)
174 #undef TARGET_HANDLE_OPTION
175 #define TARGET_HANDLE_OPTION pdp11_handle_option
176
177 #undef TARGET_RTX_COSTS
178 #define TARGET_RTX_COSTS pdp11_rtx_costs
179
180 #undef TARGET_RETURN_IN_MEMORY
181 #define TARGET_RETURN_IN_MEMORY pdp11_return_in_memory
182
183 struct gcc_target targetm = TARGET_INITIALIZER;
184 \f
185 /* Implement TARGET_HANDLE_OPTION.  */
186
187 static bool
188 pdp11_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED,
189                      int value ATTRIBUTE_UNUSED)
190 {
191   switch (code)
192     {
193     case OPT_m10:
194       target_flags &= ~(MASK_40 | MASK_45);
195       return true;
196
197     default:
198       return true;
199     }
200 }
201
202 /* Nonzero if OP is a valid second operand for an arithmetic insn.  */
203
204 int
205 arith_operand (rtx op, enum machine_mode mode)
206 {
207   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
208 }
209
210 int
211 const_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
212 {
213   return (GET_CODE (op) == CONST_INT);
214 }
215
216 int 
217 immediate15_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
218 {
219     return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
220 }
221
222 int
223 expand_shift_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
224 {
225     return (GET_CODE (op) == CONST_INT 
226             && abs (INTVAL(op)) > 1 
227             && abs (INTVAL(op)) <= 4);
228 }
229
230 /*
231    stream is a stdio stream to output the code to.
232    size is an int: how many units of temporary storage to allocate.
233    Refer to the array `regs_ever_live' to determine which registers
234    to save; `regs_ever_live[I]' is nonzero if register number I
235    is ever used in the function.  This macro is responsible for
236    knowing which registers should not be saved even if used.  
237 */
238
239 #ifdef TWO_BSD
240
241 static void
242 pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
243 {                                                              
244   fprintf (stream, "\tjsr       r5, csv\n");
245   if (size)
246     {
247       fprintf (stream, "\t/*abuse empty parameter slot for locals!*/\n");
248       if (size > 2)
249         asm_fprintf (stream, "\tsub $%#wo, sp\n", size - 2);
250
251     }
252 }
253
254 #else  /* !TWO_BSD */
255
256 static void
257 pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
258 {                                                              
259     HOST_WIDE_INT fsize = ((size) + 1) & ~1;
260     int regno;
261     int via_ac = -1;
262
263     fprintf (stream,
264              "\n\t;     /* function prologue %s*/\n",
265              current_function_name ());
266
267     /* if we are outputting code for main, 
268        the switch FPU to right mode if TARGET_FPU */
269     if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU)
270     {
271         fprintf(stream,
272                 "\t;/* switch cpu to double float, single integer */\n");
273         fprintf(stream, "\tsetd\n");
274         fprintf(stream, "\tseti\n\n");
275     }
276     
277     if (frame_pointer_needed)                                   
278     {                                                           
279         fprintf(stream, "\tmov r5, -(sp)\n");                   
280         fprintf(stream, "\tmov sp, r5\n");                              
281     }                                                           
282     else                                                                
283     {                                                           
284         /* DON'T SAVE FP */
285     }                                                           
286
287     /* make frame */
288     if (fsize)                                                  
289         asm_fprintf (stream, "\tsub $%#wo, sp\n", fsize);
290
291     /* save CPU registers  */
292     for (regno = 0; regno < 8; regno++)                         
293       if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])       
294             if (! ((regno == FRAME_POINTER_REGNUM)                      
295                    && frame_pointer_needed))                            
296                 fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);        
297     /* fpu regs saving */
298     
299     /* via_ac specifies the ac to use for saving ac4, ac5 */
300     via_ac = -1;
301     
302     for (regno = 8; regno < FIRST_PSEUDO_REGISTER ; regno++) 
303     {
304         /* ac0 - ac3 */                                         
305         if (LOAD_FPU_REG_P(regno)
306             && df_regs_ever_live_p (regno) 
307             && ! call_used_regs[regno])
308         {
309             fprintf (stream, "\tstd %s, -(sp)\n", reg_names[regno]);
310             via_ac = regno;
311         }
312         
313         /* maybe make ac4, ac5 call used regs?? */
314         /* ac4 - ac5 */
315         if (NO_LOAD_FPU_REG_P(regno)
316             && df_regs_ever_live_p (regno)
317             && ! call_used_regs[regno])
318         {
319           gcc_assert (via_ac != -1);
320           fprintf (stream, "\tldd %s, %s\n",
321                    reg_names[regno], reg_names[via_ac]);
322           fprintf (stream, "\tstd %s, -(sp)\n", reg_names[via_ac]);
323         }
324     }
325
326     fprintf (stream, "\t;/* end of prologue */\n\n");           
327 }
328
329 #endif /* !TWO_BSD */
330
331 /*
332    The function epilogue should not depend on the current stack pointer!
333    It should use the frame pointer only.  This is mandatory because
334    of alloca; we also take advantage of it to omit stack adjustments
335    before returning.  */
336
337 /* maybe we can make leaf functions faster by switching to the
338    second register file - this way we don't have to save regs!
339    leaf functions are ~ 50% of all functions (dynamically!) 
340
341    set/clear bit 11 (dec. 2048) of status word for switching register files - 
342    but how can we do this? the pdp11/45 manual says bit may only 
343    be set (p.24), but not cleared!
344
345    switching to kernel is probably more expensive, so we'll leave it 
346    like this and not use the second set of registers... 
347
348    maybe as option if you want to generate code for kernel mode? */
349
350 #ifdef TWO_BSD
351
352 static void
353 pdp11_output_function_epilogue (FILE *stream,
354                                 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
355 {                                                               
356   fprintf (stream, "\t/* SP ignored by cret? */\n");
357   fprintf (stream, "\tjmp cret\n");
358 }
359
360 #else  /* !TWO_BSD */
361
362 static void
363 pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
364 {                                                               
365     HOST_WIDE_INT fsize = ((size) + 1) & ~1;
366     int i, j, k;
367
368     int via_ac;
369     
370     fprintf (stream, "\n\t;     /*function epilogue */\n");             
371
372     if (frame_pointer_needed)                                   
373     {                                                           
374         /* hope this is safe - m68k does it also .... */                
375       df_regs_ever_live_p (FRAME_POINTER_REGNUM) = 0;                   
376                                                                 
377         for (i =7, j = 0 ; i >= 0 ; i--)                                
378           if (df_regs_ever_live_p (i) && ! call_used_regs[i])           
379                 j++;
380         
381         /* remember # of pushed bytes for CPU regs */
382         k = 2*j;
383         
384         /* change fp -> r5 due to the compile error on libgcc2.c */
385         for (i =7 ; i >= 0 ; i--)                                       
386           if (df_regs_ever_live_p (i) && ! call_used_regs[i])           
387                 fprintf(stream, "\tmov %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
388                         (-fsize-2*j--)&0xffff, reg_names[i]);
389
390         /* get ACs */                                           
391         via_ac = FIRST_PSEUDO_REGISTER -1;
392         
393         for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
394           if (df_regs_ever_live_p (i) && ! call_used_regs[i])
395             {
396                 via_ac = i;
397                 k += 8;
398             }
399         
400         for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
401         {
402             if (LOAD_FPU_REG_P(i)
403                 && df_regs_ever_live_p (i)
404                 && ! call_used_regs[i])
405             {
406                 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
407                         (-fsize-k)&0xffff, reg_names[i]);
408                 k -= 8;
409             }
410             
411             if (NO_LOAD_FPU_REG_P(i)
412                 && df_regs_ever_live_p (i)
413                 && ! call_used_regs[i])
414             {
415                 gcc_assert (LOAD_FPU_REG_P(via_ac));
416                     
417                 fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
418                         (-fsize-k)&0xffff, reg_names[via_ac]);
419                 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
420                 k -= 8;
421             }
422         }
423         
424         fprintf(stream, "\tmov r5, sp\n");                              
425         fprintf (stream, "\tmov (sp)+, r5\n");                          
426     }                                                           
427     else                                                                
428     {              
429         via_ac = FIRST_PSEUDO_REGISTER -1;
430         
431         /* get ACs */
432         for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
433           if (df_regs_ever_live_p (i) && call_used_regs[i])
434                 via_ac = i;
435         
436         for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
437         {
438             if (LOAD_FPU_REG_P(i)
439                 && df_regs_ever_live_p (i)
440                 && ! call_used_regs[i])
441               fprintf(stream, "\tldd (sp)+, %s\n", reg_names[i]);
442             
443             if (NO_LOAD_FPU_REG_P(i)
444                 && df_regs_ever_live_p (i)
445                 && ! call_used_regs[i])
446             {
447                 gcc_assert (LOAD_FPU_REG_P(via_ac));
448                     
449                 fprintf(stream, "\tldd (sp)+, %s\n", reg_names[via_ac]);
450                 fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
451             }
452         }
453
454         for (i=7; i >= 0; i--)                                  
455           if (df_regs_ever_live_p (i) && !call_used_regs[i])            
456                 fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);     
457                                                                 
458         if (fsize)                                              
459             fprintf((stream), "\tadd $%#" HOST_WIDE_INT_PRINT "o, sp\n",
460                     (fsize)&0xffff);                    
461     }                   
462                                         
463     fprintf (stream, "\trts pc\n");                                     
464     fprintf (stream, "\t;/* end of epilogue*/\n\n\n");          
465 }
466
467 #endif /* !TWO_BSD */
468         
469 /* Return the best assembler insn template
470    for moving operands[1] into operands[0] as a fullword.  */
471 static const char *
472 singlemove_string (rtx *operands)
473 {
474   if (operands[1] != const0_rtx)
475     return "mov %1,%0";
476
477   return "clr %0";
478 }
479
480 \f
481 /* Output assembler code to perform a doubleword move insn
482    with operands OPERANDS.  */
483
484 const char *
485 output_move_double (rtx *operands)
486 {
487   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
488   rtx latehalf[2];
489   rtx addreg0 = 0, addreg1 = 0;
490
491   /* First classify both operands.  */
492
493   if (REG_P (operands[0]))
494     optype0 = REGOP;
495   else if (offsettable_memref_p (operands[0]))
496     optype0 = OFFSOP;
497   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
498     optype0 = POPOP;
499   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
500     optype0 = PUSHOP;
501   else if (GET_CODE (operands[0]) == MEM)
502     optype0 = MEMOP;
503   else
504     optype0 = RNDOP;
505
506   if (REG_P (operands[1]))
507     optype1 = REGOP;
508   else if (CONSTANT_P (operands[1])
509 #if 0
510            || GET_CODE (operands[1]) == CONST_DOUBLE
511 #endif
512            )
513     optype1 = CNSTOP;
514   else if (offsettable_memref_p (operands[1]))
515     optype1 = OFFSOP;
516   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
517     optype1 = POPOP;
518   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
519     optype1 = PUSHOP;
520   else if (GET_CODE (operands[1]) == MEM)
521     optype1 = MEMOP;
522   else
523     optype1 = RNDOP;
524
525   /* Check for the cases that the operand constraints are not
526      supposed to allow to happen.  Abort if we get one,
527      because generating code for these cases is painful.  */
528
529   gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
530
531   /* If one operand is decrementing and one is incrementing
532      decrement the former register explicitly
533      and change that operand into ordinary indexing.  */
534
535   if (optype0 == PUSHOP && optype1 == POPOP)
536     {
537       operands[0] = XEXP (XEXP (operands[0], 0), 0);
538       output_asm_insn ("sub $4,%0", operands);
539       operands[0] = gen_rtx_MEM (SImode, operands[0]);
540       optype0 = OFFSOP;
541     }
542   if (optype0 == POPOP && optype1 == PUSHOP)
543     {
544       operands[1] = XEXP (XEXP (operands[1], 0), 0);
545       output_asm_insn ("sub $4,%1", operands);
546       operands[1] = gen_rtx_MEM (SImode, operands[1]);
547       optype1 = OFFSOP;
548     }
549
550   /* If an operand is an unoffsettable memory ref, find a register
551      we can increment temporarily to make it refer to the second word.  */
552
553   if (optype0 == MEMOP)
554     addreg0 = find_addr_reg (XEXP (operands[0], 0));
555
556   if (optype1 == MEMOP)
557     addreg1 = find_addr_reg (XEXP (operands[1], 0));
558
559   /* Ok, we can do one word at a time.
560      Normally we do the low-numbered word first,
561      but if either operand is autodecrementing then we
562      do the high-numbered word first.
563
564      In either case, set up in LATEHALF the operands to use
565      for the high-numbered word and in some cases alter the
566      operands in OPERANDS to be suitable for the low-numbered word.  */
567
568   if (optype0 == REGOP)
569     latehalf[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
570   else if (optype0 == OFFSOP)
571     latehalf[0] = adjust_address (operands[0], HImode, 2);
572   else
573     latehalf[0] = operands[0];
574
575   if (optype1 == REGOP)
576     latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
577   else if (optype1 == OFFSOP)
578     latehalf[1] = adjust_address (operands[1], HImode, 2);
579   else if (optype1 == CNSTOP)
580     {
581         if (CONSTANT_P (operands[1]))
582         {
583             /* now the mess begins, high word is in lower word??? 
584
585                that's what ashc makes me think, but I don't remember :-( */
586             latehalf[1] = GEN_INT (INTVAL(operands[1]) >> 16);
587             operands[1] = GEN_INT (INTVAL(operands[1]) & 0xff);
588         }
589         else
590           /* immediate 32-bit values not allowed */
591           gcc_assert (GET_CODE (operands[1]) != CONST_DOUBLE);
592     }
593   else
594     latehalf[1] = operands[1];
595
596   /* If insn is effectively movd N(sp),-(sp) then we will do the
597      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
598      for the low word as well, to compensate for the first decrement of sp.  */
599   if (optype0 == PUSHOP
600       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
601       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
602     operands[1] = latehalf[1];
603
604   /* If one or both operands autodecrementing,
605      do the two words, high-numbered first.  */
606
607   /* Likewise,  the first move would clobber the source of the second one,
608      do them in the other order.  This happens only for registers;
609      such overlap can't happen in memory unless the user explicitly
610      sets it up, and that is an undefined circumstance.  */
611
612   if (optype0 == PUSHOP || optype1 == PUSHOP
613       || (optype0 == REGOP && optype1 == REGOP
614           && REGNO (operands[0]) == REGNO (latehalf[1])))
615     {
616       /* Make any unoffsettable addresses point at high-numbered word.  */
617       if (addreg0)
618         output_asm_insn ("add $2,%0", &addreg0);
619       if (addreg1)
620         output_asm_insn ("add $2,%0", &addreg1);
621
622       /* Do that word.  */
623       output_asm_insn (singlemove_string (latehalf), latehalf);
624
625       /* Undo the adds we just did.  */
626       if (addreg0)
627         output_asm_insn ("sub $2,%0", &addreg0);
628       if (addreg1)
629         output_asm_insn ("sub $2,%0", &addreg1);
630
631       /* Do low-numbered word.  */
632       return singlemove_string (operands);
633     }
634
635   /* Normal case: do the two words, low-numbered first.  */
636
637   output_asm_insn (singlemove_string (operands), operands);
638
639   /* Make any unoffsettable addresses point at high-numbered word.  */
640   if (addreg0)
641     output_asm_insn ("add $2,%0", &addreg0);
642   if (addreg1)
643     output_asm_insn ("add $2,%0", &addreg1);
644
645   /* Do that word.  */
646   output_asm_insn (singlemove_string (latehalf), latehalf);
647
648   /* Undo the adds we just did.  */
649   if (addreg0)
650     output_asm_insn ("sub $2,%0", &addreg0);
651   if (addreg1)
652     output_asm_insn ("sub $2,%0", &addreg1);
653
654   return "";
655 }
656 /* Output assembler code to perform a quadword move insn
657    with operands OPERANDS.  */
658
659 const char *
660 output_move_quad (rtx *operands)
661 {
662   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
663   rtx latehalf[2];
664   rtx addreg0 = 0, addreg1 = 0;
665
666   output_asm_insn(";/* movdi/df: %1 -> %0 */", operands);
667   
668   if (REG_P (operands[0]))
669     optype0 = REGOP;
670   else if (offsettable_memref_p (operands[0]))
671     optype0 = OFFSOP;
672   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
673     optype0 = POPOP;
674   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
675     optype0 = PUSHOP;
676   else if (GET_CODE (operands[0]) == MEM)
677     optype0 = MEMOP;
678   else
679     optype0 = RNDOP;
680
681   if (REG_P (operands[1]))
682     optype1 = REGOP;
683   else if (CONSTANT_P (operands[1])
684            || GET_CODE (operands[1]) == CONST_DOUBLE)
685     optype1 = CNSTOP;
686   else if (offsettable_memref_p (operands[1]))
687     optype1 = OFFSOP;
688   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
689     optype1 = POPOP;
690   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
691     optype1 = PUSHOP;
692   else if (GET_CODE (operands[1]) == MEM)
693     optype1 = MEMOP;
694   else
695     optype1 = RNDOP;
696
697   /* Check for the cases that the operand constraints are not
698      supposed to allow to happen.  Abort if we get one,
699      because generating code for these cases is painful.  */
700
701   gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
702   
703   /* check if we move a CPU reg to an FPU reg, or vice versa! */
704   if (optype0 == REGOP && optype1 == REGOP)
705       /* bogus - 64 bit cannot reside in CPU! */
706       gcc_assert (!CPU_REG_P(REGNO(operands[0]))
707                   && !CPU_REG_P (REGNO(operands[1])));
708   
709   if (optype0 == REGOP || optype1 == REGOP)
710   {
711       /* check for use of clrd???? 
712          if you ever allow ac4 and ac5 (now we require secondary load) 
713          you must check whether 
714          you want to load into them or store from them - 
715          then dump ac0 into $help$ movce ac4/5 to ac0, do the 
716          store from ac0, and restore ac0 - if you can find 
717          an unused ac[0-3], use that and you save a store and a load!*/
718
719       if (FPU_REG_P(REGNO(operands[0])))
720       {
721           if (GET_CODE(operands[1]) == CONST_DOUBLE)
722           {
723               REAL_VALUE_TYPE r;
724               REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
725
726               if (REAL_VALUES_EQUAL (r, dconst0))
727                   return "{clrd|clrf} %0";
728           }
729               
730           return "{ldd|movf} %1, %0";
731       }
732       
733       if (FPU_REG_P(REGNO(operands[1])))
734           return "{std|movf} %1, %0";
735   }
736       
737   /* If one operand is decrementing and one is incrementing
738      decrement the former register explicitly
739      and change that operand into ordinary indexing.  */
740
741   if (optype0 == PUSHOP && optype1 == POPOP)
742     {
743       operands[0] = XEXP (XEXP (operands[0], 0), 0);
744       output_asm_insn ("sub $8,%0", operands);
745       operands[0] = gen_rtx_MEM (DImode, operands[0]);
746       optype0 = OFFSOP;
747     }
748   if (optype0 == POPOP && optype1 == PUSHOP)
749     {
750       operands[1] = XEXP (XEXP (operands[1], 0), 0);
751       output_asm_insn ("sub $8,%1", operands);
752       operands[1] = gen_rtx_MEM (SImode, operands[1]);
753       optype1 = OFFSOP;
754     }
755
756   /* If an operand is an unoffsettable memory ref, find a register
757      we can increment temporarily to make it refer to the second word.  */
758
759   if (optype0 == MEMOP)
760     addreg0 = find_addr_reg (XEXP (operands[0], 0));
761
762   if (optype1 == MEMOP)
763     addreg1 = find_addr_reg (XEXP (operands[1], 0));
764
765   /* Ok, we can do one word at a time.
766      Normally we do the low-numbered word first,
767      but if either operand is autodecrementing then we
768      do the high-numbered word first.
769
770      In either case, set up in LATEHALF the operands to use
771      for the high-numbered word and in some cases alter the
772      operands in OPERANDS to be suitable for the low-numbered word.  */
773
774   if (optype0 == REGOP)
775     latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
776   else if (optype0 == OFFSOP)
777     latehalf[0] = adjust_address (operands[0], SImode, 4);
778   else
779     latehalf[0] = operands[0];
780
781   if (optype1 == REGOP)
782     latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
783   else if (optype1 == OFFSOP)
784     latehalf[1] = adjust_address (operands[1], SImode, 4);
785   else if (optype1 == CNSTOP)
786     {
787       if (GET_CODE (operands[1]) == CONST_DOUBLE)
788         {
789           REAL_VALUE_TYPE r;
790           long dval[2];
791           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
792           REAL_VALUE_TO_TARGET_DOUBLE (r, dval);
793           latehalf[1] = GEN_INT (dval[1]);
794           operands[1] = GEN_INT (dval[0]);
795         }
796       else if (GET_CODE(operands[1]) == CONST_INT)
797         {
798           latehalf[1] = const0_rtx;
799         }
800       else
801         gcc_unreachable ();
802     }
803   else
804     latehalf[1] = operands[1];
805
806   /* If insn is effectively movd N(sp),-(sp) then we will do the
807      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
808      for the low word as well, to compensate for the first decrement of sp.  */
809   if (optype0 == PUSHOP
810       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
811       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
812     operands[1] = latehalf[1];
813
814   /* If one or both operands autodecrementing,
815      do the two words, high-numbered first.  */
816
817   /* Likewise,  the first move would clobber the source of the second one,
818      do them in the other order.  This happens only for registers;
819      such overlap can't happen in memory unless the user explicitly
820      sets it up, and that is an undefined circumstance.  */
821
822   if (optype0 == PUSHOP || optype1 == PUSHOP
823       || (optype0 == REGOP && optype1 == REGOP
824           && REGNO (operands[0]) == REGNO (latehalf[1])))
825     {
826       /* Make any unoffsettable addresses point at high-numbered word.  */
827       if (addreg0)
828         output_asm_insn ("add $4,%0", &addreg0);
829       if (addreg1)
830         output_asm_insn ("add $4,%0", &addreg1);
831
832       /* Do that word.  */
833       output_asm_insn(output_move_double(latehalf), latehalf);
834
835       /* Undo the adds we just did.  */
836       if (addreg0)
837         output_asm_insn ("sub $4,%0", &addreg0);
838       if (addreg1)
839         output_asm_insn ("sub $4,%0", &addreg1);
840
841       /* Do low-numbered word.  */
842       return output_move_double (operands);
843     }
844
845   /* Normal case: do the two words, low-numbered first.  */
846
847   output_asm_insn (output_move_double (operands), operands);
848
849   /* Make any unoffsettable addresses point at high-numbered word.  */
850   if (addreg0)
851     output_asm_insn ("add $4,%0", &addreg0);
852   if (addreg1)
853     output_asm_insn ("add $4,%0", &addreg1);
854
855   /* Do that word.  */
856   output_asm_insn (output_move_double (latehalf), latehalf);
857
858   /* Undo the adds we just did.  */
859   if (addreg0)
860     output_asm_insn ("sub $4,%0", &addreg0);
861   if (addreg1)
862     output_asm_insn ("sub $4,%0", &addreg1);
863
864   return "";
865 }
866
867 \f
868 /* Return a REG that occurs in ADDR with coefficient 1.
869    ADDR can be effectively incremented by incrementing REG.  */
870
871 static rtx
872 find_addr_reg (rtx addr)
873 {
874   while (GET_CODE (addr) == PLUS)
875     {
876       if (GET_CODE (XEXP (addr, 0)) == REG)
877         addr = XEXP (addr, 0);
878       if (GET_CODE (XEXP (addr, 1)) == REG)
879         addr = XEXP (addr, 1);
880       if (CONSTANT_P (XEXP (addr, 0)))
881         addr = XEXP (addr, 1);
882       if (CONSTANT_P (XEXP (addr, 1)))
883         addr = XEXP (addr, 0);
884     }
885   if (GET_CODE (addr) == REG)
886     return addr;
887   return 0;
888 }
889 \f
890 /* Output an ascii string.  */
891 void
892 output_ascii (FILE *file, const char *p, int size)
893 {
894   int i;
895
896   /* This used to output .byte "string", which doesn't work with the UNIX
897      assembler and I think not with DEC ones either.  */
898   fprintf (file, "\t.byte ");
899
900   for (i = 0; i < size; i++)
901     {
902       register int c = p[i];
903       if (c < 0)
904         c += 256;
905       fprintf (file, "%#o", c);
906       if (i < size - 1)
907         putc (',', file);
908     }
909   putc ('\n', file);
910 }
911
912
913 /* --- stole from out-vax, needs changes */
914
915 void
916 print_operand_address (FILE *file, register rtx addr)
917 {
918   register rtx reg1, reg2, breg, ireg;
919   rtx offset;
920
921  retry:
922
923   switch (GET_CODE (addr))
924     {
925     case MEM:
926       if (TARGET_UNIX_ASM)
927         fprintf (file, "*");
928       else
929         fprintf (file, "@");
930       addr = XEXP (addr, 0);
931       goto retry;
932
933     case REG:
934       fprintf (file, "(%s)", reg_names[REGNO (addr)]);
935       break;
936
937     case PRE_MODIFY:
938     case PRE_DEC:
939       fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
940       break;
941
942     case POST_MODIFY:
943     case POST_INC:
944       fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
945       break;
946
947     case PLUS:
948       reg1 = 0; reg2 = 0;
949       ireg = 0; breg = 0;
950       offset = 0;
951       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
952           || GET_CODE (XEXP (addr, 0)) == MEM)
953         {
954           offset = XEXP (addr, 0);
955           addr = XEXP (addr, 1);
956         }
957       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
958                || GET_CODE (XEXP (addr, 1)) == MEM)
959         {
960           offset = XEXP (addr, 1);
961           addr = XEXP (addr, 0);
962         }
963       if (GET_CODE (addr) != PLUS)
964         ;
965       else if (GET_CODE (XEXP (addr, 0)) == MULT)
966         {
967           reg1 = XEXP (addr, 0);
968           addr = XEXP (addr, 1);
969         }
970       else if (GET_CODE (XEXP (addr, 1)) == MULT)
971         {
972           reg1 = XEXP (addr, 1);
973           addr = XEXP (addr, 0);
974         }
975       else if (GET_CODE (XEXP (addr, 0)) == REG)
976         {
977           reg1 = XEXP (addr, 0);
978           addr = XEXP (addr, 1);
979         }
980       else if (GET_CODE (XEXP (addr, 1)) == REG)
981         {
982           reg1 = XEXP (addr, 1);
983           addr = XEXP (addr, 0);
984         }
985       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
986         {
987           if (reg1 == 0)
988             reg1 = addr;
989           else
990             reg2 = addr;
991           addr = 0;
992         }
993       if (offset != 0)
994         {
995           gcc_assert (addr == 0);
996           addr = offset;
997         }
998       if (reg1 != 0 && GET_CODE (reg1) == MULT)
999         {
1000           breg = reg2;
1001           ireg = reg1;
1002         }
1003       else if (reg2 != 0 && GET_CODE (reg2) == MULT)
1004         {
1005           breg = reg1;
1006           ireg = reg2;
1007         }
1008       else if (reg2 != 0 || GET_CODE (addr) == MEM)
1009         {
1010           breg = reg2;
1011           ireg = reg1;
1012         }
1013       else
1014         {
1015           breg = reg1;
1016           ireg = reg2;
1017         }
1018       if (addr != 0)
1019         output_address (addr);
1020       if (breg != 0)
1021         {
1022           gcc_assert (GET_CODE (breg) == REG);
1023           fprintf (file, "(%s)", reg_names[REGNO (breg)]);
1024         }
1025       if (ireg != 0)
1026         {
1027           if (GET_CODE (ireg) == MULT)
1028             ireg = XEXP (ireg, 0);
1029           gcc_assert (GET_CODE (ireg) == REG);
1030           gcc_unreachable(); /* ??? */
1031           fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
1032         }
1033       break;
1034
1035     default:
1036       output_addr_const_pdp11 (file, addr);
1037     }
1038 }
1039
1040 /* Target hook to assemble integer objects.  We need to use the
1041    pdp-specific version of output_addr_const.  */
1042
1043 static bool
1044 pdp11_assemble_integer (rtx x, unsigned int size, int aligned_p)
1045 {
1046   if (aligned_p)
1047     switch (size)
1048       {
1049       case 1:
1050         fprintf (asm_out_file, "\t.byte\t");
1051         output_addr_const_pdp11 (asm_out_file, x);
1052         fprintf (asm_out_file, " /* char */\n");
1053         return true;
1054
1055       case 2:
1056         fprintf (asm_out_file, TARGET_UNIX_ASM ? "\t" : "\t.word\t");
1057         output_addr_const_pdp11 (asm_out_file, x);
1058         fprintf (asm_out_file, " /* short */\n");
1059         return true;
1060       }
1061   return default_assemble_integer (x, size, aligned_p);
1062 }
1063
1064
1065 /* register move costs, indexed by regs */
1066
1067 static const int move_costs[N_REG_CLASSES][N_REG_CLASSES] = 
1068 {
1069              /* NO  MUL  GEN  LFPU  NLFPU FPU ALL */
1070
1071 /* NO */     {  0,   0,   0,    0,    0,    0,   0},
1072 /* MUL */    {  0,   2,   2,   10,   22,   22,  22},
1073 /* GEN */    {  0,   2,   2,   10,   22,   22,  22},
1074 /* LFPU */   {  0,  10,  10,    2,    2,    2,  10},
1075 /* NLFPU */  {  0,  22,  22,    2,    2,    2,  22},
1076 /* FPU */    {  0,  22,  22,    2,    2,    2,  22},
1077 /* ALL */    {  0,  22,  22,   10,   22,   22,  22}
1078 }  ;
1079
1080
1081 /* -- note that some moves are tremendously expensive, 
1082    because they require lots of tricks! do we have to 
1083    charge the costs incurred by secondary reload class 
1084    -- as we do here with 22 -- or not ? */
1085
1086 int 
1087 register_move_cost(enum reg_class c1, enum reg_class c2)
1088 {
1089     return move_costs[(int)c1][(int)c2];
1090 }
1091
1092 static bool
1093 pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
1094 {
1095   switch (code)
1096     {
1097     case CONST_INT:
1098       if (INTVAL (x) == 0 || INTVAL (x) == -1 || INTVAL (x) == 1)
1099         {
1100           *total = 0;
1101           return true;
1102         }
1103       /* FALLTHRU */
1104
1105     case CONST:
1106     case LABEL_REF:
1107     case SYMBOL_REF:
1108       /* Twice as expensive as REG.  */
1109       *total = 2;
1110       return true;
1111
1112     case CONST_DOUBLE:
1113       /* Twice (or 4 times) as expensive as 16 bit.  */
1114       *total = 4;
1115       return true;
1116
1117     case MULT:
1118       /* ??? There is something wrong in MULT because MULT is not 
1119          as cheap as total = 2 even if we can shift!  */
1120       /* If optimizing for size make mult etc cheap, but not 1, so when 
1121          in doubt the faster insn is chosen.  */
1122       if (optimize_size)
1123         *total = COSTS_N_INSNS (2);
1124       else
1125         *total = COSTS_N_INSNS (11);
1126       return false;
1127
1128     case DIV:
1129       if (optimize_size)
1130         *total = COSTS_N_INSNS (2);
1131       else
1132         *total = COSTS_N_INSNS (25);
1133       return false;
1134
1135     case MOD:
1136       if (optimize_size)
1137         *total = COSTS_N_INSNS (2);
1138       else
1139         *total = COSTS_N_INSNS (26);
1140       return false;
1141
1142     case ABS:
1143       /* Equivalent to length, so same for optimize_size.  */
1144       *total = COSTS_N_INSNS (3);
1145       return false;
1146
1147     case ZERO_EXTEND:
1148       /* Only used for qi->hi.  */
1149       *total = COSTS_N_INSNS (1);
1150       return false;
1151
1152     case SIGN_EXTEND:
1153       if (GET_MODE (x) == HImode)
1154         *total = COSTS_N_INSNS (1);
1155       else if (GET_MODE (x) == SImode)
1156         *total = COSTS_N_INSNS (6);
1157       else
1158         *total = COSTS_N_INSNS (2);
1159       return false;
1160
1161     case ASHIFT:
1162     case LSHIFTRT:
1163     case ASHIFTRT:
1164       if (optimize_size)
1165         *total = COSTS_N_INSNS (1);
1166       else if (GET_MODE (x) ==  QImode)
1167         {
1168           if (GET_CODE (XEXP (x, 1)) != CONST_INT)
1169             *total = COSTS_N_INSNS (8); /* worst case */
1170           else
1171             *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
1172         }
1173       else if (GET_MODE (x) == HImode)
1174         {
1175           if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1176             {
1177               if (abs (INTVAL (XEXP (x, 1))) == 1)
1178                 *total = COSTS_N_INSNS (1);
1179               else
1180                 *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
1181             }
1182           else
1183             *total = COSTS_N_INSNS (10); /* worst case */
1184         }
1185       else if (GET_MODE (x) == SImode)
1186         {
1187           if (GET_CODE (XEXP (x, 1)) == CONST_INT)
1188             *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
1189           else /* worst case */
1190             *total = COSTS_N_INSNS (18);
1191         }
1192       return false;
1193
1194     default:
1195       return false;
1196     }
1197 }
1198
1199 const char *
1200 output_jump (const char *pos, const char *neg, int length)
1201 {
1202     static int x = 0;
1203     
1204     static char buf[1000];
1205
1206 #if 0
1207 /* currently we don't need this, because the tstdf and cmpdf 
1208    copy the condition code immediately, and other float operations are not 
1209    yet recognized as changing the FCC - if so, then the length-cost of all
1210    jump insns increases by one, because we have to potentially copy the 
1211    FCC! */
1212     if (cc_status.flags & CC_IN_FPU)
1213         output_asm_insn("cfcc", NULL);
1214 #endif
1215         
1216     switch (length)
1217     {
1218       case 1:
1219         
1220         strcpy(buf, pos);
1221         strcat(buf, " %l0");
1222         
1223         return buf;
1224         
1225       case 3:
1226         
1227         sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x);
1228         
1229         x++;
1230         
1231         return buf;
1232         
1233       default:
1234         
1235         gcc_unreachable ();
1236     }
1237     
1238 }
1239
1240 void
1241 notice_update_cc_on_set(rtx exp, rtx insn ATTRIBUTE_UNUSED)
1242 {
1243     if (GET_CODE (SET_DEST (exp)) == CC0)
1244     { 
1245         cc_status.flags = 0;                                    
1246         cc_status.value1 = SET_DEST (exp);                      
1247         cc_status.value2 = SET_SRC (exp);                       
1248
1249 /*
1250         if (GET_MODE(SET_SRC(exp)) == DFmode)
1251             cc_status.flags |= CC_IN_FPU;
1252 */      
1253     }                                                   
1254     else if ((GET_CODE (SET_DEST (exp)) == REG          
1255               || GET_CODE (SET_DEST (exp)) == MEM)              
1256              && GET_CODE (SET_SRC (exp)) != PC          
1257              && (GET_MODE (SET_DEST(exp)) == HImode             
1258                  || GET_MODE (SET_DEST(exp)) == QImode) 
1259                 && (GET_CODE (SET_SRC(exp)) == PLUS             
1260                     || GET_CODE (SET_SRC(exp)) == MINUS 
1261                     || GET_CODE (SET_SRC(exp)) == AND   
1262                     || GET_CODE (SET_SRC(exp)) == IOR   
1263                     || GET_CODE (SET_SRC(exp)) == XOR   
1264                     || GET_CODE (SET_SRC(exp)) == NOT   
1265                     || GET_CODE (SET_SRC(exp)) == NEG   
1266                         || GET_CODE (SET_SRC(exp)) == REG       
1267                     || GET_CODE (SET_SRC(exp)) == MEM)) 
1268     { 
1269         cc_status.flags = 0;                                    
1270         cc_status.value1 = SET_SRC (exp);                       
1271         cc_status.value2 = SET_DEST (exp);                      
1272         
1273         if (cc_status.value1 && GET_CODE (cc_status.value1) == REG      
1274             && cc_status.value2                                 
1275             && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
1276             cc_status.value2 = 0;                                       
1277         if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM      
1278             && cc_status.value2                                 
1279             && GET_CODE (cc_status.value2) == MEM)                      
1280             cc_status.value2 = 0;                                       
1281     }                                                   
1282     else if (GET_CODE (SET_SRC (exp)) == CALL)          
1283     { 
1284         CC_STATUS_INIT; 
1285     }
1286     else if (GET_CODE (SET_DEST (exp)) == REG)                  
1287         /* what's this ? */                                     
1288     { 
1289         if ((cc_status.value1                                   
1290              && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)))
1291             cc_status.value1 = 0;                               
1292         if ((cc_status.value2                                   
1293              && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)))
1294             cc_status.value2 = 0;                               
1295     }                                                   
1296     else if (SET_DEST(exp) == pc_rtx)
1297     { 
1298         /* jump */
1299     }
1300     else /* if (GET_CODE (SET_DEST (exp)) == MEM)       */      
1301     {  
1302         /* the last else is a bit paranoiac, but since nearly all instructions 
1303            play with condition codes, it's reasonable! */
1304
1305         CC_STATUS_INIT; /* paranoia*/ 
1306     }                   
1307 }
1308
1309
1310 int
1311 simple_memory_operand(rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
1312 {
1313     rtx addr;
1314
1315     /* Eliminate non-memory operations */
1316     if (GET_CODE (op) != MEM)
1317         return FALSE;
1318
1319 #if 0
1320     /* dword operations really put out 2 instructions, so eliminate them.  */
1321     if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
1322         return FALSE;
1323 #endif
1324
1325     /* Decode the address now.  */
1326
1327   indirection:
1328     
1329     addr = XEXP (op, 0);
1330
1331     switch (GET_CODE (addr))
1332     {
1333       case REG:
1334         /* (R0) - no extra cost */
1335         return 1;
1336         
1337       case PRE_DEC:
1338       case POST_INC:
1339         /* -(R0), (R0)+ - cheap! */
1340         return 0;
1341         
1342       case MEM:
1343         /* cheap - is encoded in addressing mode info! 
1344
1345            -- except for @(R0), which has to be @0(R0) !!! */
1346
1347         if (GET_CODE (XEXP (addr, 0)) == REG)
1348             return 0;
1349         
1350         op=addr;
1351         goto indirection;
1352         
1353       case CONST_INT:
1354       case LABEL_REF:          
1355       case CONST:
1356       case SYMBOL_REF:
1357         /* @#address - extra cost */
1358         return 0;
1359
1360       case PLUS:
1361         /* X(R0) - extra cost */
1362         return 0;
1363
1364       default:
1365         break;
1366     }
1367     
1368     return FALSE;
1369 }
1370
1371
1372 /*
1373  * output a block move:
1374  *
1375  * operands[0]  ... to
1376  * operands[1]  ... from
1377  * operands[2]  ... length
1378  * operands[3]  ... alignment
1379  * operands[4]  ... scratch register
1380  */
1381
1382  
1383 const char *
1384 output_block_move(rtx *operands)
1385 {
1386     static int count = 0;
1387     char buf[200];
1388     
1389     if (GET_CODE(operands[2]) == CONST_INT
1390         && ! optimize_size)
1391     {
1392         if (INTVAL(operands[2]) < 16
1393             && INTVAL(operands[3]) == 1)
1394         {
1395             register int i;
1396             
1397             for (i = 1; i <= INTVAL(operands[2]); i++)
1398                 output_asm_insn("movb (%1)+, (%0)+", operands);
1399
1400             return "";
1401         }
1402         else if (INTVAL(operands[2]) < 32)
1403         {
1404             register int i;
1405             
1406             for (i = 1; i <= INTVAL(operands[2])/2; i++)
1407                 output_asm_insn("mov (%1)+, (%0)+", operands);
1408             
1409             /* may I assume that moved quantity is 
1410                multiple of alignment ???
1411
1412                I HOPE SO !
1413             */
1414
1415             return "";
1416         }
1417         
1418
1419         /* can do other clever things, maybe... */
1420     }
1421
1422     if (CONSTANT_P(operands[2]) )
1423     {
1424         /* just move count to scratch */
1425         output_asm_insn("mov %2, %4", operands);
1426     }
1427     else
1428     {
1429         /* just clobber the register */
1430         operands[4] = operands[2];
1431     }
1432     
1433
1434     /* switch over alignment */
1435     switch (INTVAL(operands[3]))
1436     {
1437       case 1:
1438         
1439         /* 
1440           x:
1441           movb (%1)+, (%0)+
1442           
1443           if (TARGET_45)
1444              sob %4,x
1445           else
1446              dec %4
1447              bgt x
1448
1449         */
1450
1451         sprintf(buf, "\nmovestrhi%d:", count);
1452         output_asm_insn(buf, NULL);
1453         
1454         output_asm_insn("movb (%1)+, (%0)+", operands);
1455         
1456         if (TARGET_45)
1457         {
1458             sprintf(buf, "sob %%4, movestrhi%d", count);
1459             output_asm_insn(buf, operands);
1460         }
1461         else
1462         {
1463             output_asm_insn("dec %4", operands);
1464             
1465             sprintf(buf, "bgt movestrhi%d", count);
1466             output_asm_insn(buf, NULL);
1467         }
1468         
1469         count ++;
1470         break;
1471         
1472       case 2:
1473         
1474         /* 
1475            asr %4
1476
1477            x:
1478
1479            mov (%1)+, (%0)+
1480
1481            if (TARGET_45)
1482              sob %4, x
1483            else
1484              dec %4
1485              bgt x
1486         */
1487
1488       generate_compact_code:
1489
1490         output_asm_insn("asr %4", operands);
1491
1492         sprintf(buf, "\nmovestrhi%d:", count);
1493         output_asm_insn(buf, NULL);
1494         
1495         output_asm_insn("mov (%1)+, (%0)+", operands);
1496         
1497         if (TARGET_45)
1498         {
1499             sprintf(buf, "sob %%4, movestrhi%d", count);
1500             output_asm_insn(buf, operands);
1501         }
1502         else
1503         {
1504             output_asm_insn("dec %4", operands);
1505             
1506             sprintf(buf, "bgt movestrhi%d", count);
1507             output_asm_insn(buf, NULL);
1508         }
1509         
1510         count ++;
1511         break;
1512
1513       case 4:
1514         
1515         /*
1516
1517            asr %4
1518            asr %4
1519
1520            x:
1521
1522            mov (%1)+, (%0)+
1523            mov (%1)+, (%0)+
1524
1525            if (TARGET_45)
1526              sob %4, x
1527            else
1528              dec %4
1529              bgt x
1530         */
1531
1532         if (optimize_size)
1533             goto generate_compact_code;
1534         
1535         output_asm_insn("asr %4", operands);
1536         output_asm_insn("asr %4", operands);
1537
1538         sprintf(buf, "\nmovestrhi%d:", count);
1539         output_asm_insn(buf, NULL);
1540         
1541         output_asm_insn("mov (%1)+, (%0)+", operands);
1542         output_asm_insn("mov (%1)+, (%0)+", operands);
1543         
1544         if (TARGET_45)
1545         {
1546             sprintf(buf, "sob %%4, movestrhi%d", count);
1547             output_asm_insn(buf, operands);
1548         }
1549         else
1550         {
1551             output_asm_insn("dec %4", operands);
1552             
1553             sprintf(buf, "bgt movestrhi%d", count);
1554             output_asm_insn(buf, NULL);
1555         }
1556         
1557         count ++;
1558         break;
1559        
1560       default:
1561         
1562         /*
1563            
1564            asr %4
1565            asr %4
1566            asr %4
1567
1568            x:
1569
1570            mov (%1)+, (%0)+
1571            mov (%1)+, (%0)+
1572            mov (%1)+, (%0)+
1573            mov (%1)+, (%0)+
1574            
1575            if (TARGET_45)
1576              sob %4, x
1577            else
1578              dec %4
1579              bgt x
1580         */
1581
1582
1583         if (optimize_size)
1584             goto generate_compact_code;
1585         
1586         output_asm_insn("asr %4", operands);
1587         output_asm_insn("asr %4", operands);
1588         output_asm_insn("asr %4", operands);
1589
1590         sprintf(buf, "\nmovestrhi%d:", count);
1591         output_asm_insn(buf, NULL);
1592         
1593         output_asm_insn("mov (%1)+, (%0)+", operands);
1594         output_asm_insn("mov (%1)+, (%0)+", operands);
1595         output_asm_insn("mov (%1)+, (%0)+", operands);
1596         output_asm_insn("mov (%1)+, (%0)+", operands);
1597         
1598         if (TARGET_45)
1599         {
1600             sprintf(buf, "sob %%4, movestrhi%d", count);
1601             output_asm_insn(buf, operands);
1602         }
1603         else
1604         {
1605             output_asm_insn("dec %4", operands);
1606             
1607             sprintf(buf, "bgt movestrhi%d", count);
1608             output_asm_insn(buf, NULL);
1609         }
1610         
1611         count ++;
1612         break;
1613         
1614         ;
1615         
1616     }
1617     
1618     return "";
1619 }
1620
1621 int
1622 legitimate_address_p (enum machine_mode mode, rtx address)
1623 {
1624 /* #define REG_OK_STRICT */
1625     GO_IF_LEGITIMATE_ADDRESS(mode, address, win);
1626     
1627     return 0;
1628     
1629   win:
1630     return 1;
1631
1632 /* #undef REG_OK_STRICT */
1633 }
1634
1635 /* This function checks whether a real value can be encoded as
1636    a literal, i.e., addressing mode 27.  In that mode, real values
1637    are one word values, so the remaining 48 bits have to be zero.  */
1638 int
1639 legitimate_const_double_p (rtx address)
1640 {
1641   REAL_VALUE_TYPE r;
1642   long sval[2];
1643   REAL_VALUE_FROM_CONST_DOUBLE (r, address);
1644   REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
1645   if ((sval[0] & 0xffff) == 0 && sval[1] == 0)
1646     return 1;
1647   return 0;
1648 }
1649
1650 /* A copy of output_addr_const modified for pdp11 expression syntax.
1651    output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
1652    use, and for debugging output, which we don't support with this port either.
1653    So this copy should get called whenever needed.
1654 */
1655 void
1656 output_addr_const_pdp11 (FILE *file, rtx x)
1657 {
1658   char buf[256];
1659
1660  restart:
1661   switch (GET_CODE (x))
1662     {
1663     case PC:
1664       gcc_assert (flag_pic);
1665       putc ('.', file);
1666       break;
1667
1668     case SYMBOL_REF:
1669       assemble_name (file, XSTR (x, 0));
1670       break;
1671
1672     case LABEL_REF:
1673       ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
1674       assemble_name (file, buf);
1675       break;
1676
1677     case CODE_LABEL:
1678       ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
1679       assemble_name (file, buf);
1680       break;
1681
1682     case CONST_INT:
1683       /* Should we check for constants which are too big?  Maybe cutting
1684          them off to 16 bits is OK?  */
1685       fprintf (file, "%#ho", (unsigned short) INTVAL (x));
1686       break;
1687
1688     case CONST:
1689       /* This used to output parentheses around the expression,
1690          but that does not work on the 386 (either ATT or BSD assembler).  */
1691       output_addr_const_pdp11 (file, XEXP (x, 0));
1692       break;
1693
1694     case CONST_DOUBLE:
1695       if (GET_MODE (x) == VOIDmode)
1696         {
1697           /* We can use %o if the number is one word and positive.  */
1698           gcc_assert (!CONST_DOUBLE_HIGH (x));
1699           fprintf (file, "%#ho", (unsigned short) CONST_DOUBLE_LOW (x));
1700         }
1701       else
1702         /* We can't handle floating point constants;
1703            PRINT_OPERAND must handle them.  */
1704         output_operand_lossage ("floating constant misused");
1705       break;
1706
1707     case PLUS:
1708       /* Some assemblers need integer constants to appear last (e.g. masm).  */
1709       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
1710         {
1711           output_addr_const_pdp11 (file, XEXP (x, 1));
1712           if (INTVAL (XEXP (x, 0)) >= 0)
1713             fprintf (file, "+");
1714           output_addr_const_pdp11 (file, XEXP (x, 0));
1715         }
1716       else
1717         {
1718           output_addr_const_pdp11 (file, XEXP (x, 0));
1719           if (INTVAL (XEXP (x, 1)) >= 0)
1720             fprintf (file, "+");
1721           output_addr_const_pdp11 (file, XEXP (x, 1));
1722         }
1723       break;
1724
1725     case MINUS:
1726       /* Avoid outputting things like x-x or x+5-x,
1727          since some assemblers can't handle that.  */
1728       x = simplify_subtraction (x);
1729       if (GET_CODE (x) != MINUS)
1730         goto restart;
1731
1732       output_addr_const_pdp11 (file, XEXP (x, 0));
1733       fprintf (file, "-");
1734       if (GET_CODE (XEXP (x, 1)) == CONST_INT
1735           && INTVAL (XEXP (x, 1)) < 0)
1736         {
1737           fprintf (file, targetm.asm_out.open_paren);
1738           output_addr_const_pdp11 (file, XEXP (x, 1));
1739           fprintf (file, targetm.asm_out.close_paren);
1740         }
1741       else
1742         output_addr_const_pdp11 (file, XEXP (x, 1));
1743       break;
1744
1745     case ZERO_EXTEND:
1746     case SIGN_EXTEND:
1747       output_addr_const_pdp11 (file, XEXP (x, 0));
1748       break;
1749
1750     default:
1751       output_operand_lossage ("invalid expression as operand");
1752     }
1753 }
1754
1755 /* Worker function for TARGET_RETURN_IN_MEMORY.  */
1756
1757 static bool
1758 pdp11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1759 {
1760   /* Should probably return DImode and DFmode in memory, lest
1761      we fill up all regs!
1762
1763      have to, else we crash - exception: maybe return result in 
1764      ac0 if DFmode and FPU present - compatibility problem with
1765      libraries for non-floating point....  */
1766   return (TYPE_MODE (type) == DImode
1767           || (TYPE_MODE (type) == DFmode && ! TARGET_AC0));
1768 }