OSDN Git Service

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