OSDN Git Service

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