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
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 3, or (at your option)
11any later version.
12
13GCC is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along 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 */
52int current_first_parm_offset;
53
54/* Routines to encode/decode pdp11 floats */
55static void encode_pdp11_f (const struct real_format *fmt,
56			    long *, const REAL_VALUE_TYPE *);
57static void decode_pdp11_f (const struct real_format *,
58			    REAL_VALUE_TYPE *, const long *);
59static void encode_pdp11_d (const struct real_format *fmt,
60			    long *, const REAL_VALUE_TYPE *);
61static 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.  */
66const 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
87const 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
108static void
109encode_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
116static void
117decode_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
125static void
126encode_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
134static void
135decode_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
147static bool pdp11_handle_option (size_t, const char *, int);
148static rtx find_addr_reg (rtx);
149static const char *singlemove_string (rtx *);
150static bool pdp11_assemble_integer (rtx, unsigned int, int);
151static void pdp11_output_function_prologue (FILE *, HOST_WIDE_INT);
152static void pdp11_output_function_epilogue (FILE *, HOST_WIDE_INT);
153static bool pdp11_rtx_costs (rtx, int, int, int *, bool);
154static bool pdp11_return_in_memory (const_tree, const_tree);
155static 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
192struct gcc_target targetm = TARGET_INITIALIZER;
193
194/* Implement TARGET_HANDLE_OPTION.  */
195
196static bool
197pdp11_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
213int
214arith_operand (rtx op, enum machine_mode mode)
215{
216  return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
217}
218
219int
220const_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
221{
222  return (GET_CODE (op) == CONST_INT);
223}
224
225int
226immediate15_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
227{
228    return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
229}
230
231int
232expand_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
248static void
249pdp11_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
340static void
341pdp11_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.  */
447static const char *
448singlemove_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
460const char *
461output_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
635const char *
636output_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
847static rtx
848find_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.  */
867void
868output_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
891void
892print_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
1019static bool
1020pdp11_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
1043static 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
1062int
1063register_move_cost(enum reg_class c1, enum reg_class c2)
1064{
1065    return move_costs[(int)c1][(int)c2];
1066}
1067
1068static bool
1069pdp11_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
1176const char *
1177output_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
1232void
1233notice_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
1302int
1303simple_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
1375const char *
1376output_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.  */
1616int
1617legitimate_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*/
1633void
1634output_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
1735static bool
1736pdp11_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
1759static void
1760pdp11_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