OSDN Git Service

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