OSDN Git Service

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