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