OSDN Git Service

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