OSDN Git Service

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