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