OSDN Git Service

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