comparison gcc/config/pdp11/pdp11.c @ 0:a06113de4d67

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