OSDN Git Service

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