]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/pa/pa.c
(print_operand_address): A patch for 2.5.8 ended up at the wrong
[thirdparty/gcc.git] / gcc / config / pa / pa.c
CommitLineData
87ad11b0 1/* Subroutines for insn-output.c for HPPA.
6c640a06 2 Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
87ad11b0 3 Contributed by Tim Moore (moore@cs.utah.edu), based on sparc.c
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21#include <stdio.h>
22#include "config.h"
23#include "rtl.h"
24#include "regs.h"
25#include "hard-reg-set.h"
26#include "real.h"
27#include "insn-config.h"
28#include "conditions.h"
29#include "insn-flags.h"
30#include "output.h"
31#include "insn-attr.h"
32#include "flags.h"
33#include "tree.h"
34#include "c-tree.h"
35#include "expr.h"
d6f01525 36#include "obstack.h"
87ad11b0 37
38/* Save the operands last given to a compare for use when we
39 generate a scc or bcc insn. */
40
41rtx hppa_compare_op0, hppa_compare_op1;
42enum cmp_type hppa_branch_type;
43
eff812f1 44rtx hppa_save_pic_table_rtx;
45
87ad11b0 46/* Set by the FUNCTION_PROFILER macro. */
47int hp_profile_labelno;
48
a9960cdc 49/* Counts for the number of callee-saved general and floating point
50 registers which were saved by the current function's prologue. */
51static int gr_saved, fr_saved;
52
87ad11b0 53static rtx find_addr_reg ();
54
55/* Return non-zero only if OP is a register of mode MODE,
891b55b4 56 or CONST0_RTX. */
87ad11b0 57int
58reg_or_0_operand (op, mode)
59 rtx op;
60 enum machine_mode mode;
61{
891b55b4 62 return (op == CONST0_RTX (mode) || register_operand (op, mode));
87ad11b0 63}
64
575e0eb4 65/* Return non-zero if OP is suitable for use in a call to a named
66 function.
67
6d36483b 68 (???) For 2.5 try to eliminate either call_operand_address or
575e0eb4 69 function_label_operand, they perform very similar functions. */
87ad11b0 70int
71call_operand_address (op, mode)
72 rtx op;
73 enum machine_mode mode;
74{
575e0eb4 75 return (CONSTANT_P (op) && ! TARGET_LONG_CALLS);
87ad11b0 76}
77
6d36483b 78/* Return 1 if X contains a symbolic expression. We know these
79 expressions will have one of a few well defined forms, so
347b5848 80 we need only check those forms. */
81int
82symbolic_expression_p (x)
83 register rtx x;
84{
85
6d36483b 86 /* Strip off any HIGH. */
347b5848 87 if (GET_CODE (x) == HIGH)
88 x = XEXP (x, 0);
89
90 return (symbolic_operand (x, VOIDmode));
91}
92
87ad11b0 93int
94symbolic_operand (op, mode)
95 register rtx op;
96 enum machine_mode mode;
97{
98 switch (GET_CODE (op))
99 {
100 case SYMBOL_REF:
101 case LABEL_REF:
102 return 1;
103 case CONST:
104 op = XEXP (op, 0);
105 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
106 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
107 && GET_CODE (XEXP (op, 1)) == CONST_INT);
108 default:
109 return 0;
110 }
111}
112
113/* Return truth value of statement that OP is a symbolic memory
114 operand of mode MODE. */
115
116int
117symbolic_memory_operand (op, mode)
118 rtx op;
119 enum machine_mode mode;
120{
121 if (GET_CODE (op) == SUBREG)
122 op = SUBREG_REG (op);
123 if (GET_CODE (op) != MEM)
124 return 0;
125 op = XEXP (op, 0);
126 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
127 || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
128}
129
130/* Return 1 if the operand is either a register or a memory operand that is
131 not symbolic. */
132
133int
134reg_or_nonsymb_mem_operand (op, mode)
135 register rtx op;
136 enum machine_mode mode;
137{
138 if (register_operand (op, mode))
139 return 1;
140
141 if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
142 return 1;
143
144 return 0;
145}
146
6d36483b 147/* Return 1 if the operand is either a register, zero, or a memory operand
891b55b4 148 that is not symbolic. */
149
150int
151reg_or_0_or_nonsymb_mem_operand (op, mode)
152 register rtx op;
153 enum machine_mode mode;
154{
155 if (register_operand (op, mode))
156 return 1;
157
158 if (op == CONST0_RTX (mode))
159 return 1;
160
161 if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
162 return 1;
163
164 return 0;
165}
166
6d36483b 167/* Accept any constant that can be moved in one instructions into a
d9d7c968 168 general register. */
6d36483b 169int
d9d7c968 170cint_ok_for_move (intval)
6d36483b 171 HOST_WIDE_INT intval;
d9d7c968 172{
173 /* OK if ldo, ldil, or zdepi, can be used. */
174 return (VAL_14_BITS_P (intval) || (intval & 0x7ff) == 0
175 || zdepi_cint_p (intval));
176}
177
6ecdbaa1 178/* Accept anything that can be moved in one instruction into a general
179 register. */
87ad11b0 180int
181move_operand (op, mode)
182 rtx op;
183 enum machine_mode mode;
184{
185 if (register_operand (op, mode))
186 return 1;
187
42faba01 188 if (GET_CODE (op) == CONST_INT)
d9d7c968 189 return cint_ok_for_move (INTVAL (op));
87ad11b0 190
191 if (GET_MODE (op) != mode)
192 return 0;
193 if (GET_CODE (op) == SUBREG)
194 op = SUBREG_REG (op);
195 if (GET_CODE (op) != MEM)
196 return 0;
197
198 op = XEXP (op, 0);
199 if (GET_CODE (op) == LO_SUM)
200 return (register_operand (XEXP (op, 0), Pmode)
201 && CONSTANT_P (XEXP (op, 1)));
202 return memory_address_p (mode, op);
203}
204
6ecdbaa1 205/* Accept REG and any CONST_INT that can be moved in one instruction into a
206 general register. */
207int
208reg_or_cint_move_operand (op, mode)
209 rtx op;
210 enum machine_mode mode;
211{
212 if (register_operand (op, mode))
213 return 1;
214
215 if (GET_CODE (op) == CONST_INT)
686b848d 216 return cint_ok_for_move (INTVAL (op));
217
6ecdbaa1 218 return 0;
219}
220
87ad11b0 221int
222pic_operand (op, mode)
223 rtx op;
224 enum machine_mode mode;
225{
226 return flag_pic && GET_CODE (op) == LABEL_REF;
227}
228
87ad11b0 229int
230fp_reg_operand (op, mode)
231 rtx op;
232 enum machine_mode mode;
233{
234 return reg_renumber && FP_REG_P (op);
235}
d6f01525 236
87ad11b0 237\f
238extern int current_function_uses_pic_offset_table;
239extern rtx force_reg (), validize_mem ();
240
241/* The rtx for the global offset table which is a special form
242 that *is* a position independent symbolic constant. */
243rtx pic_pc_rtx;
244
245/* Ensure that we are not using patterns that are not OK with PIC. */
246
247int
248check_pic (i)
249 int i;
250{
251 extern rtx recog_operand[];
252 switch (flag_pic)
253 {
254 case 1:
255 if (GET_CODE (recog_operand[i]) == SYMBOL_REF
256 || (GET_CODE (recog_operand[i]) == CONST
257 && ! rtx_equal_p (pic_pc_rtx, recog_operand[i])))
258 abort ();
259 case 2:
260 default:
261 return 1;
262 }
263}
264
87ad11b0 265/* Return truth value of whether OP can be used as an operand in a
266 three operand arithmetic insn that accepts registers of mode MODE
267 or 14-bit signed integers. */
268int
269arith_operand (op, mode)
270 rtx op;
271 enum machine_mode mode;
272{
273 return (register_operand (op, mode)
274 || (GET_CODE (op) == CONST_INT && INT_14_BITS (op)));
275}
276
277/* Return truth value of whether OP can be used as an operand in a
278 three operand arithmetic insn that accepts registers of mode MODE
279 or 11-bit signed integers. */
280int
281arith11_operand (op, mode)
282 rtx op;
283 enum machine_mode mode;
284{
285 return (register_operand (op, mode)
286 || (GET_CODE (op) == CONST_INT && INT_11_BITS (op)));
287}
288
6d36483b 289/* A constant integer suitable for use in a PRE_MODIFY memory
757d4970 290 reference. */
42faba01 291int
292pre_cint_operand (op, mode)
293 rtx op;
294 enum machine_mode mode;
295{
296 return (GET_CODE (op) == CONST_INT
297 && INTVAL (op) >= -0x2000 && INTVAL (op) < 0x10);
298}
299
6d36483b 300/* A constant integer suitable for use in a POST_MODIFY memory
757d4970 301 reference. */
302int
303post_cint_operand (op, mode)
304 rtx op;
305 enum machine_mode mode;
306{
307 return (GET_CODE (op) == CONST_INT
308 && INTVAL (op) < 0x2000 && INTVAL (op) >= -0x10);
309}
310
87ad11b0 311int
312arith_double_operand (op, mode)
313 rtx op;
314 enum machine_mode mode;
315{
316 return (register_operand (op, mode)
317 || (GET_CODE (op) == CONST_DOUBLE
318 && GET_MODE (op) == mode
319 && VAL_14_BITS_P (CONST_DOUBLE_LOW (op))
320 && (CONST_DOUBLE_HIGH (op) >= 0
321 == ((CONST_DOUBLE_LOW (op) & 0x1000) == 0))));
322}
323
324/* Return truth value of whether OP is a integer which fits the
325 range constraining immediate operands in three-address insns. */
326
327int
328int5_operand (op, mode)
329 rtx op;
330 enum machine_mode mode;
331{
332 return (GET_CODE (op) == CONST_INT && INT_5_BITS (op));
333}
334
335int
336uint5_operand (op, mode)
337 rtx op;
338 enum machine_mode mode;
339{
340 return (GET_CODE (op) == CONST_INT && INT_U5_BITS (op));
341}
342
87ad11b0 343int
344int11_operand (op, mode)
345 rtx op;
346 enum machine_mode mode;
347{
6d36483b 348 return (GET_CODE (op) == CONST_INT && INT_11_BITS (op));
349}
350
351int
352uint32_operand (op, mode)
353 rtx op;
354 enum machine_mode mode;
355{
356#if HOST_BITS_PER_WIDE_INT > 32
357 /* All allowed constants will fit a CONST_INT. */
358 return (GET_CODE (op) == CONST_INT
359 && (INTVAL (op) >= 0 && INTVAL (op) < 0x100000000L));
360#else
361 return (GET_CODE (op) == CONST_INT
362 || (GET_CODE (op) == CONST_DOUBLE
363 && CONST_DOUBLE_HIGH (op) == 0));
364#endif
87ad11b0 365}
366
367int
368arith5_operand (op, mode)
369 rtx op;
370 enum machine_mode mode;
371{
372 return register_operand (op, mode) || int5_operand (op, mode);
373}
374
fad0b60f 375/* True iff zdepi can be used to generate this CONST_INT. */
e057641f 376int
42faba01 377zdepi_cint_p (x)
6d36483b 378 unsigned HOST_WIDE_INT x;
fad0b60f 379{
42faba01 380 unsigned lsb_mask, t;
fad0b60f 381
382 /* This might not be obvious, but it's at least fast.
383 This function is critcal; we don't have the time loops would take. */
42faba01 384 lsb_mask = x & -x;
385 t = ((x >> 4) + lsb_mask) & ~(lsb_mask - 1);
386 /* Return true iff t is a power of two. */
fad0b60f 387 return ((t & (t - 1)) == 0);
388}
389
6d36483b 390/* True iff depi or extru can be used to compute (reg & mask).
391 Accept bit pattern like these:
392 0....01....1
393 1....10....0
394 1..10..01..1 */
e057641f 395int
42faba01 396and_mask_p (mask)
6d36483b 397 unsigned HOST_WIDE_INT mask;
e057641f 398{
399 mask = ~mask;
400 mask += mask & -mask;
401 return (mask & (mask - 1)) == 0;
402}
403
404/* True iff depi or extru can be used to compute (reg & OP). */
405int
406and_operand (op, mode)
407 rtx op;
408 enum machine_mode mode;
409{
410 return (register_operand (op, mode)
42faba01 411 || (GET_CODE (op) == CONST_INT && and_mask_p (INTVAL (op))));
e057641f 412}
413
414/* True iff depi can be used to compute (reg | MASK). */
415int
416ior_mask_p (mask)
6d36483b 417 unsigned HOST_WIDE_INT mask;
e057641f 418{
419 mask += mask & -mask;
420 return (mask & (mask - 1)) == 0;
421}
422
423/* True iff depi can be used to compute (reg | OP). */
424int
425ior_operand (op, mode)
426 rtx op;
427 enum machine_mode mode;
428{
b744c8cb 429 return (GET_CODE (op) == CONST_INT && ior_mask_p (INTVAL (op)));
e057641f 430}
431
e5965947 432int
433lhs_lshift_operand (op, mode)
434 rtx op;
435 enum machine_mode mode;
436{
437 return register_operand (op, mode) || lhs_lshift_cint_operand (op, mode);
438}
439
440/* True iff OP is a CONST_INT of the forms 0...0xxxx or 0...01...1xxxx.
441 Such values can be the left hand side x in (x << r), using the zvdepi
442 instruction. */
443int
444lhs_lshift_cint_operand (op, mode)
445 rtx op;
446 enum machine_mode mode;
447{
448 unsigned x;
449 if (GET_CODE (op) != CONST_INT)
450 return 0;
451 x = INTVAL (op) >> 4;
452 return (x & (x + 1)) == 0;
453}
454
9c6d4825 455int
456arith32_operand (op, mode)
457 rtx op;
458 enum machine_mode mode;
459{
460 return register_operand (op, mode) || GET_CODE (op) == CONST_INT;
461}
ead9285f 462
463int
464pc_or_label_operand (op, mode)
465 rtx op;
466 enum machine_mode mode;
467{
468 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
469}
87ad11b0 470\f
471/* Legitimize PIC addresses. If the address is already
472 position-independent, we return ORIG. Newly generated
473 position-independent addresses go to REG. If we need more
474 than one register, we lose. */
475
476rtx
477legitimize_pic_address (orig, mode, reg)
478 rtx orig, reg;
479 enum machine_mode mode;
480{
481 rtx pic_ref = orig;
482
483 if (GET_CODE (orig) == SYMBOL_REF)
484 {
485 if (reg == 0)
486 abort ();
487
488 if (flag_pic == 2)
489 {
490 emit_insn (gen_rtx (SET, VOIDmode, reg,
491 gen_rtx (HIGH, Pmode, orig)));
492 emit_insn (gen_rtx (SET, VOIDmode, reg,
493 gen_rtx (LO_SUM, Pmode, reg, orig)));
494 orig = reg;
495 }
496 pic_ref = gen_rtx (MEM, Pmode,
497 gen_rtx (PLUS, Pmode,
498 pic_offset_table_rtx, orig));
499 current_function_uses_pic_offset_table = 1;
500 RTX_UNCHANGING_P (pic_ref) = 1;
501 emit_move_insn (reg, pic_ref);
502 return reg;
503 }
504 else if (GET_CODE (orig) == CONST)
505 {
57ed30e5 506 rtx base;
87ad11b0 507
508 if (GET_CODE (XEXP (orig, 0)) == PLUS
509 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
510 return orig;
511
512 if (reg == 0)
513 abort ();
514
515 if (GET_CODE (XEXP (orig, 0)) == PLUS)
516 {
517 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
518 orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
519 base == reg ? 0 : reg);
520 }
521 else abort ();
522 if (GET_CODE (orig) == CONST_INT)
523 {
42faba01 524 if (INT_14_BITS (orig))
87ad11b0 525 return plus_constant_for_output (base, INTVAL (orig));
526 orig = force_reg (Pmode, orig);
527 }
528 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
529 /* Likewise, should we set special REG_NOTEs here? */
530 }
531 return pic_ref;
532}
533
87ad11b0 534/* Emit special PIC prologues and epilogues. */
535
536void
537finalize_pic ()
538{
eff812f1 539 if (hppa_save_pic_table_rtx)
540 {
541 emit_insn_after (gen_rtx (SET, VOIDmode,
542 hppa_save_pic_table_rtx,
6d36483b 543 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)),
eff812f1 544 get_insns ());
545 /* Need to emit this whether or not we obey regdecls,
546 since setjmp/longjmp can cause life info to screw up. */
547 hppa_save_pic_table_rtx = 0;
548 }
87ad11b0 549 emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
550}
551
347b5848 552/* Try machine-dependent ways of modifying an illegitimate address
553 to be legitimate. If we find one, return the new, valid address.
554 This macro is used in only one place: `memory_address' in explow.c.
555
556 OLDX is the address as it was before break_out_memory_refs was called.
557 In some cases it is useful to look at this to decide what needs to be done.
558
559 MODE and WIN are passed so that this macro can use
560 GO_IF_LEGITIMATE_ADDRESS.
561
562 It is always safe for this macro to do nothing. It exists to recognize
6d36483b 563 opportunities to optimize the output.
347b5848 564
565 For the PA, transform:
566
567 memory(X + <large int>)
568
569 into:
570
571 if (<large int> & mask) >= 16
572 Y = (<large int> & ~mask) + mask + 1 Round up.
573 else
574 Y = (<large int> & ~mask) Round down.
575 Z = X + Y
576 memory (Z + (<large int> - Y));
577
6d36483b 578 This is for CSE to find several similar references, and only use one Z.
347b5848 579
580 X can either be a SYMBOL_REF or REG, but because combine can not
581 perform a 4->2 combination we do nothing for SYMBOL_REF + D where
582 D will not fit in 14 bits.
583
584 MODE_FLOAT references allow displacements which fit in 5 bits, so use
6d36483b 585 0x1f as the mask.
347b5848 586
587 MODE_INT references allow displacements which fit in 14 bits, so use
6d36483b 588 0x3fff as the mask.
347b5848 589
590 This relies on the fact that most mode MODE_FLOAT references will use FP
591 registers and most mode MODE_INT references will use integer registers.
592 (In the rare case of an FP register used in an integer MODE, we depend
593 on secondary reloads to clean things up.)
594
595
596 It is also beneficial to handle (plus (mult (X) (Y)) (Z)) in a special
597 manner if Y is 2, 4, or 8. (allows more shadd insns and shifted indexed
598 adressing modes to be used).
599
600 Put X and Z into registers. Then put the entire expression into
601 a register. */
602
603rtx
604hppa_legitimize_address (x, oldx, mode)
605 rtx x, oldx;
606 enum machine_mode mode;
607{
347b5848 608 rtx orig = x;
609
610 /* Strip off CONST. */
611 if (GET_CODE (x) == CONST)
612 x = XEXP (x, 0);
613
614 if (GET_CODE (x) == PLUS
615 && GET_CODE (XEXP (x, 1)) == CONST_INT
616 && (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
617 || GET_CODE (XEXP (x, 0)) == REG))
618 {
619 rtx int_part, ptr_reg;
620 int newoffset;
621 int offset = INTVAL (XEXP (x, 1));
622 int mask = GET_MODE_CLASS (mode) == MODE_FLOAT ? 0x1f : 0x3fff;
623
6d36483b 624 /* Choose which way to round the offset. Round up if we
347b5848 625 are >= halfway to the next boundary. */
626 if ((offset & mask) >= ((mask + 1) / 2))
627 newoffset = (offset & ~ mask) + mask + 1;
628 else
629 newoffset = (offset & ~ mask);
630
631 /* If the newoffset will not fit in 14 bits (ldo), then
632 handling this would take 4 or 5 instructions (2 to load
633 the SYMBOL_REF + 1 or 2 to load the newoffset + 1 to
634 add the new offset and the SYMBOL_REF.) Combine can
635 not handle 4->2 or 5->2 combinations, so do not create
636 them. */
637 if (! VAL_14_BITS_P (newoffset)
638 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
639 {
640 rtx const_part = gen_rtx (CONST, VOIDmode,
339613b4 641 gen_rtx (PLUS, Pmode,
347b5848 642 XEXP (x, 0),
643 GEN_INT (newoffset)));
644 rtx tmp_reg
339613b4 645 = force_reg (Pmode,
646 gen_rtx (HIGH, Pmode, const_part));
347b5848 647 ptr_reg
339613b4 648 = force_reg (Pmode,
649 gen_rtx (LO_SUM, Pmode,
347b5848 650 tmp_reg, const_part));
651 }
652 else
653 {
654 if (! VAL_14_BITS_P (newoffset))
339613b4 655 int_part = force_reg (Pmode, GEN_INT (newoffset));
347b5848 656 else
657 int_part = GEN_INT (newoffset);
658
339613b4 659 ptr_reg = force_reg (Pmode,
660 gen_rtx (PLUS, Pmode,
661 force_reg (Pmode, XEXP (x, 0)),
347b5848 662 int_part));
663 }
664 return plus_constant (ptr_reg, offset - newoffset);
665 }
45f1285a 666
667 /* Try to arrange things so that indexing modes can be used, but
6d36483b 668 only do so if indexing is safe.
45f1285a 669
670 Indexing is safe when the second operand for the outer PLUS
6d36483b 671 is a REG, SUBREG, SYMBOL_REF or the like.
45f1285a 672
6d36483b 673 For 2.5, indexing is also safe for (plus (symbol_ref) (const_int))
45f1285a 674 if the integer is > 0. */
347b5848 675 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
676 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
45f1285a 677 && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
678 && (GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == 'o'
679 || GET_CODE (XEXP (x, 1)) == SUBREG)
680 && GET_CODE (XEXP (x, 1)) != CONST)
347b5848 681 {
682 int val = INTVAL (XEXP (XEXP (x, 0), 1));
683 rtx reg1, reg2;
339613b4 684 reg1 = force_reg (Pmode, force_operand (XEXP (x, 1), 0));
685 reg2 = force_reg (Pmode,
347b5848 686 force_operand (XEXP (XEXP (x, 0), 0), 0));
339613b4 687 return force_reg (Pmode,
688 gen_rtx (PLUS, Pmode,
689 gen_rtx (MULT, Pmode, reg2,
347b5848 690 GEN_INT (val)),
691 reg1));
692 }
45f1285a 693
6d36483b 694 /* Uh-oh. We might have an address for x[n-100000]. This needs
45f1285a 695 special handling. */
696
697 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
698 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
699 && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
700 {
701 /* Ugly. We modify things here so that the address offset specified
702 by the index expression is computed first, then added to x to form
703 the entire address.
704
705 For 2.5, it might be profitable to set things up so that we
706 compute the raw (unscaled) index first, then use scaled indexing
707 to access memory, or better yet have the MI parts of the compiler
708 handle this. */
709
710 rtx regx1, regy1, regy2, y;
711
712 /* Strip off any CONST. */
713 y = XEXP (x, 1);
714 if (GET_CODE (y) == CONST)
715 y = XEXP (y, 0);
716
7ee96d6e 717 if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)
718 {
719 regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));
720 regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
721 regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
722 regx1 = force_reg (Pmode, gen_rtx (GET_CODE (y), Pmode, regx1, regy2));
723 return force_reg (Pmode, gen_rtx (PLUS, Pmode, regx1, regy1));
724 }
45f1285a 725 }
726
6d36483b 727 if (flag_pic)
347b5848 728 return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode));
729
730 return orig;
731}
732
87ad11b0 733/* For the HPPA, REG and REG+CONST is cost 0
734 and addresses involving symbolic constants are cost 2.
735
736 PIC addresses are very expensive.
737
738 It is no coincidence that this has the same structure
739 as GO_IF_LEGITIMATE_ADDRESS. */
740int
741hppa_address_cost (X)
742 rtx X;
743{
744 if (GET_CODE (X) == PLUS)
745 return 1;
746 else if (GET_CODE (X) == LO_SUM)
747 return 1;
748 else if (GET_CODE (X) == HIGH)
749 return 2;
750 return 4;
751}
752
753/* Emit insns to move operands[1] into operands[0].
754
755 Return 1 if we have written out everything that needs to be done to
756 do the move. Otherwise, return 0 and the caller will emit the move
757 normally. */
758
759int
d6f01525 760emit_move_sequence (operands, mode, scratch_reg)
87ad11b0 761 rtx *operands;
762 enum machine_mode mode;
d6f01525 763 rtx scratch_reg;
87ad11b0 764{
765 register rtx operand0 = operands[0];
766 register rtx operand1 = operands[1];
767
e8fdbafa 768 /* Handle secondary reloads for loads/stores of FP registers from
769 REG+D addresses where D does not fit in 5 bits. */
d6f01525 770 if (fp_reg_operand (operand0, mode)
771 && GET_CODE (operand1) == MEM
2fbf96d8 772 /* Using DFmode forces only short displacements be be
773 recognized as valid in reg+d addressing modes. */
774 && ! memory_address_p (DFmode, XEXP (operand1, 0))
d6f01525 775 && scratch_reg)
776 {
6d36483b 777 emit_move_insn (scratch_reg, XEXP (operand1, 0));
d6f01525 778 emit_insn (gen_rtx (SET, VOIDmode, operand0, gen_rtx (MEM, mode,
779 scratch_reg)));
780 return 1;
781 }
782 else if (fp_reg_operand (operand1, mode)
783 && GET_CODE (operand0) == MEM
2fbf96d8 784 /* Using DFmode forces only short displacements be be
785 recognized as valid in reg+d addressing modes. */
786 && ! memory_address_p (DFmode, XEXP (operand0, 0))
d6f01525 787 && scratch_reg)
788 {
6d36483b 789 emit_move_insn (scratch_reg, XEXP (operand0, 0));
790 emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, mode, scratch_reg),
d6f01525 791 operand1));
792 return 1;
793 }
753bd06a 794 /* Handle secondary reloads for loads of FP registers from constant
795 expressions by forcing the constant into memory.
796
6d36483b 797 use scratch_reg to hold the address of the memory location.
753bd06a 798
6d36483b 799 ??? The proper fix is to change PREFERRED_RELOAD_CLASS to return
800 NO_REGS when presented with a const_int and an register class
753bd06a 801 containing only FP registers. Doing so unfortunately creates
802 more problems than it solves. Fix this for 2.5. */
803 else if (fp_reg_operand (operand0, mode)
804 && CONSTANT_P (operand1)
805 && scratch_reg)
806 {
807 rtx xoperands[2];
808
809 /* Force the constant into memory and put the address of the
810 memory location into scratch_reg. */
811 xoperands[0] = scratch_reg;
812 xoperands[1] = XEXP (force_const_mem (mode, operand1), 0);
8f258b49 813 emit_move_sequence (xoperands, Pmode, 0);
753bd06a 814
815 /* Now load the destination register. */
816 emit_insn (gen_rtx (SET, mode, operand0,
817 gen_rtx (MEM, mode, scratch_reg)));
818 return 1;
819 }
e8fdbafa 820 /* Handle secondary reloads for SAR. These occur when trying to load
821 the SAR from memory or from a FP register. */
822 else if (GET_CODE (operand0) == REG
823 && REGNO_REG_CLASS (REGNO (operand0)) == SHIFT_REGS
824 && (GET_CODE (operand1) == MEM
825 || (GET_CODE (operand1) == REG
826 && FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1)))))
827 && scratch_reg)
828 {
829 emit_move_insn (scratch_reg, operand1);
830 emit_move_insn (operand0, scratch_reg);
831 return 1;
832 }
d6f01525 833 /* Handle most common case: storing into a register. */
834 else if (register_operand (operand0, mode))
87ad11b0 835 {
836 if (register_operand (operand1, mode)
42faba01 837 || (GET_CODE (operand1) == CONST_INT && INT_14_BITS (operand1))
891b55b4 838 || (operand1 == CONST0_RTX (mode))
87ad11b0 839 || (GET_CODE (operand1) == HIGH
df0651dc 840 && !symbolic_operand (XEXP (operand1, 0), VOIDmode))
87ad11b0 841 /* Only `general_operands' can come here, so MEM is ok. */
842 || GET_CODE (operand1) == MEM)
843 {
844 /* Run this case quickly. */
845 emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
846 return 1;
847 }
848 }
849 else if (GET_CODE (operand0) == MEM)
850 {
891b55b4 851 if (register_operand (operand1, mode) || operand1 == CONST0_RTX (mode))
87ad11b0 852 {
853 /* Run this case quickly. */
854 emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
855 return 1;
856 }
2ff4bf8d 857 if (! (reload_in_progress || reload_completed))
87ad11b0 858 {
859 operands[0] = validize_mem (operand0);
860 operands[1] = operand1 = force_reg (mode, operand1);
861 }
862 }
863
864 /* Simplify the source if we need to. */
57ed30e5 865 if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
2ee034bc 866 || (GET_CODE (operand1) == HIGH
63882853 867 && symbolic_operand (XEXP (operand1, 0), mode)))
87ad11b0 868 {
2ee034bc 869 int ishighonly = 0;
870
871 if (GET_CODE (operand1) == HIGH)
872 {
873 ishighonly = 1;
874 operand1 = XEXP (operand1, 0);
875 }
87ad11b0 876 if (symbolic_operand (operand1, mode))
877 {
878 if (flag_pic)
879 {
2ff4bf8d 880 rtx temp;
881
882 if (reload_in_progress || reload_completed)
883 temp = operand0;
884 else
885 temp = gen_reg_rtx (Pmode);
6d36483b 886
87ad11b0 887 operands[1] = legitimize_pic_address (operand1, mode, temp);
9aff9cf4 888 emit_insn (gen_rtx (SET, VOIDmode, operand0, operands[1]));
87ad11b0 889 }
890 /* On the HPPA, references to data space are supposed to */
2ee034bc 891 /* use dp, register 27, but showing it in the RTL inhibits various
892 cse and loop optimizations. */
6d36483b 893 else
87ad11b0 894 {
2ee034bc 895 rtx temp, set;
896
6d36483b 897 if (reload_in_progress || reload_completed)
2ee034bc 898 temp = scratch_reg ? scratch_reg : operand0;
899 else
900 temp = gen_reg_rtx (mode);
901
902 if (ishighonly)
903 set = gen_rtx (SET, mode, operand0, temp);
904 else
905 set = gen_rtx (SET, VOIDmode,
906 operand0,
907 gen_rtx (LO_SUM, mode, temp, operand1));
6d36483b 908
87ad11b0 909 emit_insn (gen_rtx (SET, VOIDmode,
2ee034bc 910 temp,
d6f01525 911 gen_rtx (HIGH, mode, operand1)));
d2498717 912 emit_insn (set);
87ad11b0 913 return 1;
914 }
2ee034bc 915 return 1;
87ad11b0 916 }
42faba01 917 else if (GET_CODE (operand1) != CONST_INT
8c8ec4de 918 || ! cint_ok_for_move (INTVAL (operand1)))
87ad11b0 919 {
2ff4bf8d 920 rtx temp;
921
922 if (reload_in_progress || reload_completed)
923 temp = operand0;
924 else
925 temp = gen_reg_rtx (mode);
926
87ad11b0 927 emit_insn (gen_rtx (SET, VOIDmode, temp,
928 gen_rtx (HIGH, mode, operand1)));
929 operands[1] = gen_rtx (LO_SUM, mode, temp, operand1);
930 }
931 }
932 /* Now have insn-emit do whatever it normally does. */
933 return 0;
934}
935
936/* Does operand (which is a symbolic_operand) live in text space? If
201f01e9 937 so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. */
87ad11b0 938
939int
940read_only_operand (operand)
941 rtx operand;
942{
943 if (GET_CODE (operand) == CONST)
944 operand = XEXP (XEXP (operand, 0), 0);
945 if (GET_CODE (operand) == SYMBOL_REF)
946 return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
947 return 1;
948}
6d36483b 949
87ad11b0 950\f
951/* Return the best assembler insn template
f54b1341 952 for moving operands[1] into operands[0] as a fullword. */
5c683f13 953char *
87ad11b0 954singlemove_string (operands)
955 rtx *operands;
956{
957 if (GET_CODE (operands[0]) == MEM)
958 return "stw %r1,%0";
9d5108ea 959 else if (GET_CODE (operands[1]) == MEM)
87ad11b0 960 return "ldw %1,%0";
9d5108ea 961 else if (GET_CODE (operands[1]) == CONST_DOUBLE
962 && GET_MODE (operands[1]) == SFmode)
963 {
964 int i;
965 union real_extract u;
966 union float_extract { float f; int i; } v;
967
968 bcopy (&CONST_DOUBLE_LOW (operands[1]), &u, sizeof u);
969 v.f = REAL_VALUE_TRUNCATE (SFmode, u.d);
970 i = v.i;
971
972 operands[1] = gen_rtx (CONST_INT, VOIDmode, i);
973
f54b1341 974 /* See if we can handle this constant in a single instruction. */
975 if (cint_ok_for_move (INTVAL (operands[1])))
976 {
6d36483b 977 HOST_WIDE_INT intval = INTVAL (operands[1]);
f54b1341 978
979 if (intval == 0)
980 return "copy 0,%0";
981 else if (VAL_14_BITS_P (intval))
982 return "ldi %1,%0";
983 else if ((intval & 0x7ff) == 0)
984 return "ldil L'%1,%0";
985 else if (zdepi_cint_p (intval))
986 return "zdepi %Z1,%0";
987 }
9d5108ea 988 else
989 return "ldil L'%1,%0\n\tldo R'%1(%0),%0";
990 }
991
992 else if (GET_CODE (operands[1]) == CONST_INT)
993 {
f54b1341 994 /* See if we can handle this in a single instruction. */
995 if (cint_ok_for_move (INTVAL (operands[1])))
996 {
997 int intval = INTVAL (operands[1]);
998
999 if (intval == 0)
1000 return "copy 0,%0";
1001 else if (VAL_14_BITS_P (intval))
1002 return "ldi %1,%0";
1003 else if ((intval & 0x7ff) == 0)
1004 return "ldil L'%1,%0";
1005 else if (zdepi_cint_p (intval))
1006 return "zdepi %Z1,%0";
1007 }
9d5108ea 1008 else
1009 return "ldil L'%1,%0\n\tldo R'%1(%0),%0";
1010 }
87ad11b0 1011 return "copy %1,%0";
1012}
1013\f
1014
201f01e9 1015/* Compute position (in OP[1]) and width (in OP[2])
1016 useful for copying IMM to a register using the zdepi
1017 instructions. Store the immediate value to insert in OP[0]. */
e057641f 1018void
42faba01 1019compute_zdepi_operands (imm, op)
6d36483b 1020 unsigned HOST_WIDE_INT imm;
42faba01 1021 unsigned *op;
7e10ba53 1022{
e057641f 1023 int lsb, len;
7e10ba53 1024
e057641f 1025 /* Find the least significant set bit in IMM. */
1026 for (lsb = 0; lsb < 32; lsb++)
7e10ba53 1027 {
e057641f 1028 if ((imm & 1) != 0)
7e10ba53 1029 break;
e057641f 1030 imm >>= 1;
7e10ba53 1031 }
1032
e057641f 1033 /* Choose variants based on *sign* of the 5-bit field. */
1034 if ((imm & 0x10) == 0)
1035 len = (lsb <= 28) ? 4 : 32 - lsb;
7e10ba53 1036 else
1037 {
e057641f 1038 /* Find the width of the bitstring in IMM. */
1039 for (len = 5; len < 32; len++)
7e10ba53 1040 {
e057641f 1041 if ((imm & (1 << len)) == 0)
7e10ba53 1042 break;
7e10ba53 1043 }
1044
e057641f 1045 /* Sign extend IMM as a 5-bit value. */
1046 imm = (imm & 0xf) - 0x10;
7e10ba53 1047 }
1048
42faba01 1049 op[0] = imm;
1050 op[1] = 31 - lsb;
1051 op[2] = len;
7e10ba53 1052}
1053
87ad11b0 1054/* Output assembler code to perform a doubleword move insn
1055 with operands OPERANDS. */
1056
1057char *
1058output_move_double (operands)
1059 rtx *operands;
1060{
1061 enum { REGOP, OFFSOP, MEMOP, CNSTOP, RNDOP } optype0, optype1;
1062 rtx latehalf[2];
1063 rtx addreg0 = 0, addreg1 = 0;
1064
1065 /* First classify both operands. */
1066
1067 if (REG_P (operands[0]))
1068 optype0 = REGOP;
1069 else if (offsettable_memref_p (operands[0]))
1070 optype0 = OFFSOP;
1071 else if (GET_CODE (operands[0]) == MEM)
1072 optype0 = MEMOP;
1073 else
1074 optype0 = RNDOP;
1075
1076 if (REG_P (operands[1]))
1077 optype1 = REGOP;
1078 else if (CONSTANT_P (operands[1]))
1079 optype1 = CNSTOP;
1080 else if (offsettable_memref_p (operands[1]))
1081 optype1 = OFFSOP;
1082 else if (GET_CODE (operands[1]) == MEM)
1083 optype1 = MEMOP;
1084 else
1085 optype1 = RNDOP;
1086
1087 /* Check for the cases that the operand constraints are not
1088 supposed to allow to happen. Abort if we get one,
1089 because generating code for these cases is painful. */
1090
1091 if (optype0 != REGOP && optype1 != REGOP)
1092 abort ();
1093
1094 /* Handle auto decrementing and incrementing loads and stores
1095 specifically, since the structure of the function doesn't work
1096 for them without major modification. Do it better when we learn
1097 this port about the general inc/dec addressing of PA.
1098 (This was written by tege. Chide him if it doesn't work.) */
1099
1100 if (optype0 == MEMOP)
1101 {
1df0058a 1102 /* We have to output the address syntax ourselves, since print_operand
1103 doesn't deal with the addresses we want to use. Fix this later. */
1104
87ad11b0 1105 rtx addr = XEXP (operands[0], 0);
1df0058a 1106 if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)
87ad11b0 1107 {
1df0058a 1108 rtx high_reg = gen_rtx (SUBREG, SImode, operands[1], 0);
1109
1110 operands[0] = XEXP (addr, 0);
1111 if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)
1112 abort ();
1113
1114 if (!reg_overlap_mentioned_p (high_reg, addr))
1115 {
1116 /* No overlap between high target register and address
1117 register. (We do this in a non-obvious way to
1118 save a register file writeback) */
1119 if (GET_CODE (addr) == POST_INC)
1120 return "stws,ma %1,8(0,%0)\n\tstw %R1,-4(0,%0)";
1121 return "stws,ma %1,-8(0,%0)\n\tstw %R1,12(0,%0)";
1122 }
1123 else
1124 abort();
a3217f65 1125 }
1df0058a 1126 else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
a3217f65 1127 {
1df0058a 1128 rtx high_reg = gen_rtx (SUBREG, SImode, operands[1], 0);
1129
1130 operands[0] = XEXP (addr, 0);
1131 if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)
1132 abort ();
1133
1134 if (!reg_overlap_mentioned_p (high_reg, addr))
1135 {
1136 /* No overlap between high target register and address
1137 register. (We do this in a non-obvious way to
1138 save a register file writeback) */
1139 if (GET_CODE (addr) == PRE_INC)
1140 return "stws,mb %1,8(0,%0)\n\tstw %R1,4(0,%0)";
1141 return "stws,mb %1,-8(0,%0)\n\tstw %R1,4(0,%0)";
1142 }
1143 else
1144 abort();
87ad11b0 1145 }
1146 }
1147 if (optype1 == MEMOP)
1148 {
1149 /* We have to output the address syntax ourselves, since print_operand
1150 doesn't deal with the addresses we want to use. Fix this later. */
1151
1152 rtx addr = XEXP (operands[1], 0);
1153 if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)
1154 {
1155 rtx high_reg = gen_rtx (SUBREG, SImode, operands[0], 0);
1156
1157 operands[1] = XEXP (addr, 0);
1158 if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG)
1159 abort ();
1160
1161 if (!reg_overlap_mentioned_p (high_reg, addr))
1162 {
1163 /* No overlap between high target register and address
3857fa62 1164 register. (We do this in a non-obvious way to
87ad11b0 1165 save a register file writeback) */
1166 if (GET_CODE (addr) == POST_INC)
1167 return "ldws,ma 8(0,%1),%0\n\tldw -4(0,%1),%R0";
1168 return "ldws,ma -8(0,%1),%0\n\tldw 12(0,%1),%R0";
1169 }
1170 else
1171 {
1172 /* This is an undefined situation. We should load into the
1173 address register *and* update that register. Probably
1174 we don't need to handle this at all. */
1175 if (GET_CODE (addr) == POST_INC)
1176 return "ldw 4(0,%1),%R0\n\tldws,ma 8(0,%1),%0";
1177 return "ldw 4(0,%1),%R0\n\tldws,ma -8(0,%1),%0";
1178 }
1179 }
1180 else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
1181 {
1182 rtx high_reg = gen_rtx (SUBREG, SImode, operands[0], 0);
1183
1184 operands[1] = XEXP (addr, 0);
1185 if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG)
1186 abort ();
1187
1188 if (!reg_overlap_mentioned_p (high_reg, addr))
1189 {
1190 /* No overlap between high target register and address
3857fa62 1191 register. (We do this in a non-obvious way to
87ad11b0 1192 save a register file writeback) */
1193 if (GET_CODE (addr) == PRE_INC)
1194 return "ldws,mb 8(0,%1),%0\n\tldw 4(0,%1),%R0";
1195 return "ldws,mb -8(0,%1),%0\n\tldw 4(0,%1),%R0";
1196 }
1197 else
1198 {
1199 /* This is an undefined situation. We should load into the
1200 address register *and* update that register. Probably
1201 we don't need to handle this at all. */
1202 if (GET_CODE (addr) == PRE_INC)
1203 return "ldw 12(0,%1),%R0\n\tldws,mb 8(0,%1),%0";
1204 return "ldw -4(0,%1),%R0\n\tldws,mb -8(0,%1),%0";
1205 }
1206 }
1207 }
1208
1209 /* If an operand is an unoffsettable memory ref, find a register
1210 we can increment temporarily to make it refer to the second word. */
1211
1212 if (optype0 == MEMOP)
1213 addreg0 = find_addr_reg (XEXP (operands[0], 0));
1214
1215 if (optype1 == MEMOP)
1216 addreg1 = find_addr_reg (XEXP (operands[1], 0));
1217
1218 /* Ok, we can do one word at a time.
1219 Normally we do the low-numbered word first.
1220
1221 In either case, set up in LATEHALF the operands to use
1222 for the high-numbered word and in some cases alter the
1223 operands in OPERANDS to be suitable for the low-numbered word. */
1224
1225 if (optype0 == REGOP)
1226 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1227 else if (optype0 == OFFSOP)
1228 latehalf[0] = adj_offsettable_operand (operands[0], 4);
1229 else
1230 latehalf[0] = operands[0];
1231
1232 if (optype1 == REGOP)
1233 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1234 else if (optype1 == OFFSOP)
1235 latehalf[1] = adj_offsettable_operand (operands[1], 4);
1236 else if (optype1 == CNSTOP)
1237 split_double (operands[1], &operands[1], &latehalf[1]);
1238 else
1239 latehalf[1] = operands[1];
1240
1241 /* If the first move would clobber the source of the second one,
1242 do them in the other order.
1243
1244 RMS says "This happens only for registers;
1245 such overlap can't happen in memory unless the user explicitly
1246 sets it up, and that is an undefined circumstance."
1247
1248 but it happens on the HP-PA when loading parameter registers,
1249 so I am going to define that circumstance, and make it work
1250 as expected. */
1251
1252 if (optype0 == REGOP && (optype1 == MEMOP || optype1 == OFFSOP)
1253 && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))
1254 {
1255 /* XXX THIS PROBABLY DOESN'T WORK. */
1256 /* Do the late half first. */
1257 if (addreg1)
6a5d085a 1258 output_asm_insn ("ldo 4(%0),%0", &addreg1);
87ad11b0 1259 output_asm_insn (singlemove_string (latehalf), latehalf);
1260 if (addreg1)
6a5d085a 1261 output_asm_insn ("ldo -4(%0),%0", &addreg1);
87ad11b0 1262 /* Then clobber. */
1263 return singlemove_string (operands);
1264 }
1265
c4fa5937 1266 if (optype0 == REGOP && optype1 == REGOP
1267 && REGNO (operands[0]) == REGNO (operands[1]) + 1)
1268 {
1269 output_asm_insn (singlemove_string (latehalf), latehalf);
1270 return singlemove_string (operands);
1271 }
1272
87ad11b0 1273 /* Normal case: do the two words, low-numbered first. */
1274
1275 output_asm_insn (singlemove_string (operands), operands);
1276
1277 /* Make any unoffsettable addresses point at high-numbered word. */
1278 if (addreg0)
6a5d085a 1279 output_asm_insn ("ldo 4(%0),%0", &addreg0);
87ad11b0 1280 if (addreg1)
6a5d085a 1281 output_asm_insn ("ldo 4(%0),%0", &addreg1);
87ad11b0 1282
1283 /* Do that word. */
1284 output_asm_insn (singlemove_string (latehalf), latehalf);
1285
1286 /* Undo the adds we just did. */
1287 if (addreg0)
6a5d085a 1288 output_asm_insn ("ldo -4(%0),%0", &addreg0);
87ad11b0 1289 if (addreg1)
6a5d085a 1290 output_asm_insn ("ldo -4(%0),%0", &addreg1);
87ad11b0 1291
1292 return "";
1293}
1294\f
1295char *
1296output_fp_move_double (operands)
1297 rtx *operands;
1298{
1299 if (FP_REG_P (operands[0]))
1300 {
6d36483b 1301 if (FP_REG_P (operands[1])
891b55b4 1302 || operands[1] == CONST0_RTX (GET_MODE (operands[0])))
1303 output_asm_insn ("fcpy,dbl %r1,%0", operands);
6d36483b 1304 else
87ad11b0 1305 output_asm_insn ("fldds%F1 %1,%0", operands);
1306 }
1307 else if (FP_REG_P (operands[1]))
1308 {
23b9e2b3 1309 output_asm_insn ("fstds%F0 %1,%0", operands);
87ad11b0 1310 }
891b55b4 1311 else if (operands[1] == CONST0_RTX (GET_MODE (operands[0])))
1312 {
1313 if (GET_CODE (operands[0]) == REG)
1314 {
1315 rtx xoperands[2];
1316 xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1317 xoperands[0] = operands[0];
1318 output_asm_insn ("copy %%r0,%0\n\tcopy %%r0,%1", xoperands);
1319 }
6d36483b 1320 /* This is a pain. You have to be prepared to deal with an
891b55b4 1321 arbritary address here including pre/post increment/decrement.
1322
1323 so avoid this in the MD. */
1324 else
1325 abort ();
1326 }
87ad11b0 1327 else abort ();
1328 return "";
1329}
1330\f
1331/* Return a REG that occurs in ADDR with coefficient 1.
1332 ADDR can be effectively incremented by incrementing REG. */
1333
1334static rtx
1335find_addr_reg (addr)
1336 rtx addr;
1337{
1338 while (GET_CODE (addr) == PLUS)
1339 {
1340 if (GET_CODE (XEXP (addr, 0)) == REG)
1341 addr = XEXP (addr, 0);
1342 else if (GET_CODE (XEXP (addr, 1)) == REG)
1343 addr = XEXP (addr, 1);
1344 else if (CONSTANT_P (XEXP (addr, 0)))
1345 addr = XEXP (addr, 1);
1346 else if (CONSTANT_P (XEXP (addr, 1)))
1347 addr = XEXP (addr, 0);
1348 else
1349 abort ();
1350 }
1351 if (GET_CODE (addr) == REG)
1352 return addr;
1353 abort ();
1354}
1355
87ad11b0 1356/* Emit code to perform a block move.
1357
1358 Restriction: If the length argument is non-constant, alignment
1359 must be 4.
1360
1361 OPERANDS[0] is the destination pointer as a REG, clobbered.
1362 OPERANDS[1] is the source pointer as a REG, clobbered.
1363 if SIZE_IS_CONSTANT
1364 OPERANDS[2] is a register for temporary storage.
1365 OPERANDS[4] is the size as a CONST_INT
1366 else
1367 OPERANDS[2] is a REG which will contain the size, clobbered.
1368 OPERANDS[3] is a register for temporary storage.
1369 OPERANDS[5] is the alignment safe to use, as a CONST_INT. */
1370
1371char *
1372output_block_move (operands, size_is_constant)
1373 rtx *operands;
1374 int size_is_constant;
1375{
1376 int align = INTVAL (operands[5]);
1377 unsigned long n_bytes;
1378
1379 /* We can't move more than four bytes at a time because the PA
1380 has no longer integer move insns. (Could use fp mem ops?) */
1381 if (align > 4)
1382 align = 4;
1383
1384 if (size_is_constant)
1385 {
87ad11b0 1386 unsigned long offset;
1387 rtx temp;
1388
1389 n_bytes = INTVAL (operands[4]);
1390 if (n_bytes == 0)
1391 return "";
1392
1393 if (align >= 4)
1394 {
1395 /* Don't unroll too large blocks. */
6d36483b 1396 if (n_bytes > 32)
87ad11b0 1397 goto copy_with_loop;
1398
1399 /* Read and store using two registers, and hide latency
4bbea254 1400 by deferring the stores until three instructions after
87ad11b0 1401 the corresponding load. The last load insn will read
1402 the entire word were the last bytes are, possibly past
1403 the end of the source block, but since loads are aligned,
1404 this is harmless. */
1405
1406 output_asm_insn ("ldws,ma 4(0,%1),%2", operands);
1407
1408 for (offset = 4; offset < n_bytes; offset += 4)
1409 {
1410 output_asm_insn ("ldws,ma 4(0,%1),%3", operands);
1411 output_asm_insn ("stws,ma %2,4(0,%0)", operands);
1412
1413 temp = operands[2];
1414 operands[2] = operands[3];
1415 operands[3] = temp;
1416 }
1417 if (n_bytes % 4 == 0)
1418 /* Store the last word. */
1419 output_asm_insn ("stw %2,0(0,%0)", operands);
1420 else
1421 {
1422 /* Store the last, partial word. */
1423 operands[4] = gen_rtx (CONST_INT, VOIDmode, n_bytes % 4);
1424 output_asm_insn ("stbys,e %2,%4(0,%0)", operands);
1425 }
1426 return "";
1427 }
1428
1429 if (align >= 2 && n_bytes >= 2)
1430 {
1431 output_asm_insn ("ldhs,ma 2(0,%1),%2", operands);
1432
1433 for (offset = 2; offset + 2 <= n_bytes; offset += 2)
1434 {
1435 output_asm_insn ("ldhs,ma 2(0,%1),%3", operands);
1436 output_asm_insn ("sths,ma %2,2(0,%0)", operands);
1437
1438 temp = operands[2];
1439 operands[2] = operands[3];
1440 operands[3] = temp;
1441 }
1442 if (n_bytes % 2 != 0)
1443 output_asm_insn ("ldb 0(0,%1),%3", operands);
1444
1445 output_asm_insn ("sths,ma %2,2(0,%0)", operands);
1446
1447 if (n_bytes % 2 != 0)
1448 output_asm_insn ("stb %3,0(0,%0)", operands);
1449
1450 return "";
1451 }
1452
1453 output_asm_insn ("ldbs,ma 1(0,%1),%2", operands);
1454
1455 for (offset = 1; offset + 1 <= n_bytes; offset += 1)
1456 {
1457 output_asm_insn ("ldbs,ma 1(0,%1),%3", operands);
1458 output_asm_insn ("stbs,ma %2,1(0,%0)", operands);
1459
1460 temp = operands[2];
1461 operands[2] = operands[3];
1462 operands[3] = temp;
1463 }
1464 output_asm_insn ("stb %2,0(0,%0)", operands);
1465
1466 return "";
1467 }
1468
1469 if (align != 4)
1470 abort();
6d36483b 1471
87ad11b0 1472 copy_with_loop:
1473
1474 if (size_is_constant)
1475 {
a3217f65 1476 /* Size is compile-time determined, and also not
87ad11b0 1477 very small (such small cases are handled above). */
1478 operands[4] = gen_rtx (CONST_INT, VOIDmode, n_bytes - 4);
1479 output_asm_insn ("ldo %4(0),%2", operands);
1480 }
1481 else
1482 {
1483 /* Decrement counter by 4, and if it becomes negative, jump past the
1484 word copying loop. */
1485 output_asm_insn ("addib,<,n -4,%2,.+16", operands);
1486 }
1487
4bbea254 1488 /* Copying loop. Note that the first load is in the annulled delay slot
87ad11b0 1489 of addib. Is it OK on PA to have a load in a delay slot, i.e. is a
1490 possible page fault stopped in time? */
1491 output_asm_insn ("ldws,ma 4(0,%1),%3", operands);
1492 output_asm_insn ("addib,>= -4,%2,.-4", operands);
1493 output_asm_insn ("stws,ma %3,4(0,%0)", operands);
1494
1495 /* The counter is negative, >= -4. The remaining number of bytes are
1496 determined by the two least significant bits. */
1497
1498 if (size_is_constant)
1499 {
1500 if (n_bytes % 4 != 0)
1501 {
1502 /* Read the entire word of the source block tail. */
1503 output_asm_insn ("ldw 0(0,%1),%3", operands);
1504 operands[4] = gen_rtx (CONST_INT, VOIDmode, n_bytes % 4);
1505 output_asm_insn ("stbys,e %3,%4(0,%0)", operands);
1506 }
1507 }
1508 else
1509 {
1510 /* Add 4 to counter. If it becomes zero, we're done. */
1511 output_asm_insn ("addib,=,n 4,%2,.+16", operands);
1512
1513 /* Read the entire word of the source block tail. (Also this
4bbea254 1514 load is in an annulled delay slot.) */
87ad11b0 1515 output_asm_insn ("ldw 0(0,%1),%3", operands);
1516
1517 /* Make %0 point at the first byte after the destination block. */
df0651dc 1518 output_asm_insn ("addl %2,%0,%0", operands);
87ad11b0 1519 /* Store the leftmost bytes, up to, but not including, the address
1520 in %0. */
1521 output_asm_insn ("stbys,e %3,0(0,%0)", operands);
1522 }
1523 return "";
1524}
58e17b0b 1525
1526/* Count the number of insns necessary to handle this block move.
1527
1528 Basic structure is the same as emit_block_move, except that we
1529 count insns rather than emit them. */
1530
1531int
1532compute_movstrsi_length (insn)
1533 rtx insn;
1534{
1535 rtx pat = PATTERN (insn);
1536 int size_is_constant;
1537 int align = INTVAL (XEXP (XVECEXP (pat, 0, 6), 0));
1538 unsigned long n_bytes;
1539 int insn_count = 0;
1540
1541 if (GET_CODE (XEXP (XVECEXP (pat, 0, 5), 0)) == CONST_INT)
1542 {
1543 size_is_constant = 1;
1544 n_bytes = INTVAL (XEXP (XVECEXP (pat, 0, 5), 0));
1545 }
1546 else
1547 {
1548 size_is_constant = 0;
1549 n_bytes = 0;
1550 }
1551
1552 /* We can't move more than four bytes at a time because the PA
1553 has no longer integer move insns. (Could use fp mem ops?) */
1554 if (align > 4)
1555 align = 4;
1556
1557 if (size_is_constant)
1558 {
58e17b0b 1559 unsigned long offset;
58e17b0b 1560
1561 if (n_bytes == 0)
1562 return 0;
1563
1564 if (align >= 4)
1565 {
1566 /* Don't unroll too large blocks. */
6d36483b 1567 if (n_bytes > 32)
58e17b0b 1568 goto copy_with_loop;
1569
1570 /* first load */
1571 insn_count = 1;
1572
1573 /* Count the unrolled insns. */
1574 for (offset = 4; offset < n_bytes; offset += 4)
1575 insn_count += 2;
1576
1577 /* Count last store or partial store. */
1578 insn_count += 1;
5a1231ef 1579 return insn_count * 4;
58e17b0b 1580 }
1581
1582 if (align >= 2 && n_bytes >= 2)
1583 {
1584 /* initial load. */
1585 insn_count = 1;
1586
1587 /* Unrolled loop. */
1588 for (offset = 2; offset + 2 <= n_bytes; offset += 2)
1589 insn_count += 2;
1590
1591 /* ??? odd load/store */
1592 if (n_bytes % 2 != 0)
1593 insn_count += 2;
1594
1595 /* ??? final store from loop. */
1596 insn_count += 1;
1597
5a1231ef 1598 return insn_count * 4;
58e17b0b 1599 }
1600
1601 /* First load. */
1602 insn_count = 1;
1603
1604 /* The unrolled loop. */
1605 for (offset = 1; offset + 1 <= n_bytes; offset += 1)
1606 insn_count += 2;
1607
1608 /* Final store. */
1609 insn_count += 1;
1610
5a1231ef 1611 return insn_count * 4;
58e17b0b 1612 }
1613
1614 if (align != 4)
1615 abort();
6d36483b 1616
58e17b0b 1617 copy_with_loop:
1618
1619 /* setup for constant and non-constant case. */
1620 insn_count = 1;
1621
1622 /* The copying loop. */
1623 insn_count += 3;
1624
1625 /* The counter is negative, >= -4. The remaining number of bytes are
1626 determined by the two least significant bits. */
1627
1628 if (size_is_constant)
1629 {
1630 if (n_bytes % 4 != 0)
1631 insn_count += 2;
1632 }
1633 else
1634 insn_count += 4;
5a1231ef 1635 return insn_count * 4;
58e17b0b 1636}
87ad11b0 1637\f
1638
e057641f 1639char *
1640output_and (operands)
1641 rtx *operands;
1642{
d6f01525 1643 if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
e057641f 1644 {
1645 unsigned mask = INTVAL (operands[2]);
1646 int ls0, ls1, ms0, p, len;
1647
1648 for (ls0 = 0; ls0 < 32; ls0++)
1649 if ((mask & (1 << ls0)) == 0)
1650 break;
1651
1652 for (ls1 = ls0; ls1 < 32; ls1++)
1653 if ((mask & (1 << ls1)) != 0)
1654 break;
1655
1656 for (ms0 = ls1; ms0 < 32; ms0++)
1657 if ((mask & (1 << ms0)) == 0)
1658 break;
1659
1660 if (ms0 != 32)
1661 abort();
1662
1663 if (ls1 == 32)
1664 {
1665 len = ls0;
1666
1667 if (len == 0)
1668 abort ();
1669
1670 operands[2] = gen_rtx (CONST_INT, VOIDmode, len);
1671 return "extru %1,31,%2,%0";
1672 }
1673 else
1674 {
1675 /* We could use this `depi' for the case above as well, but `depi'
1676 requires one more register file access than an `extru'. */
1677
1678 p = 31 - ls0;
1679 len = ls1 - ls0;
1680
1681 operands[2] = gen_rtx (CONST_INT, VOIDmode, p);
1682 operands[3] = gen_rtx (CONST_INT, VOIDmode, len);
1683 return "depi 0,%2,%3,%0";
1684 }
1685 }
1686 else
1687 return "and %1,%2,%0";
1688}
1689
1690char *
1691output_ior (operands)
1692 rtx *operands;
1693{
c9da5f4d 1694 unsigned mask = INTVAL (operands[2]);
57ed30e5 1695 int bs0, bs1, p, len;
6d36483b 1696
c9da5f4d 1697 if (INTVAL (operands[2]) == 0)
1698 return "copy %1,%0";
e057641f 1699
c9da5f4d 1700 for (bs0 = 0; bs0 < 32; bs0++)
1701 if ((mask & (1 << bs0)) != 0)
1702 break;
e057641f 1703
c9da5f4d 1704 for (bs1 = bs0; bs1 < 32; bs1++)
1705 if ((mask & (1 << bs1)) == 0)
1706 break;
e057641f 1707
c9da5f4d 1708 if (bs1 != 32 && ((unsigned) 1 << bs1) <= mask)
1709 abort();
e057641f 1710
c9da5f4d 1711 p = 31 - bs0;
1712 len = bs1 - bs0;
e057641f 1713
c9da5f4d 1714 operands[2] = gen_rtx (CONST_INT, VOIDmode, p);
1715 operands[3] = gen_rtx (CONST_INT, VOIDmode, len);
1716 return "depi -1,%2,%3,%0";
e057641f 1717}
1718\f
87ad11b0 1719/* Output an ascii string. */
57ed30e5 1720void
87ad11b0 1721output_ascii (file, p, size)
1722 FILE *file;
1723 unsigned char *p;
1724 int size;
1725{
1726 int i;
1727 int chars_output;
1728 unsigned char partial_output[16]; /* Max space 4 chars can occupy. */
1729
1730 /* The HP assembler can only take strings of 256 characters at one
1731 time. This is a limitation on input line length, *not* the
1732 length of the string. Sigh. Even worse, it seems that the
1733 restriction is in number of input characters (see \xnn &
1734 \whatever). So we have to do this very carefully. */
1735
1736 fprintf (file, "\t.STRING \"");
1737
1738 chars_output = 0;
1739 for (i = 0; i < size; i += 4)
1740 {
1741 int co = 0;
1742 int io = 0;
1743 for (io = 0, co = 0; io < MIN (4, size - i); io++)
1744 {
1745 register unsigned int c = p[i + io];
1746
1747 if (c == '\"' || c == '\\')
1748 partial_output[co++] = '\\';
1749 if (c >= ' ' && c < 0177)
1750 partial_output[co++] = c;
1751 else
1752 {
1753 unsigned int hexd;
1754 partial_output[co++] = '\\';
1755 partial_output[co++] = 'x';
1756 hexd = c / 16 - 0 + '0';
1757 if (hexd > '9')
1758 hexd -= '9' - 'a' + 1;
1759 partial_output[co++] = hexd;
1760 hexd = c % 16 - 0 + '0';
1761 if (hexd > '9')
1762 hexd -= '9' - 'a' + 1;
1763 partial_output[co++] = hexd;
1764 }
1765 }
1766 if (chars_output + co > 243)
1767 {
1768 fprintf (file, "\"\n\t.STRING \"");
1769 chars_output = 0;
1770 }
1771 fwrite (partial_output, 1, co, file);
1772 chars_output += co;
1773 co = 0;
1774 }
1775 fprintf (file, "\"\n");
1776}
1777\f
201f01e9 1778/* You may have trouble believing this, but this is the HP-PA stack
87ad11b0 1779 layout. Wow.
1780
1781 Offset Contents
1782
1783 Variable arguments (optional; any number may be allocated)
1784
1785 SP-(4*(N+9)) arg word N
1786 : :
1787 SP-56 arg word 5
1788 SP-52 arg word 4
1789
1790 Fixed arguments (must be allocated; may remain unused)
1791
1792 SP-48 arg word 3
1793 SP-44 arg word 2
1794 SP-40 arg word 1
1795 SP-36 arg word 0
1796
1797 Frame Marker
1798
1799 SP-32 External Data Pointer (DP)
1800 SP-28 External sr4
1801 SP-24 External/stub RP (RP')
1802 SP-20 Current RP
1803 SP-16 Static Link
1804 SP-12 Clean up
1805 SP-8 Calling Stub RP (RP'')
1806 SP-4 Previous SP
1807
1808 Top of Frame
1809
1810 SP-0 Stack Pointer (points to next available address)
1811
1812*/
1813
1814/* This function saves registers as follows. Registers marked with ' are
1815 this function's registers (as opposed to the previous function's).
1816 If a frame_pointer isn't needed, r4 is saved as a general register;
1817 the space for the frame pointer is still allocated, though, to keep
1818 things simple.
1819
1820
1821 Top of Frame
1822
1823 SP (FP') Previous FP
1824 SP + 4 Alignment filler (sigh)
1825 SP + 8 Space for locals reserved here.
1826 .
1827 .
1828 .
1829 SP + n All call saved register used.
1830 .
1831 .
1832 .
1833 SP + o All call saved fp registers used.
1834 .
1835 .
1836 .
1837 SP + p (SP') points to next available address.
6d36483b 1838
87ad11b0 1839*/
1840
daee63dd 1841/* Emit RTL to store REG at the memory location specified by BASE+DISP.
1842 Handle case where DISP > 8k by using the add_high_const pattern.
1843
1844 Note in DISP > 8k case, we will leave the high part of the address
1845 in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/
1846static void
1847store_reg (reg, disp, base)
1848 int reg, disp, base;
87ad11b0 1849{
1850 if (VAL_14_BITS_P (disp))
daee63dd 1851 {
6d36483b 1852 emit_move_insn (gen_rtx (MEM, SImode,
1853 gen_rtx (PLUS, SImode,
daee63dd 1854 gen_rtx (REG, SImode, base),
1855 GEN_INT (disp))),
1856 gen_rtx (REG, SImode, reg));
1857 }
87ad11b0 1858 else
daee63dd 1859 {
6d36483b 1860 emit_insn (gen_add_high_const (gen_rtx (REG, SImode, 1),
1861 gen_rtx (REG, SImode, base),
daee63dd 1862 GEN_INT (disp)));
1863 emit_move_insn (gen_rtx (MEM, SImode,
6d36483b 1864 gen_rtx (LO_SUM, SImode,
daee63dd 1865 gen_rtx (REG, SImode, 1),
1866 GEN_INT (disp))),
1867 gen_rtx (REG, SImode, reg));
1868 }
87ad11b0 1869}
1870
daee63dd 1871/* Emit RTL to load REG from the memory location specified by BASE+DISP.
1872 Handle case where DISP > 8k by using the add_high_const pattern.
1873
1874 Note in DISP > 8k case, we will leave the high part of the address
1875 in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/
1876static void
1877load_reg (reg, disp, base)
1878 int reg, disp, base;
1879{
1880 if (VAL_14_BITS_P (disp))
1881 {
1882 emit_move_insn (gen_rtx (REG, SImode, reg),
6d36483b 1883 gen_rtx (MEM, SImode,
1884 gen_rtx (PLUS, SImode,
daee63dd 1885 gen_rtx (REG, SImode, base),
1886 GEN_INT (disp))));
daee63dd 1887 }
1888 else
1889 {
6d36483b 1890 emit_insn (gen_add_high_const (gen_rtx (REG, SImode, 1),
daee63dd 1891 gen_rtx (REG, SImode, base),
1892 GEN_INT (disp)));
1893 emit_move_insn (gen_rtx (REG, SImode, reg),
1894 gen_rtx (MEM, SImode,
6d36483b 1895 gen_rtx (LO_SUM, SImode,
1896 gen_rtx (REG, SImode, 1),
daee63dd 1897 GEN_INT (disp))));
1898 }
1899}
1900
1901/* Emit RTL to set REG to the value specified by BASE+DISP.
1902 Handle case where DISP > 8k by using the add_high_const pattern.
1903
1904 Note in DISP > 8k case, we will leave the high part of the address
1905 in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/
1906static void
1907set_reg_plus_d(reg, base, disp)
1908 int reg, base, disp;
87ad11b0 1909{
1910 if (VAL_14_BITS_P (disp))
daee63dd 1911 {
1912 emit_move_insn (gen_rtx (REG, SImode, reg),
6d36483b 1913 gen_rtx (PLUS, SImode,
daee63dd 1914 gen_rtx (REG, SImode, base),
1915 GEN_INT (disp)));
daee63dd 1916 }
87ad11b0 1917 else
daee63dd 1918 {
6d36483b 1919 emit_insn (gen_add_high_const (gen_rtx (REG, SImode, 1),
daee63dd 1920 gen_rtx (REG, SImode, base),
1921 GEN_INT (disp)));
1922 emit_move_insn (gen_rtx (REG, SImode, reg),
6d36483b 1923 gen_rtx (LO_SUM, SImode,
daee63dd 1924 gen_rtx (REG, SImode, 1),
1925 GEN_INT (disp)));
1926 }
87ad11b0 1927}
1928
3ddcbb9d 1929/* Global variables set by FUNCTION_PROLOGUE. */
1930/* Size of frame. Need to know this to emit return insns from
1931 leaf procedures. */
a1ab4fa3 1932static int actual_fsize;
1933static int local_fsize, save_fregs;
3ddcbb9d 1934
87ad11b0 1935int
a1ab4fa3 1936compute_frame_size (size, fregs_live)
87ad11b0 1937 int size;
3ddcbb9d 1938 int *fregs_live;
87ad11b0 1939{
1940 extern int current_function_outgoing_args_size;
a1ab4fa3 1941 int i, fsize;
87ad11b0 1942
6d36483b 1943 /* 8 is space for frame pointer + filler. If any frame is allocated
a1ab4fa3 1944 we need to add this in because of STARTING_FRAME_OFFSET. */
1945 fsize = size + (size || frame_pointer_needed ? 8 : 0);
87ad11b0 1946
df0651dc 1947 for (i = 18; i >= 4; i--)
daee63dd 1948 {
df0651dc 1949 if (regs_ever_live[i])
daee63dd 1950 fsize += 4;
1951 }
df0651dc 1952 /* If we don't have a frame pointer, the register normally used for that
1953 purpose is saved just like other registers, not in the "frame marker". */
1954 if (! frame_pointer_needed)
87ad11b0 1955 {
df0651dc 1956 if (regs_ever_live[FRAME_POINTER_REGNUM])
1957 fsize += 4;
87ad11b0 1958 }
df0651dc 1959 fsize = (fsize + 7) & ~7;
1960
1961 for (i = 66; i >= 48; i -= 2)
1962 if (regs_ever_live[i] || regs_ever_live[i + 1])
1963 {
1964 fsize += 8;
1965 if (fregs_live)
1966 *fregs_live = 1;
1967 }
1968
a1ab4fa3 1969 fsize += current_function_outgoing_args_size;
1970 if (! leaf_function_p () || fsize)
1971 fsize += 32;
57ed30e5 1972 return (fsize + 63) & ~63;
87ad11b0 1973}
6d36483b 1974
daee63dd 1975rtx hp_profile_label_rtx;
1976static char hp_profile_label_name[8];
87ad11b0 1977void
a1ab4fa3 1978output_function_prologue (file, size)
87ad11b0 1979 FILE *file;
1980 int size;
87ad11b0 1981{
d151162a 1982 /* The function's label and associated .PROC must never be
1983 separated and must be output *after* any profiling declarations
1984 to avoid changing spaces/subspaces within a procedure. */
1985 ASM_OUTPUT_LABEL (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
1986 fputs ("\t.PROC\n", file);
1987
daee63dd 1988 /* hppa_expand_prologue does the dirty work now. We just need
1989 to output the assembler directives which denote the start
1990 of a function. */
2acd4f33 1991 fprintf (file, "\t.CALLINFO FRAME=%d", actual_fsize);
daee63dd 1992 if (regs_ever_live[2] || profile_flag)
f3ba7709 1993 fprintf (file, ",CALLS,SAVE_RP");
daee63dd 1994 else
f3ba7709 1995 fprintf (file, ",NO_CALLS");
1996
1997 if (frame_pointer_needed)
1998 fprintf (file, ",SAVE_SP");
1999
a9960cdc 2000 /* Pass on information about the number of callee register saves
9b0c95be 2001 performed in the prologue.
2002
2003 The compiler is supposed to pass the highest register number
6d36483b 2004 saved, the assembler then has to adjust that number before
9b0c95be 2005 entering it into the unwind descriptor (to account for any
6d36483b 2006 caller saved registers with lower register numbers than the
9b0c95be 2007 first callee saved register). */
2008 if (gr_saved)
2009 fprintf (file, ",ENTRY_GR=%d", gr_saved + 2);
2010
2011 if (fr_saved)
2012 fprintf (file, ",ENTRY_FR=%d", fr_saved + 11);
a9960cdc 2013
f3ba7709 2014 fprintf (file, "\n\t.ENTRY\n");
daee63dd 2015
2016 /* Horrid hack. emit_function_prologue will modify this RTL in
2017 place to get the expected results. */
2018 if (profile_flag)
07b209fc 2019 ASM_GENERATE_INTERNAL_LABEL (hp_profile_label_name, "LP",
2020 hp_profile_labelno);
daee63dd 2021}
2022
57ed30e5 2023void
daee63dd 2024hppa_expand_prologue()
2025{
87ad11b0 2026 extern char call_used_regs[];
daee63dd 2027 int size = get_frame_size ();
afd7b680 2028 int merge_sp_adjust_with_store = 0;
daee63dd 2029 int i, offset;
2030 rtx tmpreg, size_rtx;
2031
a9960cdc 2032 gr_saved = 0;
2033 fr_saved = 0;
3ddcbb9d 2034 save_fregs = 0;
a1ab4fa3 2035 local_fsize = size + (size || frame_pointer_needed ? 8 : 0);
2036 actual_fsize = compute_frame_size (size, &save_fregs);
87ad11b0 2037
daee63dd 2038 /* Compute a few things we will use often. */
2039 tmpreg = gen_rtx (REG, SImode, 1);
2040 size_rtx = GEN_INT (actual_fsize);
87ad11b0 2041
6d36483b 2042 /* Save RP first. The calling conventions manual states RP will
daee63dd 2043 always be stored into the caller's frame at sp-20. */
372ef038 2044 if (regs_ever_live[2] || profile_flag)
6d36483b 2045 store_reg (2, -20, STACK_POINTER_REGNUM);
2046
daee63dd 2047 /* Allocate the local frame and set up the frame pointer if needed. */
a1ab4fa3 2048 if (actual_fsize)
2049 if (frame_pointer_needed)
2050 {
daee63dd 2051 /* Copy the old frame pointer temporarily into %r1. Set up the
2052 new stack pointer, then store away the saved old frame pointer
2053 into the stack at sp+actual_fsize and at the same time update
2054 the stack pointer by actual_fsize bytes. Two versions, first
2055 handles small (<8k) frames. The second handles large (>8k)
2056 frames. */
2057 emit_move_insn (tmpreg, frame_pointer_rtx);
2058 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
a1ab4fa3 2059 if (VAL_14_BITS_P (actual_fsize))
daee63dd 2060 emit_insn (gen_post_stwm (stack_pointer_rtx,
2061 stack_pointer_rtx,
2062 size_rtx, tmpreg));
a1ab4fa3 2063 else
2064 {
daee63dd 2065 store_reg (1, 0, FRAME_POINTER_REGNUM);
2066 set_reg_plus_d (STACK_POINTER_REGNUM,
2067 STACK_POINTER_REGNUM,
2068 actual_fsize);
a1ab4fa3 2069 }
2070 }
daee63dd 2071 /* no frame pointer needed. */
a1ab4fa3 2072 else
a1ab4fa3 2073 {
daee63dd 2074 /* In some cases we can perform the first callee register save
2075 and allocating the stack frame at the same time. If so, just
2076 make a note of it and defer allocating the frame until saving
2077 the callee registers. */
6d36483b 2078 if (VAL_14_BITS_P (-actual_fsize)
2079 && local_fsize == 0
daee63dd 2080 && ! profile_flag
2081 && ! flag_pic)
afd7b680 2082 merge_sp_adjust_with_store = 1;
daee63dd 2083 /* Can not optimize. Adjust the stack frame by actual_fsize bytes. */
2084 else if (actual_fsize != 0)
2085 set_reg_plus_d (STACK_POINTER_REGNUM,
2086 STACK_POINTER_REGNUM,
2087 actual_fsize);
a1ab4fa3 2088 }
201f01e9 2089 /* The hppa calling conventions say that that %r19, the pic offset
daee63dd 2090 register, is saved at sp - 32 (in this function's frame) when
2091 generating PIC code. */
d6f01525 2092 if (flag_pic)
6d36483b 2093 store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM);
daee63dd 2094
2095 /* Profiling code.
372ef038 2096
daee63dd 2097 Instead of taking one argument, the counter label, as most normal
2098 mcounts do, _mcount appears to behave differently on the HPPA. It
6d36483b 2099 takes the return address of the caller, the address of this routine,
2100 and the address of the label. Also, it isn't magic, so
daee63dd 2101 argument registre hsave to be preserved. */
372ef038 2102 if (profile_flag)
2103 {
daee63dd 2104 int pc_offset, i, arg_offset, basereg, offsetadj;
2105
2106 pc_offset = 4 + (frame_pointer_needed
2107 ? (VAL_14_BITS_P (actual_fsize) ? 12 : 20)
2108 : (VAL_14_BITS_P (actual_fsize) ? 4 : 8));
2109
2110 /* When the function has a frame pointer, use it as the base
2111 register for saving/restore registers. Else use the stack
2112 pointer. Adjust the offset according to the frame size if
2113 this function does not have a frame pointer. */
d2daf090 2114
2115 basereg = frame_pointer_needed ? FRAME_POINTER_REGNUM
2116 : STACK_POINTER_REGNUM;
2117 offsetadj = frame_pointer_needed ? 0 : actual_fsize;
2118
daee63dd 2119 /* Horrid hack. emit_function_prologue will modify this RTL in
2120 place to get the expected results. sprintf here is just to
2121 put something in the name. */
2122 sprintf(hp_profile_label_name, "LP$%04d", -1);
2123 hp_profile_label_rtx = gen_rtx (SYMBOL_REF, SImode,
2124 hp_profile_label_name);
d6f01525 2125 if (current_function_returns_struct)
daee63dd 2126 store_reg (STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg);
2127
d2daf090 2128 for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4)
daee63dd 2129 if (regs_ever_live [i])
372ef038 2130 {
daee63dd 2131 store_reg (i, arg_offset, basereg);
2132 /* Deal with arg_offset not fitting in 14 bits. */
d2daf090 2133 pc_offset += VAL_14_BITS_P (arg_offset) ? 4 : 8;
372ef038 2134 }
daee63dd 2135
2136 emit_move_insn (gen_rtx (REG, SImode, 26), gen_rtx (REG, SImode, 2));
2137 emit_move_insn (tmpreg, gen_rtx (HIGH, SImode, hp_profile_label_rtx));
2138 emit_move_insn (gen_rtx (REG, SImode, 24),
2139 gen_rtx (LO_SUM, SImode, tmpreg, hp_profile_label_rtx));
2140 /* %r25 is set from within the output pattern. */
2141 emit_insn (gen_call_profiler (GEN_INT (- pc_offset - 20)));
2142
2143 /* Restore argument registers. */
d2daf090 2144 for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4)
daee63dd 2145 if (regs_ever_live [i])
2146 load_reg (i, arg_offset, basereg);
2147
d6f01525 2148 if (current_function_returns_struct)
daee63dd 2149 load_reg (STRUCT_VALUE_REGNUM, -12 - offsetadj, basereg);
2150
372ef038 2151 }
2152
6d36483b 2153 /* Normal register save.
daee63dd 2154
2155 Do not save the frame pointer in the frame_pointer_needed case. It
2156 was done earlier. */
87ad11b0 2157 if (frame_pointer_needed)
2158 {
df0651dc 2159 for (i = 18, offset = local_fsize; i >= 4; i--)
2160 if (regs_ever_live[i] && ! call_used_regs[i])
87ad11b0 2161 {
6d36483b 2162 store_reg (i, offset, FRAME_POINTER_REGNUM);
daee63dd 2163 offset += 4;
a9960cdc 2164 gr_saved++;
87ad11b0 2165 }
9b0c95be 2166 /* Account for %r4 which is saved in a special place. */
2167 gr_saved++;
87ad11b0 2168 }
daee63dd 2169 /* No frame pointer needed. */
87ad11b0 2170 else
2171 {
daee63dd 2172 for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)
87ad11b0 2173 if (regs_ever_live[i] && ! call_used_regs[i])
2174 {
6d36483b 2175 /* If merge_sp_adjust_with_store is nonzero, then we can
afd7b680 2176 optimize the first GR save. */
201f01e9 2177 if (merge_sp_adjust_with_store)
afd7b680 2178 {
2179 merge_sp_adjust_with_store = 0;
daee63dd 2180 emit_insn (gen_post_stwm (stack_pointer_rtx,
2181 stack_pointer_rtx,
2182 GEN_INT (-offset),
2183 gen_rtx (REG, SImode, i)));
afd7b680 2184 }
2185 else
daee63dd 2186 store_reg (i, offset, STACK_POINTER_REGNUM);
2187 offset += 4;
a9960cdc 2188 gr_saved++;
87ad11b0 2189 }
daee63dd 2190
afd7b680 2191 /* If we wanted to merge the SP adjustment with a GR save, but we never
daee63dd 2192 did any GR saves, then just emit the adjustment here. */
201f01e9 2193 if (merge_sp_adjust_with_store)
daee63dd 2194 set_reg_plus_d (STACK_POINTER_REGNUM,
2195 STACK_POINTER_REGNUM,
2196 actual_fsize);
87ad11b0 2197 }
6d36483b 2198
87ad11b0 2199 /* Align pointer properly (doubleword boundary). */
2200 offset = (offset + 7) & ~7;
2201
2202 /* Floating point register store. */
2203 if (save_fregs)
87ad11b0 2204 {
daee63dd 2205
2206 /* First get the frame or stack pointer to the start of the FP register
2207 save area. */
a1ab4fa3 2208 if (frame_pointer_needed)
daee63dd 2209 set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset);
a1ab4fa3 2210 else
daee63dd 2211 set_reg_plus_d (1, STACK_POINTER_REGNUM, offset);
2212
2213 /* Now actually save the FP registers. */
df0651dc 2214 for (i = 66; i >= 48; i -= 2)
2215 if (regs_ever_live[i] || regs_ever_live[i + 1])
2216 {
2217 emit_move_insn (gen_rtx (MEM, DFmode,
2218 gen_rtx (POST_INC, DFmode, tmpreg)),
2219 gen_rtx (REG, DFmode, i));
2220 fr_saved++;
2221 }
87ad11b0 2222 }
2223}
2224
daee63dd 2225
87ad11b0 2226void
a1ab4fa3 2227output_function_epilogue (file, size)
87ad11b0 2228 FILE *file;
2229 int size;
87ad11b0 2230{
3695c664 2231
2232 rtx insn = get_last_insn ();
2233
daee63dd 2234 /* hppa_expand_epilogue does the dirty work now. We just need
2235 to output the assembler directives which denote the end
3695c664 2236 of a function.
2237
2238 To make debuggers happy, emit a nop if the epilogue was completely
2239 eliminated due to a volatile call as the last insn in the
6d36483b 2240 current function. That way the return address (in %r2) will
3695c664 2241 always point to a valid instruction in the current function. */
2242
2243 /* Get the last real insn. */
2244 if (GET_CODE (insn) == NOTE)
2245 insn = prev_real_insn (insn);
2246
2247 /* If it is a sequence, then look inside. */
2248 if (insn && GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
2249 insn = XVECEXP (PATTERN (insn), 0, 0);
2250
6d36483b 2251 /* If insn is a CALL_INSN, then it must be a call to a volatile
3695c664 2252 function (otherwise there would be epilogue insns). */
2253 if (insn && GET_CODE (insn) == CALL_INSN)
2254 fprintf (file, "\tnop\n");
6d36483b 2255
daee63dd 2256 fprintf (file, "\t.EXIT\n\t.PROCEND\n");
2257}
afd7b680 2258
daee63dd 2259void
3695c664 2260hppa_expand_epilogue ()
daee63dd 2261{
6d36483b 2262 rtx tmpreg;
daee63dd 2263 int offset,i;
2264 int merge_sp_adjust_with_load = 0;
2265
2266 /* We will use this often. */
2267 tmpreg = gen_rtx (REG, SImode, 1);
2268
2269 /* Try to restore RP early to avoid load/use interlocks when
2270 RP gets used in the return (bv) instruction. This appears to still
2271 be necessary even when we schedule the prologue and epilogue. */
afd7b680 2272 if (frame_pointer_needed
2273 && (regs_ever_live [2] || profile_flag))
daee63dd 2274 load_reg (2, -20, FRAME_POINTER_REGNUM);
87ad11b0 2275
daee63dd 2276 /* No frame pointer, and stack is smaller than 8k. */
2277 else if (! frame_pointer_needed
2278 && VAL_14_BITS_P (actual_fsize + 20)
2279 && (regs_ever_live[2] || profile_flag))
2280 load_reg (2, - (actual_fsize + 20), STACK_POINTER_REGNUM);
2281
2282 /* General register restores. */
87ad11b0 2283 if (frame_pointer_needed)
2284 {
df0651dc 2285 for (i = 18, offset = local_fsize; i >= 4; i--)
2286 if (regs_ever_live[i] && ! call_used_regs[i])
87ad11b0 2287 {
daee63dd 2288 load_reg (i, offset, FRAME_POINTER_REGNUM);
2289 offset += 4;
87ad11b0 2290 }
87ad11b0 2291 }
2292 else
2293 {
daee63dd 2294 for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)
2295 if (regs_ever_live[i] && ! call_used_regs[i])
87ad11b0 2296 {
daee63dd 2297 /* Only for the first load.
2298 merge_sp_adjust_with_load holds the register load
2299 with which we will merge the sp adjustment. */
afd7b680 2300 if (VAL_14_BITS_P (actual_fsize + 20)
2301 && local_fsize == 0
afd7b680 2302 && ! merge_sp_adjust_with_load)
2303 merge_sp_adjust_with_load = i;
daee63dd 2304 else
2305 load_reg (i, offset, STACK_POINTER_REGNUM);
2306 offset += 4;
87ad11b0 2307 }
87ad11b0 2308 }
daee63dd 2309
87ad11b0 2310 /* Align pointer properly (doubleword boundary). */
2311 offset = (offset + 7) & ~7;
2312
daee63dd 2313 /* FP register restores. */
87ad11b0 2314 if (save_fregs)
87ad11b0 2315 {
daee63dd 2316 /* Adjust the register to index off of. */
a1ab4fa3 2317 if (frame_pointer_needed)
daee63dd 2318 set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset);
a1ab4fa3 2319 else
daee63dd 2320 set_reg_plus_d (1, STACK_POINTER_REGNUM, offset);
2321
2322 /* Actually do the restores now. */
df0651dc 2323 for (i = 66; i >= 48; i -= 2)
2324 if (regs_ever_live[i] || regs_ever_live[i + 1])
2325 emit_move_insn (gen_rtx (REG, DFmode, i),
2326 gen_rtx (MEM, DFmode,
2327 gen_rtx (POST_INC, DFmode, tmpreg)));
87ad11b0 2328 }
daee63dd 2329
2330 /* No frame pointer, but we have a stack greater than 8k. We restore
1921d762 2331 %r2 very late in this case. (All other cases are restored as early
2332 as possible.) */
daee63dd 2333 if (! frame_pointer_needed
2334 && ! VAL_14_BITS_P (actual_fsize + 20)
2335 && (regs_ever_live[2] || profile_flag))
87ad11b0 2336 {
daee63dd 2337 set_reg_plus_d (STACK_POINTER_REGNUM,
2338 STACK_POINTER_REGNUM,
2339 - actual_fsize);
2340 /* Uses value left over in %r1 by set_reg_plus_d. */
2341 load_reg (2, - (actual_fsize + 20 + ((- actual_fsize) & ~0x7ff)), 1);
87ad11b0 2342 }
daee63dd 2343
2344 /* Reset stack pointer (and possibly frame pointer). The stack */
2345 /* pointer is initially set to fp + 64 to avoid a race condition.
2346 ??? What race condition?!? */
2347 else if (frame_pointer_needed)
87ad11b0 2348 {
e03010ce 2349 /* Emit a blockage insn here to keep these insns from being moved
2350 to the beginning of the prologue or into the main instruction
2351 stream, doing so avoids some very obscure problems. */
2352 emit_insn (gen_blockage ());
daee63dd 2353 set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64);
2354 emit_insn (gen_pre_ldwm (stack_pointer_rtx, stack_pointer_rtx,
2355 GEN_INT (-64), frame_pointer_rtx));
87ad11b0 2356 }
daee63dd 2357 /* If we were deferring a callee register restore, do it now. */
2358 else if (! frame_pointer_needed && merge_sp_adjust_with_load)
2359 emit_insn (gen_pre_ldwm (stack_pointer_rtx,
2360 stack_pointer_rtx,
2361 GEN_INT (- actual_fsize),
6d36483b 2362 gen_rtx (REG, SImode,
daee63dd 2363 merge_sp_adjust_with_load)));
2364 else if (actual_fsize != 0)
2365 set_reg_plus_d (STACK_POINTER_REGNUM,
2366 STACK_POINTER_REGNUM,
2367 - actual_fsize);
87ad11b0 2368}
2369
757d4970 2370/* This is only valid once reload has completed because it depends on
2371 knowing exactly how much (if any) frame there is and...
2372
2373 It's only valid if there is no frame marker to de-allocate and...
2374
2375 It's only valid if %r2 hasn't been saved into the caller's frame
2376 (we're not profiling and %r2 isn't live anywhere). */
2377int
2378hppa_can_use_return_insn_p ()
2379{
2380 return (reload_completed
2381 && (compute_frame_size (get_frame_size (), 0) ? 0 : 1)
2382 && ! profile_flag
2383 && ! regs_ever_live[2]
2384 && ! frame_pointer_needed);
2385}
2386
87ad11b0 2387void
2388emit_bcond_fp (code, operand0)
2389 enum rtx_code code;
2390 rtx operand0;
2391{
2392 emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
2393 gen_rtx (IF_THEN_ELSE, VOIDmode,
6d36483b 2394 gen_rtx (code, VOIDmode,
87ad11b0 2395 gen_rtx (REG, CCFPmode, 0),
2396 const0_rtx),
2397 gen_rtx (LABEL_REF, VOIDmode, operand0),
2398 pc_rtx)));
2399
2400}
2401
2402rtx
2403gen_cmp_fp (code, operand0, operand1)
2404 enum rtx_code code;
2405 rtx operand0, operand1;
2406{
2407 return gen_rtx (SET, VOIDmode, gen_rtx (REG, CCFPmode, 0),
2408 gen_rtx (code, CCFPmode, operand0, operand1));
2409}
2410
8b49b3c7 2411/* Adjust the cost of a scheduling dependency. Return the new cost of
2412 a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
2413
2414int
2415pa_adjust_cost (insn, link, dep_insn, cost)
2416 rtx insn;
2417 rtx link;
2418 rtx dep_insn;
2419 int cost;
2420{
d402da4b 2421 if (! recog_memoized (insn))
2422 return 0;
8b49b3c7 2423
2424 if (REG_NOTE_KIND (link) == 0)
2425 {
2426 /* Data dependency; DEP_INSN writes a register that INSN reads some
2427 cycles later. */
2428
2429 if (get_attr_type (insn) == TYPE_FPSTORE)
2430 {
d402da4b 2431 rtx pat = PATTERN (insn);
2432 rtx dep_pat = PATTERN (dep_insn);
2433 if (GET_CODE (pat) == PARALLEL)
2434 {
2435 /* This happens for the fstXs,mb patterns. */
2436 pat = XVECEXP (pat, 0, 0);
2437 }
2438 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
8b49b3c7 2439 /* If this happens, we have to extend this to schedule
d402da4b 2440 optimally. Return 0 for now. */
2441 return 0;
8b49b3c7 2442
d402da4b 2443 if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
8b49b3c7 2444 {
d402da4b 2445 if (! recog_memoized (dep_insn))
2446 return 0;
2447 /* DEP_INSN is writing its result to the register
2448 being stored in the fpstore INSN. */
8b49b3c7 2449 switch (get_attr_type (dep_insn))
2450 {
2451 case TYPE_FPLOAD:
2452 /* This cost 3 cycles, not 2 as the md says. */
2453 return cost + 1;
2454
2455 case TYPE_FPALU:
2456 case TYPE_FPMUL:
2457 case TYPE_FPDIVSGL:
2458 case TYPE_FPDIVDBL:
2459 case TYPE_FPSQRTSGL:
2460 case TYPE_FPSQRTDBL:
2461 /* In these important cases, we save one cycle compared to
2462 when flop instruction feed each other. */
2463 return cost - 1;
2464
2465 default:
2466 return cost;
2467 }
2468 }
2469 }
2470
2471 /* For other data dependencies, the default cost specified in the
2472 md is correct. */
2473 return cost;
2474 }
2475 else if (REG_NOTE_KIND (link) == REG_DEP_ANTI)
2476 {
2477 /* Anti dependency; DEP_INSN reads a register that INSN writes some
2478 cycles later. */
2479
2480 if (get_attr_type (insn) == TYPE_FPLOAD)
2481 {
d402da4b 2482 rtx pat = PATTERN (insn);
2483 rtx dep_pat = PATTERN (dep_insn);
2484 if (GET_CODE (pat) == PARALLEL)
2485 {
2486 /* This happens for the fldXs,mb patterns. */
2487 pat = XVECEXP (pat, 0, 0);
2488 }
2489 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
8b49b3c7 2490 /* If this happens, we have to extend this to schedule
d402da4b 2491 optimally. Return 0 for now. */
2492 return 0;
8b49b3c7 2493
d402da4b 2494 if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat)))
8b49b3c7 2495 {
d402da4b 2496 if (! recog_memoized (dep_insn))
2497 return 0;
8b49b3c7 2498 switch (get_attr_type (dep_insn))
2499 {
2500 case TYPE_FPALU:
2501 case TYPE_FPMUL:
2502 case TYPE_FPDIVSGL:
2503 case TYPE_FPDIVDBL:
2504 case TYPE_FPSQRTSGL:
2505 case TYPE_FPSQRTDBL:
d402da4b 2506 /* A fpload can't be issued until one cycle before a
2507 preceeding arithmetic operation has finished, if
2508 the target of the fpload is any of the sources
2509 (or destination) of the arithmetic operation. */
8b49b3c7 2510 return cost - 1;
2511
2512 default:
2513 return 0;
2514 }
2515 }
2516 }
2517
2518 /* For other anti dependencies, the cost is 0. */
2519 return 0;
2520 }
2521
d402da4b 2522 /* For output dependencies, the cost is often one too high. */
2523 return cost - 1;
8b49b3c7 2524}
87ad11b0 2525
58e17b0b 2526/* Return any length adjustment needed by INSN which already has its length
6d36483b 2527 computed as LENGTH. Return zero if no adjustment is necessary.
58e17b0b 2528
5fbd5940 2529 For the PA: function calls, millicode calls, and backwards short
6d36483b 2530 conditional branches with unfilled delay slots need an adjustment by +1
5fbd5940 2531 (to account for the NOP which will be inserted into the instruction stream).
58e17b0b 2532
2533 Also compute the length of an inline block move here as it is too
5fbd5940 2534 complicated to express as a length attribute in pa.md. */
58e17b0b 2535int
2536pa_adjust_insn_length (insn, length)
2537 rtx insn;
2538 int length;
2539{
2540 rtx pat = PATTERN (insn);
2541
5fbd5940 2542 /* Call insns which are *not* indirect and have unfilled delay slots. */
58e17b0b 2543 if (GET_CODE (insn) == CALL_INSN)
5fbd5940 2544 {
2545
2546 if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL
2547 && GET_CODE (XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0)) == SYMBOL_REF)
5a1231ef 2548 return 4;
5fbd5940 2549 else if (GET_CODE (XVECEXP (pat, 0, 0)) == SET
2550 && GET_CODE (XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0))
2551 == SYMBOL_REF)
5a1231ef 2552 return 4;
5fbd5940 2553 else
2554 return 0;
2555 }
58e17b0b 2556 /* Millicode insn with an unfilled delay slot. */
2557 else if (GET_CODE (insn) == INSN
2558 && GET_CODE (pat) != SEQUENCE
2559 && GET_CODE (pat) != USE
2560 && GET_CODE (pat) != CLOBBER
2561 && get_attr_type (insn) == TYPE_MILLI)
5a1231ef 2562 return 4;
58e17b0b 2563 /* Block move pattern. */
2564 else if (GET_CODE (insn) == INSN
2565 && GET_CODE (pat) == PARALLEL
2566 && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 0)) == MEM
2567 && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 1)) == MEM
2568 && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode
2569 && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 1)) == BLKmode)
5a1231ef 2570 return compute_movstrsi_length (insn) - 4;
58e17b0b 2571 /* Conditional branch with an unfilled delay slot. */
5fbd5940 2572 else if (GET_CODE (insn) == JUMP_INSN && ! simplejump_p (insn))
2573 {
2574 /* Adjust a short backwards conditional with an unfilled delay slot. */
2575 if (GET_CODE (pat) == SET
5a1231ef 2576 && length == 4
5fbd5940 2577 && ! forward_branch_p (insn))
5a1231ef 2578 return 4;
5fbd5940 2579 /* Adjust dbra insn with short backwards conditional branch with
6d36483b 2580 unfilled delay slot -- only for case where counter is in a
29a4502c 2581 general register register. */
5fbd5940 2582 else if (GET_CODE (pat) == PARALLEL
2583 && GET_CODE (XVECEXP (pat, 0, 1)) == SET
2584 && GET_CODE (XEXP (XVECEXP (pat, 0, 1), 0)) == REG
6d36483b 2585 && ! FP_REG_P (XEXP (XVECEXP (pat, 0, 1), 0))
5a1231ef 2586 && length == 4
5fbd5940 2587 && ! forward_branch_p (insn))
5a1231ef 2588 return 4;
5fbd5940 2589 else
2590 return 0;
2591 }
58e17b0b 2592 else
2593 return 0;
2594}
2595
87ad11b0 2596/* Print operand X (an rtx) in assembler syntax to file FILE.
2597 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2598 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2599
2600void
2601print_operand (file, x, code)
2602 FILE *file;
2603 rtx x;
2604 int code;
2605{
2606 switch (code)
2607 {
2608 case '#':
2609 /* Output a 'nop' if there's nothing for the delay slot. */
2610 if (dbr_sequence_length () == 0)
2611 fputs ("\n\tnop", file);
2612 return;
2613 case '*':
2614 /* Output an nullification completer if there's nothing for the */
6d36483b 2615 /* delay slot or nullification is requested. */
87ad11b0 2616 if (dbr_sequence_length () == 0 ||
2617 (final_sequence &&
2618 INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))))
2619 fputs (",n", file);
2620 return;
2621 case 'R':
2622 /* Print out the second register name of a register pair.
2623 I.e., R (6) => 7. */
2624 fputs (reg_names[REGNO (x)+1], file);
2625 return;
2626 case 'r':
2627 /* A register or zero. */
891b55b4 2628 if (x == const0_rtx
2629 || (x == CONST0_RTX (DFmode))
2630 || (x == CONST0_RTX (SFmode)))
87ad11b0 2631 {
2632 fputs ("0", file);
2633 return;
2634 }
2635 else
2636 break;
c8975385 2637 case 'C': /* Plain (C)ondition */
87ad11b0 2638 case 'X':
2639 switch (GET_CODE (x))
6d36483b 2640 {
87ad11b0 2641 case EQ:
2642 fprintf (file, "="); break;
2643 case NE:
9d887bf4 2644 fprintf (file, "<>"); break;
87ad11b0 2645 case GT:
2646 fprintf (file, ">"); break;
2647 case GE:
2648 fprintf (file, ">="); break;
2649 case GEU:
2650 fprintf (file, ">>="); break;
2651 case GTU:
2652 fprintf (file, ">>"); break;
2653 case LT:
2654 fprintf (file, "<"); break;
2655 case LE:
2656 fprintf (file, "<="); break;
2657 case LEU:
2658 fprintf (file, "<<="); break;
2659 case LTU:
2660 fprintf (file, "<<"); break;
2661 default:
87ad11b0 2662 abort ();
2663 }
2664 return;
c8975385 2665 case 'N': /* Condition, (N)egated */
87ad11b0 2666 switch (GET_CODE (x))
2667 {
2668 case EQ:
9d887bf4 2669 fprintf (file, "<>"); break;
87ad11b0 2670 case NE:
2671 fprintf (file, "="); break;
2672 case GT:
2673 fprintf (file, "<="); break;
2674 case GE:
2675 fprintf (file, "<"); break;
2676 case GEU:
2677 fprintf (file, "<<"); break;
2678 case GTU:
2679 fprintf (file, "<<="); break;
2680 case LT:
2681 fprintf (file, ">="); break;
2682 case LE:
2683 fprintf (file, ">"); break;
2684 case LEU:
2685 fprintf (file, ">>"); break;
2686 case LTU:
2687 fprintf (file, ">>="); break;
2688 default:
87ad11b0 2689 abort ();
2690 }
2691 return;
61230bc9 2692 /* For floating point comparisons. Need special conditions to deal
2693 with NaNs properly. */
2694 case 'Y':
2695 switch (GET_CODE (x))
2696 {
2697 case EQ:
2698 fprintf (file, "!="); break;
2699 case NE:
2700 fprintf (file, "="); break;
2701 case GT:
2702 fprintf (file, "!>"); break;
2703 case GE:
2704 fprintf (file, "!>="); break;
2705 case LT:
2706 fprintf (file, "!<"); break;
2707 case LE:
2708 fprintf (file, "!<="); break;
2709 default:
61230bc9 2710 abort ();
2711 }
2712 return;
c8975385 2713 case 'S': /* Condition, operands are (S)wapped. */
2714 switch (GET_CODE (x))
2715 {
2716 case EQ:
2717 fprintf (file, "="); break;
2718 case NE:
2719 fprintf (file, "<>"); break;
2720 case GT:
2721 fprintf (file, "<"); break;
2722 case GE:
2723 fprintf (file, "<="); break;
2724 case GEU:
2725 fprintf (file, "<<="); break;
2726 case GTU:
2727 fprintf (file, "<<"); break;
2728 case LT:
2729 fprintf (file, ">"); break;
2730 case LE:
2731 fprintf (file, ">="); break;
2732 case LEU:
2733 fprintf (file, ">>="); break;
2734 case LTU:
2735 fprintf (file, ">>"); break;
2736 default:
c8975385 2737 abort ();
6d36483b 2738 }
c8975385 2739 return;
2740 case 'B': /* Condition, (B)oth swapped and negate. */
2741 switch (GET_CODE (x))
2742 {
2743 case EQ:
2744 fprintf (file, "<>"); break;
2745 case NE:
2746 fprintf (file, "="); break;
2747 case GT:
2748 fprintf (file, ">="); break;
2749 case GE:
2750 fprintf (file, ">"); break;
2751 case GEU:
2752 fprintf (file, ">>"); break;
2753 case GTU:
2754 fprintf (file, ">>="); break;
2755 case LT:
2756 fprintf (file, "<="); break;
2757 case LE:
2758 fprintf (file, "<"); break;
2759 case LEU:
2760 fprintf (file, "<<"); break;
2761 case LTU:
2762 fprintf (file, "<<="); break;
2763 default:
c8975385 2764 abort ();
6d36483b 2765 }
c8975385 2766 return;
2767 case 'k':
2768 if (GET_CODE (x) == CONST_INT)
2769 {
2770 fprintf (file, "%d", ~INTVAL (x));
2771 return;
2772 }
2773 abort();
e5965947 2774 case 'L':
2775 if (GET_CODE (x) == CONST_INT)
2776 {
2777 fprintf (file, "%d", 32 - (INTVAL (x) & 31));
2778 return;
2779 }
2780 abort();
3a16146d 2781 case 'O':
2782 if (GET_CODE (x) == CONST_INT && exact_log2 (INTVAL (x)) >= 0)
2783 {
2784 fprintf (file, "%d", exact_log2 (INTVAL (x)));
2785 return;
2786 }
2787 abort();
e5965947 2788 case 'P':
2789 if (GET_CODE (x) == CONST_INT)
2790 {
2791 fprintf (file, "%d", 31 - (INTVAL (x) & 31));
2792 return;
2793 }
2794 abort();
c8975385 2795 case 'I':
2796 if (GET_CODE (x) == CONST_INT)
2797 fputs ("i", file);
2798 return;
87ad11b0 2799 case 'M':
2800 switch (GET_CODE (XEXP (x, 0)))
2801 {
2802 case PRE_DEC:
2803 case PRE_INC:
2804 fprintf (file, "s,mb");
2805 break;
2806 case POST_DEC:
2807 case POST_INC:
2808 fprintf (file, "s,ma");
2809 break;
2810 default:
2811 break;
2812 }
2813 return;
2814 case 'F':
2815 switch (GET_CODE (XEXP (x, 0)))
2816 {
2817 case PRE_DEC:
2818 case PRE_INC:
2819 fprintf (file, ",mb");
2820 break;
2821 case POST_DEC:
2822 case POST_INC:
2823 fprintf (file, ",ma");
2824 break;
2825 default:
2826 break;
2827 }
2828 return;
2829 case 'G':
2830 output_global_address (file, x);
2831 return;
2832 case 0: /* Don't do anything special */
2833 break;
42faba01 2834 case 'Z':
2835 {
2836 unsigned op[3];
2837 compute_zdepi_operands (INTVAL (x), op);
2838 fprintf (file, "%d,%d,%d", op[0], op[1], op[2]);
2839 return;
2840 }
87ad11b0 2841 default:
2842 abort ();
2843 }
2844 if (GET_CODE (x) == REG)
df0651dc 2845 {
2846 if (FP_REG_P (x) && GET_MODE_SIZE (GET_MODE (x)) <= 4 && (REGNO (x) & 1) == 0)
2847 fprintf (file, "%sL", reg_names [REGNO (x)]);
2848 else
2849 fprintf (file, "%s", reg_names [REGNO (x)]);
2850 }
87ad11b0 2851 else if (GET_CODE (x) == MEM)
2852 {
2853 int size = GET_MODE_SIZE (GET_MODE (x));
2854 rtx base = XEXP (XEXP (x, 0), 0);
2855 switch (GET_CODE (XEXP (x, 0)))
2856 {
2857 case PRE_DEC:
2858 case POST_DEC:
2859 fprintf (file, "-%d(0,%s)", size, reg_names [REGNO (base)]);
2860 break;
2861 case PRE_INC:
2862 case POST_INC:
2863 fprintf (file, "%d(0,%s)", size, reg_names [REGNO (base)]);
2864 break;
2865 default:
2866 output_address (XEXP (x, 0));
2867 break;
2868 }
2869 }
2870 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
2871 {
2872 union { double d; int i[2]; } u;
2873 union { float f; int i; } u1;
2874 u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1);
2875 u1.f = u.d;
2876 if (code == 'f')
2877 fprintf (file, "0r%.9g", u1.f);
2878 else
2879 fprintf (file, "0x%x", u1.i);
2880 }
6c640a06 2881 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
87ad11b0 2882 {
2883 union { double d; int i[2]; } u;
2884 u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1);
2885 fprintf (file, "0r%.20g", u.d);
2886 }
2887 else
2888 output_addr_const (file, x);
2889}
2890
2891/* output a SYMBOL_REF or a CONST expression involving a SYMBOL_REF. */
2892
2893void
2894output_global_address (file, x)
2895 FILE *file;
2896 rtx x;
2897{
2ee034bc 2898
2899 /* Imagine (high (const (plus ...))). */
2900 if (GET_CODE (x) == HIGH)
2901 x = XEXP (x, 0);
2902
87ad11b0 2903 if (GET_CODE (x) == SYMBOL_REF && read_only_operand (x))
2904 assemble_name (file, XSTR (x, 0));
2905 else if (GET_CODE (x) == SYMBOL_REF)
2906 {
2907 assemble_name (file, XSTR (x, 0));
2908 fprintf (file, "-$global$");
2909 }
2910 else if (GET_CODE (x) == CONST)
2911 {
2912 char *sep = "";
2913 int offset = 0; /* assembler wants -$global$ at end */
2914 rtx base;
6d36483b 2915
87ad11b0 2916 if (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
2917 {
2918 base = XEXP (XEXP (x, 0), 0);
2919 output_addr_const (file, base);
2920 }
2921 else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == CONST_INT)
2922 offset = INTVAL (XEXP (XEXP (x, 0), 0));
2923 else abort ();
2924
2925 if (GET_CODE (XEXP (XEXP (x, 0), 1)) == SYMBOL_REF)
2926 {
2927 base = XEXP (XEXP (x, 0), 1);
2928 output_addr_const (file, base);
2929 }
2930 else if (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2931 offset = INTVAL (XEXP (XEXP (x, 0),1));
2932 else abort ();
2933
2934 if (GET_CODE (XEXP (x, 0)) == PLUS)
2935 {
2936 if (offset < 0)
2937 {
2938 offset = -offset;
2939 sep = "-";
2940 }
2941 else
2942 sep = "+";
2943 }
2944 else if (GET_CODE (XEXP (x, 0)) == MINUS
2945 && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))
2946 sep = "-";
2947 else abort ();
2948
2949 if (!read_only_operand (base))
2950 fprintf (file, "-$global$");
2951 fprintf (file, "%s", sep);
2952 if (offset) fprintf (file,"%d", offset);
2953 }
2954 else
2955 output_addr_const (file, x);
2956}
2957
87ad11b0 2958/* HP's millicode routines mean something special to the assembler.
2959 Keep track of which ones we have used. */
2960
2961enum millicodes { remI, remU, divI, divU, mulI, mulU, end1000 };
2962static char imported[(int)end1000];
2963static char *milli_names[] = {"remI", "remU", "divI", "divU", "mulI", "mulU"};
2964static char import_string[] = ".IMPORT $$....,MILLICODE";
2965#define MILLI_START 10
2966
57ed30e5 2967static void
87ad11b0 2968import_milli (code)
2969 enum millicodes code;
2970{
2971 char str[sizeof (import_string)];
6d36483b 2972
87ad11b0 2973 if (!imported[(int)code])
2974 {
2975 imported[(int)code] = 1;
2976 strcpy (str, import_string);
2977 strncpy (str + MILLI_START, milli_names[(int)code], 4);
2978 output_asm_insn (str, 0);
2979 }
2980}
2981
6d36483b 2982/* The register constraints have put the operands and return value in
87ad11b0 2983 the proper registers. */
2984
2985char *
d6686e21 2986output_mul_insn (unsignedp, insn)
87ad11b0 2987 int unsignedp;
d6686e21 2988 rtx insn;
87ad11b0 2989{
d6686e21 2990
87ad11b0 2991 if (unsignedp)
2992 {
2993 import_milli (mulU);
d6686e21 2994 return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$mulU"),
2995 gen_rtx (REG, SImode, 31));
87ad11b0 2996 }
2997 else
2998 {
2999 import_milli (mulI);
d6686e21 3000 return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$mulI"),
3001 gen_rtx (REG, SImode, 31));
87ad11b0 3002 }
3003}
3004
3005/* If operands isn't NULL, then it's a CONST_INT with which we can do
3006 something */
3007
3008
3009/* Emit the rtl for doing a division by a constant. */
3010
3011 /* Do magic division millicodes exist for this value? */
3012
3013static int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
3014 1, 1};
3015
6d36483b 3016/* We'll use an array to keep track of the magic millicodes and
87ad11b0 3017 whether or not we've used them already. [n][0] is signed, [n][1] is
3018 unsigned. */
3019
87ad11b0 3020static int div_milli[16][2];
3021
3022int
3023div_operand (op, mode)
3024 rtx op;
3025 enum machine_mode mode;
3026{
3027 return (mode == SImode
3028 && ((GET_CODE (op) == REG && REGNO (op) == 25)
3029 || (GET_CODE (op) == CONST_INT && INTVAL (op) > 0
3030 && INTVAL (op) < 16 && magic_milli[INTVAL (op)])));
3031}
3032
3033int
3034emit_hpdiv_const (operands, unsignedp)
3035 rtx *operands;
3036 int unsignedp;
3037{
3038 if (GET_CODE (operands[2]) == CONST_INT
3039 && INTVAL (operands[2]) > 0
3040 && INTVAL (operands[2]) < 16
3041 && magic_milli[INTVAL (operands[2])])
3042 {
3043 emit_move_insn ( gen_rtx (REG, SImode, 26), operands[1]);
3044 emit
3045 (gen_rtx
3046 (PARALLEL, VOIDmode,
3047 gen_rtvec (5, gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 29),
3048 gen_rtx (unsignedp ? UDIV : DIV, SImode,
3049 gen_rtx (REG, SImode, 26),
3050 operands[2])),
33bd7237 3051 gen_rtx (CLOBBER, VOIDmode, operands[3]),
87ad11b0 3052 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 26)),
3053 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 25)),
3054 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 31)))));
3055 emit_move_insn (operands[0], gen_rtx (REG, SImode, 29));
3056 return 1;
3057 }
3058 return 0;
3059}
3060
3061char *
d6686e21 3062output_div_insn (operands, unsignedp, insn)
87ad11b0 3063 rtx *operands;
3064 int unsignedp;
d6686e21 3065 rtx insn;
87ad11b0 3066{
3067 int divisor;
6d36483b 3068
3069 /* If the divisor is a constant, try to use one of the special
87ad11b0 3070 opcodes .*/
3071 if (GET_CODE (operands[0]) == CONST_INT)
3072 {
d6686e21 3073 static char buf[100];
87ad11b0 3074 divisor = INTVAL (operands[0]);
3075 if (!div_milli[divisor][unsignedp])
3076 {
d6686e21 3077 div_milli[divisor][unsignedp] = 1;
87ad11b0 3078 if (unsignedp)
3079 output_asm_insn (".IMPORT $$divU_%0,MILLICODE", operands);
3080 else
3081 output_asm_insn (".IMPORT $$divI_%0,MILLICODE", operands);
87ad11b0 3082 }
3083 if (unsignedp)
d6686e21 3084 {
3085 sprintf (buf, "$$divU_%d", INTVAL (operands[0]));
3086 return output_call (insn, gen_rtx (SYMBOL_REF, SImode, buf),
3087 gen_rtx (REG, SImode, 31));
3088 }
3089 else
3090 {
3091 sprintf (buf, "$$divI_%d", INTVAL (operands[0]));
3092 return output_call (insn, gen_rtx (SYMBOL_REF, SImode, buf),
3093 gen_rtx (REG, SImode, 31));
3094 }
87ad11b0 3095 }
3096 /* Divisor isn't a special constant. */
3097 else
3098 {
3099 if (unsignedp)
3100 {
3101 import_milli (divU);
d6686e21 3102 return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$divU"),
3103 gen_rtx (REG, SImode, 31));
87ad11b0 3104 }
3105 else
3106 {
3107 import_milli (divI);
d6686e21 3108 return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$divI"),
3109 gen_rtx (REG, SImode, 31));
87ad11b0 3110 }
3111 }
3112}
3113
3114/* Output a $$rem millicode to do mod. */
3115
3116char *
d6686e21 3117output_mod_insn (unsignedp, insn)
87ad11b0 3118 int unsignedp;
d6686e21 3119 rtx insn;
87ad11b0 3120{
3121 if (unsignedp)
3122 {
3123 import_milli (remU);
d6686e21 3124 return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$remU"),
3125 gen_rtx (REG, SImode, 31));
87ad11b0 3126 }
3127 else
3128 {
3129 import_milli (remI);
d6686e21 3130 return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$remI"),
3131 gen_rtx (REG, SImode, 31));
87ad11b0 3132 }
3133}
3134
3135void
df0651dc 3136output_arg_descriptor (call_insn)
3137 rtx call_insn;
87ad11b0 3138{
3139 char *arg_regs[4];
3140 enum machine_mode arg_mode;
df0651dc 3141 rtx link;
87ad11b0 3142 int i, output_flag = 0;
3143 int regno;
6d36483b 3144
87ad11b0 3145 for (i = 0; i < 4; i++)
3146 arg_regs[i] = 0;
3147
738176ab 3148 /* Specify explicitly that no argument relocations should take place
3149 if using the portable runtime calling conventions. */
3150 if (TARGET_PORTABLE_RUNTIME)
3151 {
3152 fprintf (asm_out_file,
3153 "\t.CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO,RETVAL=NO\n");
3154 return;
3155 }
3156
df0651dc 3157 if (GET_CODE (call_insn) != CALL_INSN)
3158 abort ();
3159 for (link = CALL_INSN_FUNCTION_USAGE (call_insn); link; link = XEXP (link, 1))
87ad11b0 3160 {
df0651dc 3161 rtx use = XEXP (link, 0);
c12afafd 3162
df0651dc 3163 if (! (GET_CODE (use) == USE
3164 && GET_CODE (XEXP (use, 0)) == REG
3165 && FUNCTION_ARG_REGNO_P (REGNO (XEXP (use, 0)))))
c12afafd 3166 continue;
3167
df0651dc 3168 arg_mode = GET_MODE (XEXP (use, 0));
3169 regno = REGNO (XEXP (use, 0));
87ad11b0 3170 if (regno >= 23 && regno <= 26)
372ef038 3171 {
3172 arg_regs[26 - regno] = "GR";
3173 if (arg_mode == DImode)
3174 arg_regs[25 - regno] = "GR";
3175 }
df0651dc 3176 else if (regno >= 32 && regno <= 39)
87ad11b0 3177 {
3178 if (arg_mode == SFmode)
df0651dc 3179 arg_regs[(regno - 32) / 2] = "FR";
e6ba640e 3180 else
87ad11b0 3181 {
eeec72c0 3182#ifndef HP_FP_ARG_DESCRIPTOR_REVERSED
df0651dc 3183 arg_regs[(regno - 34) / 2] = "FR";
3184 arg_regs[(regno - 34) / 2 + 1] = "FU";
87ad11b0 3185#else
df0651dc 3186 arg_regs[(regno - 34) / 2] = "FU";
3187 arg_regs[(regno - 34) / 2 + 1] = "FR";
87ad11b0 3188#endif
3189 }
87ad11b0 3190 }
3191 }
3192 fputs ("\t.CALL ", asm_out_file);
3193 for (i = 0; i < 4; i++)
3194 {
3195 if (arg_regs[i])
3196 {
3197 if (output_flag++)
3198 fputc (',', asm_out_file);
3199 fprintf (asm_out_file, "ARGW%d=%s", i, arg_regs[i]);
3200 }
3201 }
3202 fputc ('\n', asm_out_file);
3203}
3204\f
d2c1d63d 3205/* Memory loads/stores to/from the shift need to go through
3206 the general registers. */
87ad11b0 3207
3208enum reg_class
3209secondary_reload_class (class, mode, in)
3210 enum reg_class class;
3211 enum machine_mode mode;
3212 rtx in;
3213{
3214 int regno = true_regnum (in);
3215
d2498717 3216 if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
6d36483b 3217 && GET_MODE_CLASS (mode) == MODE_INT
3218 && FP_REG_CLASS_P (class))
d6f01525 3219 || (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
9c6d4825 3220 return GENERAL_REGS;
d2c1d63d 3221
2ee034bc 3222 if (GET_CODE (in) == HIGH)
3223 in = XEXP (in, 0);
3224
63882853 3225 if (class != R1_REGS && symbolic_operand (in, VOIDmode))
2ee034bc 3226 return R1_REGS;
3227
d2c1d63d 3228 return NO_REGS;
87ad11b0 3229}
3230
3231enum direction
3232function_arg_padding (mode, type)
3233 enum machine_mode mode;
3234 tree type;
3235{
3236 int size;
3237
3238 if (mode == BLKmode)
3239 {
3240 if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
3241 size = int_size_in_bytes (type) * BITS_PER_UNIT;
3242 else
3243 return upward; /* Don't know if this is right, but */
3244 /* same as old definition. */
3245 }
3246 else
3247 size = GET_MODE_BITSIZE (mode);
3248 if (size < PARM_BOUNDARY)
3249 return downward;
3250 else if (size % PARM_BOUNDARY)
3251 return upward;
3252 else
3253 return none;
3254}
3255
87ad11b0 3256\f
3257/* Do what is necessary for `va_start'. The argument is ignored;
3258 We look at the current function to determine if stdargs or varargs
3259 is used and fill in an initial va_list. A pointer to this constructor
3260 is returned. */
3261
3262struct rtx_def *
3263hppa_builtin_saveregs (arglist)
3264 tree arglist;
3265{
57ed30e5 3266 rtx offset;
87ad11b0 3267 tree fntype = TREE_TYPE (current_function_decl);
3268 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
3269 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
3270 != void_type_node)))
3271 ? UNITS_PER_WORD : 0);
3272
3273 if (argadj)
3274 offset = plus_constant (current_function_arg_offset_rtx, argadj);
3275 else
3276 offset = current_function_arg_offset_rtx;
9c6d4825 3277
87ad11b0 3278 /* Store general registers on the stack. */
3279 move_block_from_reg (23,
3280 gen_rtx (MEM, BLKmode,
3281 plus_constant
3282 (current_function_internal_arg_pointer, -16)),
6d36483b 3283 4, 4 * UNITS_PER_WORD);
9c6d4825 3284 return copy_to_reg (expand_binop (Pmode, add_optab,
3285 current_function_internal_arg_pointer,
3286 offset, 0, 0, OPTAB_LIB_WIDEN));
87ad11b0 3287}
d6f01525 3288
6d36483b 3289/* This routine handles all the normal conditional branch sequences we
3290 might need to generate. It handles compare immediate vs compare
3291 register, nullification of delay slots, varying length branches,
0d986529 3292 negated branches, and all combinations of the above. It returns the
6d36483b 3293 output appropriate to emit the branch corresponding to all given
0d986529 3294 parameters. */
3295
3296char *
3297output_cbranch (operands, nullify, length, negated, insn)
3298 rtx *operands;
3299 int nullify, length, negated;
3300 rtx insn;
29a4502c 3301{
0d986529 3302 static char buf[100];
3303 int useskip = 0;
3304
29a4502c 3305 /* A conditional branch to the following instruction (eg the delay slot) is
3306 asking for a disaster. This can happen when not optimizing.
3307
3308 In such cases it is safe to emit nothing. */
3309
3310 if (JUMP_LABEL (insn) == next_nonnote_insn (insn))
3311 return "";
6d36483b 3312
5fbd5940 3313 /* If this is a long branch with its delay slot unfilled, set `nullify'
3314 as it can nullify the delay slot and save a nop. */
5a1231ef 3315 if (length == 8 && dbr_sequence_length () == 0)
5fbd5940 3316 nullify = 1;
3317
3318 /* If this is a short forward conditional branch which did not get
3319 its delay slot filled, the delay slot can still be nullified. */
5a1231ef 3320 if (! nullify && length == 4 && dbr_sequence_length () == 0)
5fbd5940 3321 nullify = forward_branch_p (insn);
3322
6d36483b 3323 /* A forward branch over a single nullified insn can be done with a
0d986529 3324 comclr instruction. This avoids a single cycle penalty due to
3325 mis-predicted branch if we fall through (branch not taken). */
5a1231ef 3326 if (length == 4
5fbd5940 3327 && next_real_insn (insn) != 0
5a1231ef 3328 && get_attr_length (next_real_insn (insn)) == 4
5fbd5940 3329 && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
0d986529 3330 && nullify)
3331 useskip = 1;
3332
3333 switch (length)
3334 {
5fbd5940 3335 /* All short conditional branches except backwards with an unfilled
3336 delay slot. */
5a1231ef 3337 case 4:
0d986529 3338 if (useskip)
3339 strcpy (buf, "com%I2clr,");
3340 else
3341 strcpy (buf, "com%I2b,");
3342 if (negated)
3343 strcat (buf, "%B3");
3344 else
3345 strcat (buf, "%S3");
3346 if (useskip)
3347 strcat (buf, " %2,%1,0");
3348 else if (nullify)
3349 strcat (buf, ",n %2,%1,%0");
6d36483b 3350 else
5fbd5940 3351 strcat (buf, " %2,%1,%0");
0d986529 3352 break;
3353
6d36483b 3354 /* All long conditionals. Note an short backward branch with an
5fbd5940 3355 unfilled delay slot is treated just like a long backward branch
3356 with an unfilled delay slot. */
5a1231ef 3357 case 8:
5fbd5940 3358 /* Handle weird backwards branch with a filled delay slot
3359 with is nullified. */
3360 if (dbr_sequence_length () != 0
3361 && ! forward_branch_p (insn)
3362 && nullify)
3363 {
3364 strcpy (buf, "com%I2b,");
3365 if (negated)
3366 strcat (buf, "%S3");
3367 else
3368 strcat (buf, "%B3");
3369 strcat (buf, ",n %2,%1,.+12\n\tbl %0,0");
3370 }
0d986529 3371 else
5fbd5940 3372 {
3373 strcpy (buf, "com%I2clr,");
3374 if (negated)
3375 strcat (buf, "%S3");
3376 else
3377 strcat (buf, "%B3");
3378 if (nullify)
3379 strcat (buf, " %2,%1,0\n\tbl,n %0,0");
3380 else
3381 strcat (buf, " %2,%1,0\n\tbl %0,0");
3382 }
0d986529 3383 break;
3384
3385 default:
3386 abort();
5fbd5940 3387 }
0d986529 3388 return buf;
3389}
3390
6d36483b 3391/* This routine handles all the branch-on-bit conditional branch sequences we
0d986529 3392 might need to generate. It handles nullification of delay slots,
3393 varying length branches, negated branches and all combinations of the
3394 above. it returns the appropriate output template to emit the branch. */
3395
3396char *
3397output_bb (operands, nullify, length, negated, insn, which)
3398 rtx *operands;
3399 int nullify, length, negated;
3400 rtx insn;
3401 int which;
29a4502c 3402{
0d986529 3403 static char buf[100];
3404 int useskip = 0;
3405
29a4502c 3406 /* A conditional branch to the following instruction (eg the delay slot) is
3407 asking for a disaster. I do not think this can happen as this pattern
6d36483b 3408 is only used when optimizing; jump optimization should eliminate the
29a4502c 3409 jump. But be prepared just in case. */
6d36483b 3410
29a4502c 3411 if (JUMP_LABEL (insn) == next_nonnote_insn (insn))
3412 return "";
6d36483b 3413
5fbd5940 3414 /* If this is a long branch with its delay slot unfilled, set `nullify'
3415 as it can nullify the delay slot and save a nop. */
5a1231ef 3416 if (length == 8 && dbr_sequence_length () == 0)
5fbd5940 3417 nullify = 1;
3418
3419 /* If this is a short forward conditional branch which did not get
3420 its delay slot filled, the delay slot can still be nullified. */
5a1231ef 3421 if (! nullify && length == 4 && dbr_sequence_length () == 0)
5fbd5940 3422 nullify = forward_branch_p (insn);
3423
6d36483b 3424 /* A forward branch over a single nullified insn can be done with a
0d986529 3425 extrs instruction. This avoids a single cycle penalty due to
3426 mis-predicted branch if we fall through (branch not taken). */
3427
5a1231ef 3428 if (length == 4
5fbd5940 3429 && next_real_insn (insn) != 0
5a1231ef 3430 && get_attr_length (next_real_insn (insn)) == 4
5fbd5940 3431 && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
0d986529 3432 && nullify)
3433 useskip = 1;
3434
3435 switch (length)
3436 {
3437
5fbd5940 3438 /* All short conditional branches except backwards with an unfilled
3439 delay slot. */
5a1231ef 3440 case 4:
0d986529 3441 if (useskip)
3442 strcpy (buf, "extrs,");
6d36483b 3443 else
0d986529 3444 strcpy (buf, "bb,");
3445 if ((which == 0 && negated)
3446 || (which == 1 && ! negated))
3447 strcat (buf, ">=");
3448 else
3449 strcat (buf, "<");
3450 if (useskip)
3451 strcat (buf, " %0,%1,1,0");
3452 else if (nullify && negated)
3453 strcat (buf, ",n %0,%1,%3");
3454 else if (nullify && ! negated)
3455 strcat (buf, ",n %0,%1,%2");
3456 else if (! nullify && negated)
5fbd5940 3457 strcat (buf, "%0,%1,%3");
0d986529 3458 else if (! nullify && ! negated)
5fbd5940 3459 strcat (buf, " %0,%1,%2");
0d986529 3460 break;
3461
6d36483b 3462 /* All long conditionals. Note an short backward branch with an
5fbd5940 3463 unfilled delay slot is treated just like a long backward branch
3464 with an unfilled delay slot. */
5a1231ef 3465 case 8:
5fbd5940 3466 /* Handle weird backwards branch with a filled delay slot
3467 with is nullified. */
3468 if (dbr_sequence_length () != 0
3469 && ! forward_branch_p (insn)
3470 && nullify)
3471 {
3472 strcpy (buf, "bb,");
3473 if ((which == 0 && negated)
3474 || (which == 1 && ! negated))
3475 strcat (buf, "<");
3476 else
3477 strcat (buf, ">=");
3478 if (negated)
3479 strcat (buf, " %0,%1,.+12\n\tbl %3,0");
3480 else
3481 strcat (buf, " %0,%1,.+12\n\tbl %2,0");
3482 }
0d986529 3483 else
5fbd5940 3484 {
3485 strcpy (buf, "extrs,");
3486 if ((which == 0 && negated)
3487 || (which == 1 && ! negated))
3488 strcat (buf, "<");
3489 else
3490 strcat (buf, ">=");
3491 if (nullify && negated)
3492 strcat (buf, " %0,%1,1,0\n\tbl,n %3,0");
3493 else if (nullify && ! negated)
3494 strcat (buf, " %0,%1,1,0\n\tbl,n %2,0");
3495 else if (negated)
3496 strcat (buf, " %0,%1,1,0\n\tbl %3,0");
6d36483b 3497 else
5fbd5940 3498 strcat (buf, " %0,%1,1,0\n\tbl %2,0");
3499 }
0d986529 3500 break;
3501
3502 default:
3503 abort();
5fbd5940 3504 }
0d986529 3505 return buf;
3506}
3507
29a4502c 3508/* Return the output template for emitting a dbra type insn.
3509
3510 Note it may perform some output operations on its own before
3511 returning the final output string. */
3512char *
3513output_dbra (operands, insn, which_alternative)
3514 rtx *operands;
3515 rtx insn;
3516 int which_alternative;
3517{
3518
3519 /* A conditional branch to the following instruction (eg the delay slot) is
3520 asking for a disaster. Be prepared! */
3521
3522 if (JUMP_LABEL (insn) == next_nonnote_insn (insn))
3523 {
3524 if (which_alternative == 0)
3525 return "ldo %1(%0),%0";
3526 else if (which_alternative == 1)
3527 {
3528 output_asm_insn ("fstws %0,-16(0,%%r30)",operands);
3529 output_asm_insn ("ldw -16(0,%%r30),%4",operands);
3530 output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(0,%%r30)", operands);
3531 return "fldws -16(0,%%r30),%0";
3532 }
3533 else
3534 {
3535 output_asm_insn ("ldw %0,%4", operands);
3536 return "ldo %1(%4),%4\n\tstw %4,%0";
3537 }
3538 }
3539
3540 if (which_alternative == 0)
3541 {
3542 int nullify = INSN_ANNULLED_BRANCH_P (insn);
3543 int length = get_attr_length (insn);
3544
3545 /* If this is a long branch with its delay slot unfilled, set `nullify'
3546 as it can nullify the delay slot and save a nop. */
5a1231ef 3547 if (length == 8 && dbr_sequence_length () == 0)
29a4502c 3548 nullify = 1;
3549
3550 /* If this is a short forward conditional branch which did not get
3551 its delay slot filled, the delay slot can still be nullified. */
5a1231ef 3552 if (! nullify && length == 4 && dbr_sequence_length () == 0)
29a4502c 3553 nullify = forward_branch_p (insn);
3554
3555 /* Handle short versions first. */
5a1231ef 3556 if (length == 4 && nullify)
29a4502c 3557 return "addib,%C2,n %1,%0,%3";
5a1231ef 3558 else if (length == 4 && ! nullify)
29a4502c 3559 return "addib,%C2 %1,%0,%3";
5a1231ef 3560 else if (length == 8)
29a4502c 3561 {
6d36483b 3562 /* Handle weird backwards branch with a fulled delay slot
29a4502c 3563 which is nullified. */
3564 if (dbr_sequence_length () != 0
3565 && ! forward_branch_p (insn)
3566 && nullify)
3567 return "addib,%N2,n %1,%0,.+12\n\tbl %3,0";
6d36483b 3568
3569 /* Handle normal cases. */
29a4502c 3570 if (nullify)
3571 return "addi,%N2 %1,%0,%0\n\tbl,n %3,0";
3572 else
3573 return "addi,%N2 %1,%0,%0\n\tbl %3,0";
3574 }
3575 else
3576 abort();
3577 }
3578 /* Deal with gross reload from FP register case. */
3579 else if (which_alternative == 1)
3580 {
3581 /* Move loop counter from FP register to MEM then into a GR,
3582 increment the GR, store the GR into MEM, and finally reload
6d36483b 3583 the FP register from MEM from within the branch's delay slot. */
29a4502c 3584 output_asm_insn ("fstws %0,-16(0,%%r30)\n\tldw -16(0,%%r30),%4",operands);
3585 output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(0,%%r30)", operands);
5a1231ef 3586 if (get_attr_length (insn) == 24)
29a4502c 3587 return "comb,%S2 0,%4,%3\n\tfldws -16(0,%%r30),%0";
3588 else
3589 return "comclr,%B2 0,%4,0\n\tbl %3,0\n\tfldws -16(0,%%r30),%0";
3590 }
3591 /* Deal with gross reload from memory case. */
3592 else
3593 {
3594 /* Reload loop counter from memory, the store back to memory
3595 happens in the branch's delay slot. */
3596 output_asm_insn ("ldw %0,%4", operands);
5a1231ef 3597 if (get_attr_length (insn) == 12)
29a4502c 3598 return "addib,%C2 %1,%4,%3\n\tstw %4,%0";
3599 else
b42d4c50 3600 return "addi,%N2 %1,%4,%4\n\tbl %3,0\n\tstw %4,%0";
29a4502c 3601 }
3602}
3603
3604/* Return the output template for emitting a dbra type insn.
3605
3606 Note it may perform some output operations on its own before
3607 returning the final output string. */
3608char *
3609output_movb (operands, insn, which_alternative, reverse_comparison)
3610 rtx *operands;
3611 rtx insn;
3612 int which_alternative;
3613 int reverse_comparison;
3614{
3615
3616 /* A conditional branch to the following instruction (eg the delay slot) is
3617 asking for a disaster. Be prepared! */
3618
3619 if (JUMP_LABEL (insn) == next_nonnote_insn (insn))
3620 {
3621 if (which_alternative == 0)
3622 return "copy %1,%0";
3623 else if (which_alternative == 1)
3624 {
b4437664 3625 output_asm_insn ("stw %1,-16(0,%%r30)",operands);
29a4502c 3626 return "fldws -16(0,%%r30),%0";
3627 }
3628 else
3629 return "stw %1,%0";
3630 }
3631
3632 /* Support the second variant. */
3633 if (reverse_comparison)
3634 PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2])));
3635
3636 if (which_alternative == 0)
3637 {
3638 int nullify = INSN_ANNULLED_BRANCH_P (insn);
3639 int length = get_attr_length (insn);
3640
3641 /* If this is a long branch with its delay slot unfilled, set `nullify'
3642 as it can nullify the delay slot and save a nop. */
5a1231ef 3643 if (length == 8 && dbr_sequence_length () == 0)
29a4502c 3644 nullify = 1;
3645
3646 /* If this is a short forward conditional branch which did not get
3647 its delay slot filled, the delay slot can still be nullified. */
5a1231ef 3648 if (! nullify && length == 4 && dbr_sequence_length () == 0)
29a4502c 3649 nullify = forward_branch_p (insn);
3650
3651 /* Handle short versions first. */
5a1231ef 3652 if (length == 4 && nullify)
29a4502c 3653 return "movb,%C2,n %1,%0,%3";
5a1231ef 3654 else if (length == 4 && ! nullify)
29a4502c 3655 return "movb,%C2 %1,%0,%3";
5a1231ef 3656 else if (length == 8)
29a4502c 3657 {
6d36483b 3658 /* Handle weird backwards branch with a filled delay slot
29a4502c 3659 which is nullified. */
3660 if (dbr_sequence_length () != 0
3661 && ! forward_branch_p (insn)
3662 && nullify)
3663 return "movb,%N2,n %1,%0,.+12\n\ttbl %3,0";
6d36483b 3664
3665 /* Handle normal cases. */
29a4502c 3666 if (nullify)
3667 return "or,%N2 %1,%%r0,%0\n\tbl,n %3,0";
3668 else
3669 return "or,%N2 %1,%%r0,%0\n\tbl %3,0";
3670 }
3671 else
3672 abort();
3673 }
3674 /* Deal with gross reload from FP register case. */
3675 else if (which_alternative == 1)
3676 {
3677 /* Move loop counter from FP register to MEM then into a GR,
3678 increment the GR, store the GR into MEM, and finally reload
6d36483b 3679 the FP register from MEM from within the branch's delay slot. */
b4437664 3680 output_asm_insn ("stw %1,-16(0,%%r30)",operands);
5a1231ef 3681 if (get_attr_length (insn) == 12)
29a4502c 3682 return "comb,%S2 0,%1,%3\n\tfldws -16(0,%%r30),%0";
3683 else
3684 return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tfldws -16(0,%%r30),%0";
3685 }
3686 /* Deal with gross reload from memory case. */
3687 else
3688 {
3689 /* Reload loop counter from memory, the store back to memory
3690 happens in the branch's delay slot. */
5a1231ef 3691 if (get_attr_length (insn) == 8)
29a4502c 3692 return "comb,%S2 0,%1,%3\n\tstw %1,%0";
3693 else
3694 return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tstw %1,%0";
3695 }
3696}
3697
3698
d6686e21 3699/* INSN is either a function call or a millicode call. It may have an
6d36483b 3700 unconditional jump in its delay slot.
d6686e21 3701
3702 CALL_DEST is the routine we are calling.
3703
3704 RETURN_POINTER is the register which will hold the return address.
3683f840 3705 %r2 for most calls, %r31 for millicode calls.
3706
3707 When TARGET_LONG_CALLS is true, output_call is only called for
3708 millicode calls. In addition, no delay slots are available when
3709 TARGET_LONG_CALLS is true. */
3710
d6686e21 3711char *
3712output_call (insn, call_dest, return_pointer)
3713 rtx insn;
3714 rtx call_dest;
3715 rtx return_pointer;
3716
3717{
3718 int distance;
3719 rtx xoperands[4];
3720 rtx seq_insn;
3721
3722 /* Handle common case -- empty delay slot or no jump in the delay slot. */
3723 if (dbr_sequence_length () == 0
6d36483b 3724 || (dbr_sequence_length () != 0
d6686e21 3725 && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN))
3726 {
3727 xoperands[0] = call_dest;
3728 xoperands[1] = return_pointer;
3683f840 3729 if (TARGET_LONG_CALLS)
3730 {
3731 output_asm_insn ("ldil L%%%0,%%r29", xoperands);
3732 output_asm_insn ("ldo R%%%0(%%r29),%%r29", xoperands);
3733 output_asm_insn ("blr 0,%r1\n\tbv,n 0(%%r29)\n\tnop", xoperands);
3734 }
3735 else
3736 output_asm_insn ("bl %0,%r1%#", xoperands);
d6686e21 3737 return "";
3738 }
6d36483b 3739
d6686e21 3740 /* This call has an unconditional jump in its delay slot. */
3741
3742 /* Use the containing sequence insn's address. */
3743 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
3744
6d36483b 3745 distance = insn_addresses[INSN_UID (JUMP_LABEL (NEXT_INSN (insn)))]
d6686e21 3746 - insn_addresses[INSN_UID (seq_insn)] - 8;
3747
3748 /* If the branch was too far away, emit a normal call followed
3749 by a nop, followed by the unconditional branch.
3750
6d36483b 3751 If the branch is close, then adjust %r2 from within the
d6686e21 3752 call's delay slot. */
3753
3754 xoperands[0] = call_dest;
3755 xoperands[1] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
3756 xoperands[2] = return_pointer;
3757 if (! VAL_14_BITS_P (distance))
3758 output_asm_insn ("bl %0,%r2\n\tnop\n\tbl,n %1,%%r0", xoperands);
3759 else
3760 {
3761 xoperands[3] = gen_label_rtx ();
2a033928 3762 output_asm_insn ("\n\tbl %0,%r2\n\tldo %1-%3(%r2),%r2", xoperands);
6d36483b 3763 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
0410a74e 3764 CODE_LABEL_NUMBER (xoperands[3]));
d6686e21 3765 }
3766
3767 /* Delete the jump. */
3768 PUT_CODE (NEXT_INSN (insn), NOTE);
3769 NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
3770 NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
3771 return "";
3772}
3773
d6f01525 3774extern struct obstack *saveable_obstack;
3775
3776/* In HPUX 8.0's shared library scheme, special relocations are needed
6d36483b 3777 for function labels if they might be passed to a function
d6f01525 3778 in a shared library (because shared libraries don't live in code
3779 space), and special magic is needed to construct their address. */
3780
3781void
3782hppa_encode_label (sym)
3783 rtx sym;
3784{
3785 char *str = XSTR (sym, 0);
3786 int len = strlen (str);
3787 char *newstr = obstack_alloc (saveable_obstack, len + 2) ;
3788
c1b3411e 3789 if (str[0] == '*')
3790 *newstr++ = *str++;
d6f01525 3791 strcpy (newstr + 1, str);
c1b3411e 3792 *newstr = '@';
d6f01525 3793 XSTR (sym,0) = newstr;
3794}
6d36483b 3795
d6f01525 3796int
3797function_label_operand (op, mode)
3798 rtx op;
3799 enum machine_mode mode;
3800{
c1b3411e 3801 return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0));
d6f01525 3802}
f33e3942 3803
37580c80 3804/* Returns 1 if the 6 operands specified in OPERANDS are suitable for
3805 use in fmpyadd instructions. */
4ed6ee50 3806int
df0651dc 3807fmpyaddoperands (operands)
4ed6ee50 3808 rtx *operands;
3809{
201f01e9 3810 enum machine_mode mode = GET_MODE (operands[0]);
4ed6ee50 3811
3812 /* All modes must be the same. */
201f01e9 3813 if (! (mode == GET_MODE (operands[1])
3814 && mode == GET_MODE (operands[2])
3815 && mode == GET_MODE (operands[3])
3816 && mode == GET_MODE (operands[4])
3817 && mode == GET_MODE (operands[5])))
4ed6ee50 3818 return 0;
3819
3820 /* Both DFmode and SFmode should work. But using SFmode makes the
3821 assembler complain. Just turn it off for now. */
201f01e9 3822 if (mode != DFmode)
4ed6ee50 3823 return 0;
3824
37580c80 3825 /* Only 2 real operands to the addition. One of the input operands must
3826 be the same as the output operand. */
4ed6ee50 3827 if (! rtx_equal_p (operands[3], operands[4])
3828 && ! rtx_equal_p (operands[3], operands[5]))
3829 return 0;
3830
3831 /* Inout operand of add can not conflict with any operands from multiply. */
3832 if (rtx_equal_p (operands[3], operands[0])
3833 || rtx_equal_p (operands[3], operands[1])
3834 || rtx_equal_p (operands[3], operands[2]))
3835 return 0;
3836
3837 /* multiply can not feed into addition operands. */
3838 if (rtx_equal_p (operands[4], operands[0])
3839 || rtx_equal_p (operands[5], operands[0]))
3840 return 0;
3841
4ed6ee50 3842 /* Passed. Operands are suitable for fmpyadd. */
3843 return 1;
3844}
3845
37580c80 3846/* Returns 1 if the 6 operands specified in OPERANDS are suitable for
3847 use in fmpysub instructions. */
4ed6ee50 3848int
df0651dc 3849fmpysuboperands (operands)
4ed6ee50 3850 rtx *operands;
3851{
201f01e9 3852 enum machine_mode mode = GET_MODE (operands[0]);
4ed6ee50 3853
3854 /* All modes must be the same. */
201f01e9 3855 if (! (mode == GET_MODE (operands[1])
3856 && mode == GET_MODE (operands[2])
3857 && mode == GET_MODE (operands[3])
3858 && mode == GET_MODE (operands[4])
3859 && mode == GET_MODE (operands[5])))
4ed6ee50 3860 return 0;
3861
3862 /* Both DFmode and SFmode should work. But using SFmode makes the
3863 assembler complain. Just turn it off for now. */
201f01e9 3864 if (mode != DFmode)
4ed6ee50 3865 return 0;
3866
37580c80 3867 /* Only 2 real operands to the subtraction. Subtraction is not a commutative
3868 operation, so operands[4] must be the same as operand[3]. */
4ed6ee50 3869 if (! rtx_equal_p (operands[3], operands[4]))
3870 return 0;
3871
3872 /* multiply can not feed into subtraction. */
37580c80 3873 if (rtx_equal_p (operands[5], operands[0]))
4ed6ee50 3874 return 0;
3875
37580c80 3876 /* Inout operand of sub can not conflict with any operands from multiply. */
4ed6ee50 3877 if (rtx_equal_p (operands[3], operands[0])
3878 || rtx_equal_p (operands[3], operands[1])
3879 || rtx_equal_p (operands[3], operands[2]))
3880 return 0;
3881
3882 /* Passed. Operands are suitable for fmpysub. */
3883 return 1;
3884}
3885
89f29d73 3886int
3887plus_xor_ior_operator (op, mode)
3888 rtx op;
3889 enum machine_mode mode;
3890{
3891 return (GET_CODE (op) == PLUS || GET_CODE (op) == XOR
3892 || GET_CODE (op) == IOR);
3893}
6720f95e 3894
3895/* Return 1 if the given constant is 2, 4, or 8. These are the valid
3896 constants for shadd instructions. */
3897int
3898shadd_constant_p (val)
3899 int val;
3900{
3901 if (val == 2 || val == 4 || val == 8)
3902 return 1;
3903 else
3904 return 0;
3905}
3a16146d 3906
3907/* Return 1 if OP is a CONST_INT with the value 2, 4, or 8. These are
3908 the valid constant for shadd instructions. */
3909int
3910shadd_operand (op, mode)
3911 rtx op;
3912 enum machine_mode mode;
3913{
3914 return (GET_CODE (op) == CONST_INT && shadd_constant_p (INTVAL (op)));
3915}
5fbd5940 3916
3917/* Return 1 if INSN branches forward. Should be using insn_addresses
3918 to avoid walking through all the insns... */
3919int
3920forward_branch_p (insn)
3921 rtx insn;
3922{
3923 rtx label = JUMP_LABEL (insn);
3924
3925 while (insn)
3926 {
3927 if (insn == label)
3928 break;
3929 else
3930 insn = NEXT_INSN (insn);
3931 }
3932
3933 return (insn == label);
3934}
3935
29a4502c 3936/* Return 1 if OP is an equality comparison, else return 0. */
3937int
3938eq_neq_comparison_operator (op, mode)
3939 rtx op;
3940 enum machine_mode mode;
3941{
3942 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
3943}
3944
3945/* Return 1 if OP is an operator suitable for use in a movb instruction. */
3946int
3947movb_comparison_operator (op, mode)
3948 rtx op;
3949 enum machine_mode mode;
3950{
3951 return (GET_CODE (op) == EQ || GET_CODE (op) == NE
3952 || GET_CODE (op) == LT || GET_CODE (op) == GE);
3953}
3954
d6686e21 3955/* Return 1 if INSN is in the delay slot of a call instruction. */
3956int
3957jump_in_call_delay (insn)
3958 rtx insn;
3959{
3960
3961 if (GET_CODE (insn) != JUMP_INSN)
3962 return 0;
3963
3964 if (PREV_INSN (insn)
3965 && PREV_INSN (PREV_INSN (insn))
3966 && GET_CODE (next_active_insn (PREV_INSN (PREV_INSN (insn)))) == INSN)
3967 {
3968 rtx test_insn = next_active_insn (PREV_INSN (PREV_INSN (insn)));
3969
3970 return (GET_CODE (PATTERN (test_insn)) == SEQUENCE
3971 && XVECEXP (PATTERN (test_insn), 0, 1) == insn);
3972
3973 }
3974 else
3975 return 0;
3976}