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