]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/pa/pa.c
* pa.md (reload_insi, reload_outsi): Use new "Z" constraint instead
[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 49/* Name of where we pretend to think the frame pointer points.
50 Normally, this is "4", but if we are in a leaf procedure,
51 this is "something(30)". Will this work? */
52char *frame_base_name;
53
54static rtx find_addr_reg ();
55
56/* Return non-zero only if OP is a register of mode MODE,
57 or const0_rtx. */
58int
59reg_or_0_operand (op, mode)
60 rtx op;
61 enum machine_mode mode;
62{
63 return (op == const0_rtx || register_operand (op, mode));
64}
65
66int
67call_operand_address (op, mode)
68 rtx op;
69 enum machine_mode mode;
70{
ccea8506 71 return (REG_P (op)
72 || (CONSTANT_P (op) && ! TARGET_LONG_CALLS));
87ad11b0 73}
74
75int
76symbolic_operand (op, mode)
77 register rtx op;
78 enum machine_mode mode;
79{
80 switch (GET_CODE (op))
81 {
82 case SYMBOL_REF:
83 case LABEL_REF:
84 return 1;
85 case CONST:
86 op = XEXP (op, 0);
87 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
88 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
89 && GET_CODE (XEXP (op, 1)) == CONST_INT);
90 default:
91 return 0;
92 }
93}
94
95/* Return truth value of statement that OP is a symbolic memory
96 operand of mode MODE. */
97
98int
99symbolic_memory_operand (op, mode)
100 rtx op;
101 enum machine_mode mode;
102{
103 if (GET_CODE (op) == SUBREG)
104 op = SUBREG_REG (op);
105 if (GET_CODE (op) != MEM)
106 return 0;
107 op = XEXP (op, 0);
108 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
109 || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
110}
111
112/* Return 1 if the operand is either a register or a memory operand that is
113 not symbolic. */
114
115int
116reg_or_nonsymb_mem_operand (op, mode)
117 register rtx op;
118 enum machine_mode mode;
119{
120 if (register_operand (op, mode))
121 return 1;
122
123 if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
124 return 1;
125
126 return 0;
127}
128
129int
130move_operand (op, mode)
131 rtx op;
132 enum machine_mode mode;
133{
134 if (register_operand (op, mode))
135 return 1;
136
137 if (op == CONST0_RTX (mode))
138 return 1;
139
140 if (GET_MODE (op) != mode)
141 return 0;
142 if (GET_CODE (op) == SUBREG)
143 op = SUBREG_REG (op);
144 if (GET_CODE (op) != MEM)
145 return 0;
146
147 op = XEXP (op, 0);
148 if (GET_CODE (op) == LO_SUM)
149 return (register_operand (XEXP (op, 0), Pmode)
150 && CONSTANT_P (XEXP (op, 1)));
151 return memory_address_p (mode, op);
152}
153
154int
155pic_operand (op, mode)
156 rtx op;
157 enum machine_mode mode;
158{
159 return flag_pic && GET_CODE (op) == LABEL_REF;
160}
161
162int
163short_memory_operand (op, mode)
164 rtx op;
165 enum machine_mode mode;
166{
167 if (GET_CODE (op) == MEM)
168 {
169 if (GET_CODE (XEXP (op, 0)) == REG)
170 return 1;
171 else if (GET_CODE (XEXP (op, 0)) == PLUS)
172 {
173 rtx op1 = XEXP (XEXP (op, 0), 0);
174 rtx op2 = XEXP (XEXP (op, 0), 1);
175
176 if (GET_CODE (op1) == REG)
177 return (GET_CODE (op2) == CONST_INT && INT_5_BITS (op2));
178 else if (GET_CODE (op2) == REG)
179 return (GET_CODE (op1) == CONST_INT && INT_5_BITS (op1));
180 }
181 }
182 return 0;
183}
184
185int
186register_or_short_operand (op, mode)
187 rtx op;
188 enum machine_mode mode;
189{
190 if (register_operand (op, mode))
191 return 1;
192 if (GET_CODE (op) == SUBREG)
193 op = SUBREG_REG (op);
194 return short_memory_operand (op, mode);
195}
196
197int
198fp_reg_operand (op, mode)
199 rtx op;
200 enum machine_mode mode;
201{
202 return reg_renumber && FP_REG_P (op);
203}
d6f01525 204
205int
206check_fp_mov (operands)
207 rtx *operands;
208{
209 enum machine_mode mode = GET_MODE (operands[0]);
210
211 if (fp_reg_operand (operands[0], mode))
212 return (register_operand (operands[1], mode)
213 || short_memory_operand (operands[1], mode));
214 else if (fp_reg_operand (operands[1], mode))
215 return (register_operand (operands[0], mode)
216 || short_memory_operand (operands[0], mode));
217 else
218 return 1;
219}
87ad11b0 220\f
221extern int current_function_uses_pic_offset_table;
222extern rtx force_reg (), validize_mem ();
223
224/* The rtx for the global offset table which is a special form
225 that *is* a position independent symbolic constant. */
226rtx pic_pc_rtx;
227
228/* Ensure that we are not using patterns that are not OK with PIC. */
229
230int
231check_pic (i)
232 int i;
233{
234 extern rtx recog_operand[];
235 switch (flag_pic)
236 {
237 case 1:
238 if (GET_CODE (recog_operand[i]) == SYMBOL_REF
239 || (GET_CODE (recog_operand[i]) == CONST
240 && ! rtx_equal_p (pic_pc_rtx, recog_operand[i])))
241 abort ();
242 case 2:
243 default:
244 return 1;
245 }
246}
247
248/* Return truth value of whether OP is EQ or NE. */
249
250int
251eq_or_neq (op, mode)
252 rtx op;
253 enum machine_mode mode;
254{
255 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
256}
257
258/* Return truth value of whether OP can be used as an operand in a
259 three operand arithmetic insn that accepts registers of mode MODE
260 or 14-bit signed integers. */
261int
262arith_operand (op, mode)
263 rtx op;
264 enum machine_mode mode;
265{
266 return (register_operand (op, mode)
267 || (GET_CODE (op) == CONST_INT && INT_14_BITS (op)));
268}
269
270/* Return truth value of whether OP can be used as an operand in a
271 three operand arithmetic insn that accepts registers of mode MODE
272 or 11-bit signed integers. */
273int
274arith11_operand (op, mode)
275 rtx op;
276 enum machine_mode mode;
277{
278 return (register_operand (op, mode)
279 || (GET_CODE (op) == CONST_INT && INT_11_BITS (op)));
280}
281
282int
283arith_double_operand (op, mode)
284 rtx op;
285 enum machine_mode mode;
286{
287 return (register_operand (op, mode)
288 || (GET_CODE (op) == CONST_DOUBLE
289 && GET_MODE (op) == mode
290 && VAL_14_BITS_P (CONST_DOUBLE_LOW (op))
291 && (CONST_DOUBLE_HIGH (op) >= 0
292 == ((CONST_DOUBLE_LOW (op) & 0x1000) == 0))));
293}
294
295/* Return truth value of whether OP is a integer which fits the
296 range constraining immediate operands in three-address insns. */
297
298int
299int5_operand (op, mode)
300 rtx op;
301 enum machine_mode mode;
302{
303 return (GET_CODE (op) == CONST_INT && INT_5_BITS (op));
304}
305
306int
307uint5_operand (op, mode)
308 rtx op;
309 enum machine_mode mode;
310{
311 return (GET_CODE (op) == CONST_INT && INT_U5_BITS (op));
312}
313
314
315int
316int11_operand (op, mode)
317 rtx op;
318 enum machine_mode mode;
319{
320 return (GET_CODE (op) == CONST_INT && INT_11_BITS (op));
321}
322
323int
324arith5_operand (op, mode)
325 rtx op;
326 enum machine_mode mode;
327{
328 return register_operand (op, mode) || int5_operand (op, mode);
329}
330
fad0b60f 331/* True iff zdepi can be used to generate this CONST_INT. */
e057641f 332int
333depi_cint_operand (op, mode)
fad0b60f 334 rtx op;
335 enum machine_mode mode;
336{
337 unsigned x;
338 unsigned lbmask, t;
339
340 if (GET_CODE (op) != CONST_INT)
341 return 0;
342
343 /* This might not be obvious, but it's at least fast.
344 This function is critcal; we don't have the time loops would take. */
345 x = INTVAL (op);
346 lbmask = x & -x;
347 t = ((x >> 4) + lbmask) & ~(lbmask - 1);
348 return ((t & (t - 1)) == 0);
349}
350
e057641f 351/* True iff depi or extru can be used to compute (reg & mask). */
352int
353consec_zeros_p (mask)
354 unsigned mask;
355{
356 mask = ~mask;
357 mask += mask & -mask;
358 return (mask & (mask - 1)) == 0;
359}
360
361/* True iff depi or extru can be used to compute (reg & OP). */
362int
363and_operand (op, mode)
364 rtx op;
365 enum machine_mode mode;
366{
367 return (register_operand (op, mode)
368 || (GET_CODE (op) == CONST_INT && consec_zeros_p (INTVAL (op))));
369}
370
371/* True iff depi can be used to compute (reg | MASK). */
372int
373ior_mask_p (mask)
374 unsigned mask;
375{
376 mask += mask & -mask;
377 return (mask & (mask - 1)) == 0;
378}
379
380/* True iff depi can be used to compute (reg | OP). */
381int
382ior_operand (op, mode)
383 rtx op;
384 enum machine_mode mode;
385{
386 return (register_operand (op, mode)
387 || (GET_CODE (op) == CONST_INT && ior_mask_p (INTVAL (op))));
388}
389
9c6d4825 390int
391arith32_operand (op, mode)
392 rtx op;
393 enum machine_mode mode;
394{
395 return register_operand (op, mode) || GET_CODE (op) == CONST_INT;
396}
397
87ad11b0 398/* True iff OP can be the source of a move to a general register. */
399int
400srcsi_operand (op, mode)
401 rtx op;
402 enum machine_mode mode;
403{
404 /* Not intended for other modes than SImode. */
405 if (mode != SImode)
406 return 0;
407
408 /* Accept any register or memory reference. */
409 if (nonimmediate_operand (op, mode))
410 return 1;
411
d2c1d63d 412 if (depi_cint_operand (op, mode))
413 return 1;
414
87ad11b0 415 /* OK if ldo or ldil can be used. */
416 return (GET_CODE (op) == CONST_INT
417 && (INT_14_BITS (op) || (INTVAL (op) & 0x7ff) == 0));
418}
419
420\f
421/* Legitimize PIC addresses. If the address is already
422 position-independent, we return ORIG. Newly generated
423 position-independent addresses go to REG. If we need more
424 than one register, we lose. */
425
426rtx
427legitimize_pic_address (orig, mode, reg)
428 rtx orig, reg;
429 enum machine_mode mode;
430{
431 rtx pic_ref = orig;
432
433 if (GET_CODE (orig) == SYMBOL_REF)
434 {
435 if (reg == 0)
436 abort ();
437
438 if (flag_pic == 2)
439 {
440 emit_insn (gen_rtx (SET, VOIDmode, reg,
441 gen_rtx (HIGH, Pmode, orig)));
442 emit_insn (gen_rtx (SET, VOIDmode, reg,
443 gen_rtx (LO_SUM, Pmode, reg, orig)));
444 orig = reg;
445 }
446 pic_ref = gen_rtx (MEM, Pmode,
447 gen_rtx (PLUS, Pmode,
448 pic_offset_table_rtx, orig));
449 current_function_uses_pic_offset_table = 1;
450 RTX_UNCHANGING_P (pic_ref) = 1;
451 emit_move_insn (reg, pic_ref);
452 return reg;
453 }
454 else if (GET_CODE (orig) == CONST)
455 {
456 rtx base, offset;
457
458 if (GET_CODE (XEXP (orig, 0)) == PLUS
459 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
460 return orig;
461
462 if (reg == 0)
463 abort ();
464
465 if (GET_CODE (XEXP (orig, 0)) == PLUS)
466 {
467 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
468 orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
469 base == reg ? 0 : reg);
470 }
471 else abort ();
472 if (GET_CODE (orig) == CONST_INT)
473 {
474 if (SMALL_INT (orig))
475 return plus_constant_for_output (base, INTVAL (orig));
476 orig = force_reg (Pmode, orig);
477 }
478 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
479 /* Likewise, should we set special REG_NOTEs here? */
480 }
481 return pic_ref;
482}
483
484/* Set up PIC-specific rtl. This should not cause any insns
485 to be emitted. */
486
487void
488initialize_pic ()
489{
490}
491
492/* Emit special PIC prologues and epilogues. */
493
494void
495finalize_pic ()
496{
eff812f1 497 if (hppa_save_pic_table_rtx)
498 {
499 emit_insn_after (gen_rtx (SET, VOIDmode,
500 hppa_save_pic_table_rtx,
501 gen_rtx (REG, Pmode, 19)),
502 get_insns ());
503 /* Need to emit this whether or not we obey regdecls,
504 since setjmp/longjmp can cause life info to screw up. */
505 hppa_save_pic_table_rtx = 0;
506 }
87ad11b0 507 emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
eff812f1 508
87ad11b0 509}
510
511/* For the HPPA, REG and REG+CONST is cost 0
512 and addresses involving symbolic constants are cost 2.
513
514 PIC addresses are very expensive.
515
516 It is no coincidence that this has the same structure
517 as GO_IF_LEGITIMATE_ADDRESS. */
518int
519hppa_address_cost (X)
520 rtx X;
521{
522 if (GET_CODE (X) == PLUS)
523 return 1;
524 else if (GET_CODE (X) == LO_SUM)
525 return 1;
526 else if (GET_CODE (X) == HIGH)
527 return 2;
528 return 4;
529}
530
531/* Emit insns to move operands[1] into operands[0].
532
533 Return 1 if we have written out everything that needs to be done to
534 do the move. Otherwise, return 0 and the caller will emit the move
535 normally. */
536
537int
d6f01525 538emit_move_sequence (operands, mode, scratch_reg)
87ad11b0 539 rtx *operands;
540 enum machine_mode mode;
d6f01525 541 rtx scratch_reg;
87ad11b0 542{
543 register rtx operand0 = operands[0];
544 register rtx operand1 = operands[1];
545
d6f01525 546 if (fp_reg_operand (operand0, mode)
547 && GET_CODE (operand1) == MEM
548 && !short_memory_operand (operand1, mode)
549 && scratch_reg)
550 {
551 emit_move_insn (scratch_reg, XEXP (operand1 , 0));
552 emit_insn (gen_rtx (SET, VOIDmode, operand0, gen_rtx (MEM, mode,
553 scratch_reg)));
554 return 1;
555 }
556 else if (fp_reg_operand (operand1, mode)
557 && GET_CODE (operand0) == MEM
558 && !short_memory_operand (operand0, mode)
559 && scratch_reg)
560 {
561 emit_move_insn (scratch_reg, XEXP (operand0 , 0));
562 emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, mode, scratch_reg),
563 operand1));
564 return 1;
565 }
566 /* Handle most common case: storing into a register. */
567 else if (register_operand (operand0, mode))
87ad11b0 568 {
569 if (register_operand (operand1, mode)
570 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
571 || (GET_CODE (operand1) == HIGH
572 && !symbolic_operand (XEXP (operand1, 0)))
573 /* Only `general_operands' can come here, so MEM is ok. */
574 || GET_CODE (operand1) == MEM)
575 {
576 /* Run this case quickly. */
577 emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
578 return 1;
579 }
580 }
581 else if (GET_CODE (operand0) == MEM)
582 {
583 if (register_operand (operand1, mode) || operand1 == const0_rtx)
584 {
585 /* Run this case quickly. */
586 emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
587 return 1;
588 }
589 if (! reload_in_progress)
590 {
591 operands[0] = validize_mem (operand0);
592 operands[1] = operand1 = force_reg (mode, operand1);
593 }
594 }
595
596 /* Simplify the source if we need to. */
87ad11b0 597 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
598 {
599 if (symbolic_operand (operand1, mode))
600 {
601 if (flag_pic)
602 {
603 rtx temp = reload_in_progress ? operand0 : gen_reg_rtx (Pmode);
604 operands[1] = legitimize_pic_address (operand1, mode, temp);
605 }
606 /* On the HPPA, references to data space are supposed to */
607 /* use dp, register 27. */
608 else if (read_only_operand (operand1))
609 {
d6f01525 610 rtx set = gen_rtx (SET, VOIDmode,
87ad11b0 611 operand0,
d6f01525 612 gen_rtx (LO_SUM, mode, operand0, operand1));
613
87ad11b0 614 emit_insn (gen_rtx (SET, VOIDmode,
615 operand0,
d6f01525 616 gen_rtx (HIGH, mode, operand1)));
617 if (TARGET_SHARED_LIBS
618 && function_label_operand (operand1, mode))
619 {
620 rtx temp = reload_in_progress ? scratch_reg
621 : gen_reg_rtx (mode);
622 if (!temp)
623 abort ();
624 emit_insn (gen_rtx (PARALLEL, VOIDmode,
625 gen_rtvec (2,
626 set,
627 gen_rtx (CLOBBER, VOIDmode,
628 temp))));
629 }
630 else
631 emit_insn (set);
87ad11b0 632 return 1;
633 }
634 else
635 {
636 /* If reload_in_progress, we can't use addil and r1; we */
637 /* have to use the more expensive ldil sequence. */
638 if (reload_in_progress)
639 {
640 emit_insn (gen_rtx (SET, VOIDmode,
641 operand0,
642 gen_rtx (HIGH, mode, operand1)));
643 emit_insn (gen_rtx (SET, VOIDmode,
644 operand0,
645 gen_rtx (PLUS, mode,
646 operand0,
647 gen_rtx (REG, mode, 27))));
648 emit_insn (gen_rtx (SET, VOIDmode,
649 operand0,
650 gen_rtx (LO_SUM, mode,
651 operand0, operand1)));
652 }
653 else
654 {
26344e96 655 rtx temp1, temp2 = gen_reg_rtx (mode);
87ad11b0 656
26344e96 657 /* For 2.4 we could set RTX_UNCHANGING and add a
658 REG_EQUAL note for the first insn. This would
659 allow the first insn to be moved out of loops. */
660 temp1 = gen_rtx (HIGH, mode, operand1);
87ad11b0 661 emit_insn (gen_rtx (SET, VOIDmode,
662 temp2,
663 gen_rtx (PLUS, mode,
664 gen_rtx (REG, mode, 27),
665 temp1)));
666 emit_insn (gen_rtx (SET, VOIDmode,
667 operand0,
668 gen_rtx (LO_SUM, mode,
669 temp2, operand1)));
670 }
671 return 1;
672 }
673 }
e057641f 674 else if (depi_cint_operand (operand1, VOIDmode))
fad0b60f 675 return 0;
87ad11b0 676 else if (GET_CODE (operand1) == CONST_INT
677 ? (! SMALL_INT (operand1)
678 && (INTVAL (operand1) & 0x7ff) != 0) : 1)
679 {
680 rtx temp = reload_in_progress ? operand0 : gen_reg_rtx (mode);
681 emit_insn (gen_rtx (SET, VOIDmode, temp,
682 gen_rtx (HIGH, mode, operand1)));
683 operands[1] = gen_rtx (LO_SUM, mode, temp, operand1);
684 }
685 }
686 /* Now have insn-emit do whatever it normally does. */
687 return 0;
688}
689
690/* Does operand (which is a symbolic_operand) live in text space? If
691 so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true.*/
692
693int
694read_only_operand (operand)
695 rtx operand;
696{
697 if (GET_CODE (operand) == CONST)
698 operand = XEXP (XEXP (operand, 0), 0);
699 if (GET_CODE (operand) == SYMBOL_REF)
700 return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
701 return 1;
702}
703
704\f
705/* Return the best assembler insn template
706 for moving operands[1] into operands[0] as a fullword. */
707
5c683f13 708char *
87ad11b0 709singlemove_string (operands)
710 rtx *operands;
711{
712 if (GET_CODE (operands[0]) == MEM)
713 return "stw %r1,%0";
714 if (GET_CODE (operands[1]) == MEM)
715 return "ldw %1,%0";
716 if (GET_CODE (operands[1]) == CONST_INT)
717 if (INT_14_BITS (operands[1]))
718 return (INTVAL (operands[1]) == 0 ? "copy 0,%0" : "ldi %1,%0");
719 else
720 return "ldil L'%1,%0\n\tldo R'%1(%0),%0";
721 return "copy %1,%0";
722}
723\f
724
e057641f 725/* Compute position (in OPERANDS[2]) and width (in OPERANDS[3])
726 useful for copying or or'ing IMM to a register using bit field
727 instructions. Store the immediate value to insert in OPERANDS[1]. */
728void
729compute_xdepi_operands_from_integer (imm, operands)
730 unsigned imm;
7e10ba53 731 rtx *operands;
732{
e057641f 733 int lsb, len;
7e10ba53 734
e057641f 735 /* Find the least significant set bit in IMM. */
736 for (lsb = 0; lsb < 32; lsb++)
7e10ba53 737 {
e057641f 738 if ((imm & 1) != 0)
7e10ba53 739 break;
e057641f 740 imm >>= 1;
7e10ba53 741 }
742
e057641f 743 /* Choose variants based on *sign* of the 5-bit field. */
744 if ((imm & 0x10) == 0)
745 len = (lsb <= 28) ? 4 : 32 - lsb;
7e10ba53 746 else
747 {
e057641f 748 /* Find the width of the bitstring in IMM. */
749 for (len = 5; len < 32; len++)
7e10ba53 750 {
e057641f 751 if ((imm & (1 << len)) == 0)
7e10ba53 752 break;
7e10ba53 753 }
754
e057641f 755 /* Sign extend IMM as a 5-bit value. */
756 imm = (imm & 0xf) - 0x10;
7e10ba53 757 }
758
e057641f 759 operands[1] = gen_rtx (CONST_INT, VOIDmode, imm);
760 operands[2] = gen_rtx (CONST_INT, VOIDmode, 31 - lsb);
761 operands[3] = gen_rtx (CONST_INT, VOIDmode, len);
7e10ba53 762}
763
87ad11b0 764/* Output assembler code to perform a doubleword move insn
765 with operands OPERANDS. */
766
767char *
768output_move_double (operands)
769 rtx *operands;
770{
771 enum { REGOP, OFFSOP, MEMOP, CNSTOP, RNDOP } optype0, optype1;
772 rtx latehalf[2];
773 rtx addreg0 = 0, addreg1 = 0;
774
775 /* First classify both operands. */
776
777 if (REG_P (operands[0]))
778 optype0 = REGOP;
779 else if (offsettable_memref_p (operands[0]))
780 optype0 = OFFSOP;
781 else if (GET_CODE (operands[0]) == MEM)
782 optype0 = MEMOP;
783 else
784 optype0 = RNDOP;
785
786 if (REG_P (operands[1]))
787 optype1 = REGOP;
788 else if (CONSTANT_P (operands[1]))
789 optype1 = CNSTOP;
790 else if (offsettable_memref_p (operands[1]))
791 optype1 = OFFSOP;
792 else if (GET_CODE (operands[1]) == MEM)
793 optype1 = MEMOP;
794 else
795 optype1 = RNDOP;
796
797 /* Check for the cases that the operand constraints are not
798 supposed to allow to happen. Abort if we get one,
799 because generating code for these cases is painful. */
800
801 if (optype0 != REGOP && optype1 != REGOP)
802 abort ();
803
804 /* Handle auto decrementing and incrementing loads and stores
805 specifically, since the structure of the function doesn't work
806 for them without major modification. Do it better when we learn
807 this port about the general inc/dec addressing of PA.
808 (This was written by tege. Chide him if it doesn't work.) */
809
810 if (optype0 == MEMOP)
811 {
1df0058a 812 /* We have to output the address syntax ourselves, since print_operand
813 doesn't deal with the addresses we want to use. Fix this later. */
814
87ad11b0 815 rtx addr = XEXP (operands[0], 0);
1df0058a 816 if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)
87ad11b0 817 {
1df0058a 818 rtx high_reg = gen_rtx (SUBREG, SImode, operands[1], 0);
819
820 operands[0] = XEXP (addr, 0);
821 if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)
822 abort ();
823
824 if (!reg_overlap_mentioned_p (high_reg, addr))
825 {
826 /* No overlap between high target register and address
827 register. (We do this in a non-obvious way to
828 save a register file writeback) */
829 if (GET_CODE (addr) == POST_INC)
830 return "stws,ma %1,8(0,%0)\n\tstw %R1,-4(0,%0)";
831 return "stws,ma %1,-8(0,%0)\n\tstw %R1,12(0,%0)";
832 }
833 else
834 abort();
a3217f65 835 }
1df0058a 836 else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
a3217f65 837 {
1df0058a 838 rtx high_reg = gen_rtx (SUBREG, SImode, operands[1], 0);
839
840 operands[0] = XEXP (addr, 0);
841 if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)
842 abort ();
843
844 if (!reg_overlap_mentioned_p (high_reg, addr))
845 {
846 /* No overlap between high target register and address
847 register. (We do this in a non-obvious way to
848 save a register file writeback) */
849 if (GET_CODE (addr) == PRE_INC)
850 return "stws,mb %1,8(0,%0)\n\tstw %R1,4(0,%0)";
851 return "stws,mb %1,-8(0,%0)\n\tstw %R1,4(0,%0)";
852 }
853 else
854 abort();
87ad11b0 855 }
856 }
857 if (optype1 == MEMOP)
858 {
859 /* We have to output the address syntax ourselves, since print_operand
860 doesn't deal with the addresses we want to use. Fix this later. */
861
862 rtx addr = XEXP (operands[1], 0);
863 if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)
864 {
865 rtx high_reg = gen_rtx (SUBREG, SImode, operands[0], 0);
866
867 operands[1] = XEXP (addr, 0);
868 if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG)
869 abort ();
870
871 if (!reg_overlap_mentioned_p (high_reg, addr))
872 {
873 /* No overlap between high target register and address
3857fa62 874 register. (We do this in a non-obvious way to
87ad11b0 875 save a register file writeback) */
876 if (GET_CODE (addr) == POST_INC)
877 return "ldws,ma 8(0,%1),%0\n\tldw -4(0,%1),%R0";
878 return "ldws,ma -8(0,%1),%0\n\tldw 12(0,%1),%R0";
879 }
880 else
881 {
882 /* This is an undefined situation. We should load into the
883 address register *and* update that register. Probably
884 we don't need to handle this at all. */
885 if (GET_CODE (addr) == POST_INC)
886 return "ldw 4(0,%1),%R0\n\tldws,ma 8(0,%1),%0";
887 return "ldw 4(0,%1),%R0\n\tldws,ma -8(0,%1),%0";
888 }
889 }
890 else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
891 {
892 rtx high_reg = gen_rtx (SUBREG, SImode, operands[0], 0);
893
894 operands[1] = XEXP (addr, 0);
895 if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG)
896 abort ();
897
898 if (!reg_overlap_mentioned_p (high_reg, addr))
899 {
900 /* No overlap between high target register and address
3857fa62 901 register. (We do this in a non-obvious way to
87ad11b0 902 save a register file writeback) */
903 if (GET_CODE (addr) == PRE_INC)
904 return "ldws,mb 8(0,%1),%0\n\tldw 4(0,%1),%R0";
905 return "ldws,mb -8(0,%1),%0\n\tldw 4(0,%1),%R0";
906 }
907 else
908 {
909 /* This is an undefined situation. We should load into the
910 address register *and* update that register. Probably
911 we don't need to handle this at all. */
912 if (GET_CODE (addr) == PRE_INC)
913 return "ldw 12(0,%1),%R0\n\tldws,mb 8(0,%1),%0";
914 return "ldw -4(0,%1),%R0\n\tldws,mb -8(0,%1),%0";
915 }
916 }
917 }
918
919 /* If an operand is an unoffsettable memory ref, find a register
920 we can increment temporarily to make it refer to the second word. */
921
922 if (optype0 == MEMOP)
923 addreg0 = find_addr_reg (XEXP (operands[0], 0));
924
925 if (optype1 == MEMOP)
926 addreg1 = find_addr_reg (XEXP (operands[1], 0));
927
928 /* Ok, we can do one word at a time.
929 Normally we do the low-numbered word first.
930
931 In either case, set up in LATEHALF the operands to use
932 for the high-numbered word and in some cases alter the
933 operands in OPERANDS to be suitable for the low-numbered word. */
934
935 if (optype0 == REGOP)
936 latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
937 else if (optype0 == OFFSOP)
938 latehalf[0] = adj_offsettable_operand (operands[0], 4);
939 else
940 latehalf[0] = operands[0];
941
942 if (optype1 == REGOP)
943 latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
944 else if (optype1 == OFFSOP)
945 latehalf[1] = adj_offsettable_operand (operands[1], 4);
946 else if (optype1 == CNSTOP)
947 split_double (operands[1], &operands[1], &latehalf[1]);
948 else
949 latehalf[1] = operands[1];
950
951 /* If the first move would clobber the source of the second one,
952 do them in the other order.
953
954 RMS says "This happens only for registers;
955 such overlap can't happen in memory unless the user explicitly
956 sets it up, and that is an undefined circumstance."
957
958 but it happens on the HP-PA when loading parameter registers,
959 so I am going to define that circumstance, and make it work
960 as expected. */
961
962 if (optype0 == REGOP && (optype1 == MEMOP || optype1 == OFFSOP)
963 && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))
964 {
965 /* XXX THIS PROBABLY DOESN'T WORK. */
966 /* Do the late half first. */
967 if (addreg1)
6a5d085a 968 output_asm_insn ("ldo 4(%0),%0", &addreg1);
87ad11b0 969 output_asm_insn (singlemove_string (latehalf), latehalf);
970 if (addreg1)
6a5d085a 971 output_asm_insn ("ldo -4(%0),%0", &addreg1);
87ad11b0 972 /* Then clobber. */
973 return singlemove_string (operands);
974 }
975
c4fa5937 976 if (optype0 == REGOP && optype1 == REGOP
977 && REGNO (operands[0]) == REGNO (operands[1]) + 1)
978 {
979 output_asm_insn (singlemove_string (latehalf), latehalf);
980 return singlemove_string (operands);
981 }
982
87ad11b0 983 /* Normal case: do the two words, low-numbered first. */
984
985 output_asm_insn (singlemove_string (operands), operands);
986
987 /* Make any unoffsettable addresses point at high-numbered word. */
988 if (addreg0)
6a5d085a 989 output_asm_insn ("ldo 4(%0),%0", &addreg0);
87ad11b0 990 if (addreg1)
6a5d085a 991 output_asm_insn ("ldo 4(%0),%0", &addreg1);
87ad11b0 992
993 /* Do that word. */
994 output_asm_insn (singlemove_string (latehalf), latehalf);
995
996 /* Undo the adds we just did. */
997 if (addreg0)
6a5d085a 998 output_asm_insn ("ldo -4(%0),%0", &addreg0);
87ad11b0 999 if (addreg1)
6a5d085a 1000 output_asm_insn ("ldo -4(%0),%0", &addreg1);
87ad11b0 1001
1002 return "";
1003}
1004\f
1005char *
1006output_fp_move_double (operands)
1007 rtx *operands;
1008{
1009 if (FP_REG_P (operands[0]))
1010 {
1011 if (FP_REG_P (operands[1]))
1012 output_asm_insn ("fcpy,dbl %1,%0", operands);
1013 else if (GET_CODE (operands[1]) == REG)
1014 {
1015 rtx xoperands[3];
1016 xoperands[0] = operands[0];
1017 xoperands[1] = operands[1];
1018 xoperands[2] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1019 output_asm_insn
1020 ("stw %1,-16(0,30)\n\tstw %2,-12(0,30)\n\tfldds -16(0,30),%0",
1021 xoperands);
1022 }
1023 else
1024 output_asm_insn ("fldds%F1 %1,%0", operands);
1025 }
1026 else if (FP_REG_P (operands[1]))
1027 {
1028 if (GET_CODE (operands[0]) == REG)
1029 {
1030 rtx xoperands[3];
1031 xoperands[2] = operands[1];
1032 xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1033 xoperands[0] = operands[0];
1034 output_asm_insn
1035 ("fstds %2,-16(0,30)\n\tldw -12(0,30),%1\n\tldw -16(0,30),%0",
1036 xoperands);
1037 }
1038 else
1039 output_asm_insn ("fstds%F0 %1,%0", operands);
1040 }
1041 else abort ();
1042 return "";
1043}
1044\f
1045/* Return a REG that occurs in ADDR with coefficient 1.
1046 ADDR can be effectively incremented by incrementing REG. */
1047
1048static rtx
1049find_addr_reg (addr)
1050 rtx addr;
1051{
1052 while (GET_CODE (addr) == PLUS)
1053 {
1054 if (GET_CODE (XEXP (addr, 0)) == REG)
1055 addr = XEXP (addr, 0);
1056 else if (GET_CODE (XEXP (addr, 1)) == REG)
1057 addr = XEXP (addr, 1);
1058 else if (CONSTANT_P (XEXP (addr, 0)))
1059 addr = XEXP (addr, 1);
1060 else if (CONSTANT_P (XEXP (addr, 1)))
1061 addr = XEXP (addr, 0);
1062 else
1063 abort ();
1064 }
1065 if (GET_CODE (addr) == REG)
1066 return addr;
1067 abort ();
1068}
1069
87ad11b0 1070/* Emit code to perform a block move.
1071
1072 Restriction: If the length argument is non-constant, alignment
1073 must be 4.
1074
1075 OPERANDS[0] is the destination pointer as a REG, clobbered.
1076 OPERANDS[1] is the source pointer as a REG, clobbered.
1077 if SIZE_IS_CONSTANT
1078 OPERANDS[2] is a register for temporary storage.
1079 OPERANDS[4] is the size as a CONST_INT
1080 else
1081 OPERANDS[2] is a REG which will contain the size, clobbered.
1082 OPERANDS[3] is a register for temporary storage.
1083 OPERANDS[5] is the alignment safe to use, as a CONST_INT. */
1084
1085char *
1086output_block_move (operands, size_is_constant)
1087 rtx *operands;
1088 int size_is_constant;
1089{
1090 int align = INTVAL (operands[5]);
1091 unsigned long n_bytes;
1092
1093 /* We can't move more than four bytes at a time because the PA
1094 has no longer integer move insns. (Could use fp mem ops?) */
1095 if (align > 4)
1096 align = 4;
1097
1098 if (size_is_constant)
1099 {
1100 unsigned long n_items;
1101 unsigned long offset;
1102 rtx temp;
1103
1104 n_bytes = INTVAL (operands[4]);
1105 if (n_bytes == 0)
1106 return "";
1107
1108 if (align >= 4)
1109 {
1110 /* Don't unroll too large blocks. */
1111 if (n_bytes > 64)
1112 goto copy_with_loop;
1113
1114 /* Read and store using two registers, and hide latency
4bbea254 1115 by deferring the stores until three instructions after
87ad11b0 1116 the corresponding load. The last load insn will read
1117 the entire word were the last bytes are, possibly past
1118 the end of the source block, but since loads are aligned,
1119 this is harmless. */
1120
1121 output_asm_insn ("ldws,ma 4(0,%1),%2", operands);
1122
1123 for (offset = 4; offset < n_bytes; offset += 4)
1124 {
1125 output_asm_insn ("ldws,ma 4(0,%1),%3", operands);
1126 output_asm_insn ("stws,ma %2,4(0,%0)", operands);
1127
1128 temp = operands[2];
1129 operands[2] = operands[3];
1130 operands[3] = temp;
1131 }
1132 if (n_bytes % 4 == 0)
1133 /* Store the last word. */
1134 output_asm_insn ("stw %2,0(0,%0)", operands);
1135 else
1136 {
1137 /* Store the last, partial word. */
1138 operands[4] = gen_rtx (CONST_INT, VOIDmode, n_bytes % 4);
1139 output_asm_insn ("stbys,e %2,%4(0,%0)", operands);
1140 }
1141 return "";
1142 }
1143
1144 if (align >= 2 && n_bytes >= 2)
1145 {
1146 output_asm_insn ("ldhs,ma 2(0,%1),%2", operands);
1147
1148 for (offset = 2; offset + 2 <= n_bytes; offset += 2)
1149 {
1150 output_asm_insn ("ldhs,ma 2(0,%1),%3", operands);
1151 output_asm_insn ("sths,ma %2,2(0,%0)", operands);
1152
1153 temp = operands[2];
1154 operands[2] = operands[3];
1155 operands[3] = temp;
1156 }
1157 if (n_bytes % 2 != 0)
1158 output_asm_insn ("ldb 0(0,%1),%3", operands);
1159
1160 output_asm_insn ("sths,ma %2,2(0,%0)", operands);
1161
1162 if (n_bytes % 2 != 0)
1163 output_asm_insn ("stb %3,0(0,%0)", operands);
1164
1165 return "";
1166 }
1167
1168 output_asm_insn ("ldbs,ma 1(0,%1),%2", operands);
1169
1170 for (offset = 1; offset + 1 <= n_bytes; offset += 1)
1171 {
1172 output_asm_insn ("ldbs,ma 1(0,%1),%3", operands);
1173 output_asm_insn ("stbs,ma %2,1(0,%0)", operands);
1174
1175 temp = operands[2];
1176 operands[2] = operands[3];
1177 operands[3] = temp;
1178 }
1179 output_asm_insn ("stb %2,0(0,%0)", operands);
1180
1181 return "";
1182 }
1183
1184 if (align != 4)
1185 abort();
1186
1187 copy_with_loop:
1188
1189 if (size_is_constant)
1190 {
a3217f65 1191 /* Size is compile-time determined, and also not
87ad11b0 1192 very small (such small cases are handled above). */
1193 operands[4] = gen_rtx (CONST_INT, VOIDmode, n_bytes - 4);
1194 output_asm_insn ("ldo %4(0),%2", operands);
1195 }
1196 else
1197 {
1198 /* Decrement counter by 4, and if it becomes negative, jump past the
1199 word copying loop. */
1200 output_asm_insn ("addib,<,n -4,%2,.+16", operands);
1201 }
1202
4bbea254 1203 /* Copying loop. Note that the first load is in the annulled delay slot
87ad11b0 1204 of addib. Is it OK on PA to have a load in a delay slot, i.e. is a
1205 possible page fault stopped in time? */
1206 output_asm_insn ("ldws,ma 4(0,%1),%3", operands);
1207 output_asm_insn ("addib,>= -4,%2,.-4", operands);
1208 output_asm_insn ("stws,ma %3,4(0,%0)", operands);
1209
1210 /* The counter is negative, >= -4. The remaining number of bytes are
1211 determined by the two least significant bits. */
1212
1213 if (size_is_constant)
1214 {
1215 if (n_bytes % 4 != 0)
1216 {
1217 /* Read the entire word of the source block tail. */
1218 output_asm_insn ("ldw 0(0,%1),%3", operands);
1219 operands[4] = gen_rtx (CONST_INT, VOIDmode, n_bytes % 4);
1220 output_asm_insn ("stbys,e %3,%4(0,%0)", operands);
1221 }
1222 }
1223 else
1224 {
1225 /* Add 4 to counter. If it becomes zero, we're done. */
1226 output_asm_insn ("addib,=,n 4,%2,.+16", operands);
1227
1228 /* Read the entire word of the source block tail. (Also this
4bbea254 1229 load is in an annulled delay slot.) */
87ad11b0 1230 output_asm_insn ("ldw 0(0,%1),%3", operands);
1231
1232 /* Make %0 point at the first byte after the destination block. */
1233 output_asm_insn ("add %2,%0,%0", operands);
1234 /* Store the leftmost bytes, up to, but not including, the address
1235 in %0. */
1236 output_asm_insn ("stbys,e %3,0(0,%0)", operands);
1237 }
1238 return "";
1239}
1240\f
1241
e057641f 1242char *
1243output_and (operands)
1244 rtx *operands;
1245{
d6f01525 1246 if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
e057641f 1247 {
1248 unsigned mask = INTVAL (operands[2]);
1249 int ls0, ls1, ms0, p, len;
1250
1251 for (ls0 = 0; ls0 < 32; ls0++)
1252 if ((mask & (1 << ls0)) == 0)
1253 break;
1254
1255 for (ls1 = ls0; ls1 < 32; ls1++)
1256 if ((mask & (1 << ls1)) != 0)
1257 break;
1258
1259 for (ms0 = ls1; ms0 < 32; ms0++)
1260 if ((mask & (1 << ms0)) == 0)
1261 break;
1262
1263 if (ms0 != 32)
1264 abort();
1265
1266 if (ls1 == 32)
1267 {
1268 len = ls0;
1269
1270 if (len == 0)
1271 abort ();
1272
1273 operands[2] = gen_rtx (CONST_INT, VOIDmode, len);
1274 return "extru %1,31,%2,%0";
1275 }
1276 else
1277 {
1278 /* We could use this `depi' for the case above as well, but `depi'
1279 requires one more register file access than an `extru'. */
1280
1281 p = 31 - ls0;
1282 len = ls1 - ls0;
1283
1284 operands[2] = gen_rtx (CONST_INT, VOIDmode, p);
1285 operands[3] = gen_rtx (CONST_INT, VOIDmode, len);
1286 return "depi 0,%2,%3,%0";
1287 }
1288 }
1289 else
1290 return "and %1,%2,%0";
1291}
1292
1293char *
1294output_ior (operands)
1295 rtx *operands;
1296{
1297 if (GET_CODE (operands[2]) == CONST_INT)
1298 {
1299 unsigned mask = INTVAL (operands[2]);
1300 int bs0, bs1, bs2, p, len;
23675219 1301
1302 if (INTVAL (operands[2]) == 0)
1303 return "copy %1,%0";
e057641f 1304
1305 for (bs0 = 0; bs0 < 32; bs0++)
1306 if ((mask & (1 << bs0)) != 0)
1307 break;
1308
1309 for (bs1 = bs0; bs1 < 32; bs1++)
1310 if ((mask & (1 << bs1)) == 0)
1311 break;
1312
1313 if (bs1 != 32 && ((unsigned) 1 << bs1) <= mask)
1314 abort();
1315
1316 p = 31 - bs0;
1317 len = bs1 - bs0;
1318
1319 operands[2] = gen_rtx (CONST_INT, VOIDmode, p);
1320 operands[3] = gen_rtx (CONST_INT, VOIDmode, len);
1321 return "depi -1,%2,%3,%0";
1322 }
1323 else
1324 return "or %1,%2,%0";
1325}
1326\f
87ad11b0 1327/* Output an ascii string. */
1328output_ascii (file, p, size)
1329 FILE *file;
1330 unsigned char *p;
1331 int size;
1332{
1333 int i;
1334 int chars_output;
1335 unsigned char partial_output[16]; /* Max space 4 chars can occupy. */
1336
1337 /* The HP assembler can only take strings of 256 characters at one
1338 time. This is a limitation on input line length, *not* the
1339 length of the string. Sigh. Even worse, it seems that the
1340 restriction is in number of input characters (see \xnn &
1341 \whatever). So we have to do this very carefully. */
1342
1343 fprintf (file, "\t.STRING \"");
1344
1345 chars_output = 0;
1346 for (i = 0; i < size; i += 4)
1347 {
1348 int co = 0;
1349 int io = 0;
1350 for (io = 0, co = 0; io < MIN (4, size - i); io++)
1351 {
1352 register unsigned int c = p[i + io];
1353
1354 if (c == '\"' || c == '\\')
1355 partial_output[co++] = '\\';
1356 if (c >= ' ' && c < 0177)
1357 partial_output[co++] = c;
1358 else
1359 {
1360 unsigned int hexd;
1361 partial_output[co++] = '\\';
1362 partial_output[co++] = 'x';
1363 hexd = c / 16 - 0 + '0';
1364 if (hexd > '9')
1365 hexd -= '9' - 'a' + 1;
1366 partial_output[co++] = hexd;
1367 hexd = c % 16 - 0 + '0';
1368 if (hexd > '9')
1369 hexd -= '9' - 'a' + 1;
1370 partial_output[co++] = hexd;
1371 }
1372 }
1373 if (chars_output + co > 243)
1374 {
1375 fprintf (file, "\"\n\t.STRING \"");
1376 chars_output = 0;
1377 }
1378 fwrite (partial_output, 1, co, file);
1379 chars_output += co;
1380 co = 0;
1381 }
1382 fprintf (file, "\"\n");
1383}
1384\f
1385/* You may have trouble believing this, but this is the HP825 stack
1386 layout. Wow.
1387
1388 Offset Contents
1389
1390 Variable arguments (optional; any number may be allocated)
1391
1392 SP-(4*(N+9)) arg word N
1393 : :
1394 SP-56 arg word 5
1395 SP-52 arg word 4
1396
1397 Fixed arguments (must be allocated; may remain unused)
1398
1399 SP-48 arg word 3
1400 SP-44 arg word 2
1401 SP-40 arg word 1
1402 SP-36 arg word 0
1403
1404 Frame Marker
1405
1406 SP-32 External Data Pointer (DP)
1407 SP-28 External sr4
1408 SP-24 External/stub RP (RP')
1409 SP-20 Current RP
1410 SP-16 Static Link
1411 SP-12 Clean up
1412 SP-8 Calling Stub RP (RP'')
1413 SP-4 Previous SP
1414
1415 Top of Frame
1416
1417 SP-0 Stack Pointer (points to next available address)
1418
1419*/
1420
1421/* This function saves registers as follows. Registers marked with ' are
1422 this function's registers (as opposed to the previous function's).
1423 If a frame_pointer isn't needed, r4 is saved as a general register;
1424 the space for the frame pointer is still allocated, though, to keep
1425 things simple.
1426
1427
1428 Top of Frame
1429
1430 SP (FP') Previous FP
1431 SP + 4 Alignment filler (sigh)
1432 SP + 8 Space for locals reserved here.
1433 .
1434 .
1435 .
1436 SP + n All call saved register used.
1437 .
1438 .
1439 .
1440 SP + o All call saved fp registers used.
1441 .
1442 .
1443 .
1444 SP + p (SP') points to next available address.
1445
1446*/
1447
1448/* Helper functions */
1449void
1450print_stw (file, r, disp, base)
1451 FILE *file;
1452 int r, disp, base;
1453{
1454 if (VAL_14_BITS_P (disp))
1455 fprintf (file, "\tstw %d,%d(0,%d)\n", r, disp, base);
1456 else
1457 fprintf (file, "\taddil L'%d,%d\n\tstw %d,R'%d(0,1)\n", disp, base,
1458 r, disp);
1459}
1460
1461void
1462print_ldw (file, r, disp, base)
1463 FILE *file;
1464 int r, disp, base;
1465{
1466 if (VAL_14_BITS_P (disp))
1467 fprintf (file, "\tldw %d(0,%d),%d\n", disp, base, r);
1468 else
1469 fprintf (file, "\taddil L'%d,%d\n\tldw R'%d(0,1),%d\n", disp, base,
1470 disp, r);
1471}
1472
3ddcbb9d 1473/* Global variables set by FUNCTION_PROLOGUE. */
1474/* Size of frame. Need to know this to emit return insns from
1475 leaf procedures. */
a1ab4fa3 1476static int actual_fsize;
1477static int local_fsize, save_fregs;
3ddcbb9d 1478
87ad11b0 1479int
a1ab4fa3 1480compute_frame_size (size, fregs_live)
87ad11b0 1481 int size;
3ddcbb9d 1482 int *fregs_live;
87ad11b0 1483{
1484 extern int current_function_outgoing_args_size;
a1ab4fa3 1485 int i, fsize;
87ad11b0 1486
a1ab4fa3 1487 /* 8 is space for frame pointer + filler. If any frame is allocated
1488 we need to add this in because of STARTING_FRAME_OFFSET. */
1489 fsize = size + (size || frame_pointer_needed ? 8 : 0);
87ad11b0 1490
1491 /* fp is stored in a special place. */
1492 for (i = 18; i >= 5; i--)
1493 if (regs_ever_live[i])
a1ab4fa3 1494 fsize += 4;
87ad11b0 1495
1496 if (regs_ever_live[3])
a1ab4fa3 1497 fsize += 4;
1498 fsize = (fsize + 7) & ~7;
87ad11b0 1499
1500 if (!TARGET_SNAKE)
1501 {
1502 for (i = 47; i >= 44; i--)
1503 if (regs_ever_live[i])
1504 {
a1ab4fa3 1505 fsize += 8;
3ddcbb9d 1506 if (fregs_live)
1507 *fregs_live = 1;
87ad11b0 1508 }
1509 }
1510 else
1511 {
1512 for (i = 90; i >= 72; i -= 2)
1513 if (regs_ever_live[i] || regs_ever_live[i + 1])
1514 {
a1ab4fa3 1515 fsize += 8;
3ddcbb9d 1516 if (fregs_live)
1517 *fregs_live = 1;
87ad11b0 1518 }
1519 }
a1ab4fa3 1520 fsize += current_function_outgoing_args_size;
1521 if (! leaf_function_p () || fsize)
1522 fsize += 32;
1523 return TARGET_SNAKE ? (fsize + 63 & ~63) : fsize;
87ad11b0 1524}
1525
1526void
a1ab4fa3 1527output_function_prologue (file, size)
87ad11b0 1528 FILE *file;
1529 int size;
87ad11b0 1530{
1531 extern char call_used_regs[];
1532 extern int frame_pointer_needed;
d6f01525 1533 extern int current_function_returns_struct;
87ad11b0 1534 int i, offset;
1535
3ddcbb9d 1536 save_fregs = 0;
a1ab4fa3 1537 local_fsize = size + (size || frame_pointer_needed ? 8 : 0);
1538 actual_fsize = compute_frame_size (size, &save_fregs);
87ad11b0 1539
1540 /* Let's not try to bullshit more than we need to here. */
1541 /* This might be right a lot of the time */
1542 fprintf (file, "\t.PROC\n\t.CALLINFO FRAME=%d", actual_fsize);
83071196 1543 if (regs_ever_live[2] || profile_flag)
87ad11b0 1544 fprintf (file, ",CALLS,SAVE_RP\n");
1545 else
1546 fprintf (file, ",NO_CALLS\n");
1547 fprintf (file, "\t.ENTRY\n");
1548
87ad11b0 1549 /* Some registers have places to go in the current stack
1550 structure. */
1551
372ef038 1552 if (regs_ever_live[2] || profile_flag)
87ad11b0 1553 fprintf (file, "\tstw 2,-20(0,30)\n");
1554
1555 /* Reserve space for local variables. */
a1ab4fa3 1556 if (actual_fsize)
1557 if (frame_pointer_needed)
1558 {
1559 if (VAL_14_BITS_P (actual_fsize))
1560 fprintf (file, "\tcopy 4,1\n\tcopy 30,4\n\tstwm 1,%d(0,30)\n",
1561 actual_fsize);
1562 else
1563 {
1564 fprintf (file, "\tcopy 4,1\n\tcopy 30,4\n\tstw 1,0(0,4)\n");
1565 fprintf (file, "\taddil L'%d,30\n\tldo R'%d(1),30\n",
1566 actual_fsize, actual_fsize);
1567 }
1568 }
1569 else
1570 /* Used to be abort (); */
1571 {
1572 if (VAL_14_BITS_P (actual_fsize))
1573 fprintf (file, "\tldo %d(30),30\n", actual_fsize);
1574 else
87ad11b0 1575 fprintf (file, "\taddil L'%d,30\n\tldo R'%d(1),30\n",
1576 actual_fsize, actual_fsize);
a1ab4fa3 1577 }
d6f01525 1578 /* The hppa calling conventions say that that %r19, the pic offset
1579 register, is saved at sp - 32 (in this function's frame) */
1580 if (flag_pic)
1581 {
1582 fprintf (file, "\tstw %%r19,-32(%%r30)\n");
1583 }
372ef038 1584 /* Instead of taking one argument, the counter label, as most normal
1585 mcounts do, _mcount appears to behave differently on the HPPA. It
1586 takes the return address of the caller, the address of this
1587 routine, and the address of the label. Also, it isn't magic, so
1588 argument registers have to be preserved. */
1589
1590 if (profile_flag)
1591 {
1592 unsigned int pc_offset =
1593 (4 + (frame_pointer_needed
1594 ? (VAL_14_BITS_P (actual_fsize) ? 12 : 20)
1595 : (VAL_14_BITS_P (actual_fsize) ? 4 : 8)));
1596 int i, arg_offset;
d2daf090 1597 int basereg, offsetadj;
372ef038 1598
d2daf090 1599 /* When the function has a frame pointer, use that as the base
1600 register for saving/restoring registers. Else use the stack
1601 pointer. Adjust the offset according to the frame size if this
1602 function does not have a frame pointer. */
1603
1604 basereg = frame_pointer_needed ? FRAME_POINTER_REGNUM
1605 : STACK_POINTER_REGNUM;
1606 offsetadj = frame_pointer_needed ? 0 : actual_fsize;
1607
d6f01525 1608 if (current_function_returns_struct)
1609 print_stw (file, STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg);
d2daf090 1610 for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4)
372ef038 1611 if (regs_ever_live[i])
1612 {
d2daf090 1613 print_stw (file, i, arg_offset, basereg);
1614 /* It is possible for the arg_offset not to fit in 14 bits
1615 when profiling a function without a frame pointer. Deal
1616 with such cases. */
1617 pc_offset += VAL_14_BITS_P (arg_offset) ? 4 : 8;
372ef038 1618 }
1619 fprintf (file,
1620 "\tcopy %%r2,%%r26\n\taddil L'LP$%04d-$global$,%%r27\n\
1621\tldo R'LP$%04d-$global$(%%r1),%%r24\n\tbl _mcount,%%r2\n\
1622\tldo %d(%%r2),%%r25\n",
1623 hp_profile_labelno, hp_profile_labelno, -pc_offset - 12 - 8);
d2daf090 1624 for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4)
372ef038 1625 if (regs_ever_live[i])
d2daf090 1626 print_ldw (file, i, arg_offset, basereg);
d6f01525 1627 if (current_function_returns_struct)
1628 print_ldw (file, STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg);
372ef038 1629 }
1630
87ad11b0 1631 /* Normal register save. */
1632 if (frame_pointer_needed)
1633 {
1634 for (i = 18, offset = local_fsize; i >= 5; i--)
1635 if (regs_ever_live[i] && ! call_used_regs[i])
1636 {
1637 print_stw (file, i, offset, 4); offset += 4;
1638 }
1639 if (regs_ever_live[3] && ! call_used_regs[3])
1640 {
1641 print_stw (file, 3, offset, 4); offset += 4;
1642 }
1643 }
1644 else
1645 {
1646 for (i = 18, offset = local_fsize - actual_fsize; i >= 5; i--)
1647 if (regs_ever_live[i] && ! call_used_regs[i])
1648 {
1649 print_stw (file, i, offset, 30); offset += 4;
1650 }
1651 if (regs_ever_live[3] && ! call_used_regs[3])
1652 {
1653 print_stw (file, 3, offset, 30); offset += 4;
1654 }
1655 }
1656
1657 /* Align pointer properly (doubleword boundary). */
1658 offset = (offset + 7) & ~7;
1659
1660 /* Floating point register store. */
1661 if (save_fregs)
87ad11b0 1662 {
a1ab4fa3 1663 if (frame_pointer_needed)
87ad11b0 1664 {
a1ab4fa3 1665 if (VAL_14_BITS_P (offset))
1666 fprintf (file, "\tldo %d(4),1\n", offset);
1667 else
1668 fprintf (file, "\taddil L'%d,4\n\tldo R'%d(1),1\n",
1669 offset, offset);
1670 }
1671 else
1672 {
1673 if (VAL_14_BITS_P (offset))
1674 fprintf (file, "\tldo %d(30),1\n", offset);
1675 else
1676 fprintf (file, "\taddil L'%d,30\n\tldo R'%d(1),1\n",
1677 offset, offset);
1678 }
1679 if (!TARGET_SNAKE)
1680 {
1681 for (i = 47; i >= 44; i--)
1682 {
1683 if (regs_ever_live[i])
1684 fprintf (file, "\tfstds,ma %s,8(0,1)\n", reg_names[i]);
1685 }
1686 }
1687 else
1688 {
1689 for (i = 90; i >= 72; i -= 2)
1690 if (regs_ever_live[i] || regs_ever_live[i + 1])
1691 {
1692 fprintf (file, "\tfstds,ma %s,8(0,1)\n", reg_names[i]);
1693 }
87ad11b0 1694 }
87ad11b0 1695 }
1696}
1697
1698void
a1ab4fa3 1699output_function_epilogue (file, size)
87ad11b0 1700 FILE *file;
1701 int size;
87ad11b0 1702{
1703 extern char call_used_regs[];
1704 extern int frame_pointer_needed;
1705 int i, offset;
1706
1707 if (frame_pointer_needed)
1708 {
1709 for (i = 18, offset = local_fsize; i >= 5; i--)
1710 if (regs_ever_live[i] && ! call_used_regs[i])
1711 {
1712 print_ldw (file, i, offset, 4); offset += 4;
1713 }
1714 if (regs_ever_live[3] && ! call_used_regs[3])
1715 {
1716 print_ldw (file, 3, offset, 4); offset += 4;
1717 }
1718 }
1719 else
1720 {
1721 for (i = 18, offset = local_fsize - actual_fsize; i >= 5; i--)
1722 if (regs_ever_live[i] && ! call_used_regs[i])
1723 {
1724 print_ldw (file, i, offset, 30); offset += 4;
1725 }
1726 if (regs_ever_live[3] && ! call_used_regs[3])
1727 {
1728 print_ldw (file, 3, offset, 30); offset += 4;
1729 }
1730 }
1731
1732 /* Align pointer properly (doubleword boundary). */
1733 offset = (offset + 7) & ~7;
1734
1735 /* Floating point register restore. */
1736 if (save_fregs)
87ad11b0 1737 {
a1ab4fa3 1738 if (frame_pointer_needed)
87ad11b0 1739 {
a1ab4fa3 1740 if (VAL_14_BITS_P (offset))
1741 fprintf (file, "\tldo %d(4),1\n", offset);
1742 else
1743 fprintf (file, "\taddil L'%d,4\n\tldo R'%d(1),1\n",
1744 offset, offset);
1745 }
1746 else
1747 {
1748 if (VAL_14_BITS_P (offset))
1749 fprintf (file, "\tldo %d(30),1\n", offset);
1750 else
1751 fprintf (file, "\taddil L'%d,30\n\tldo R'%d(1),1\n",
1752 offset, offset);
1753 }
1754 if (!TARGET_SNAKE)
1755 {
1756 for (i = 47; i >= 44; i--)
1757 {
1758 if (regs_ever_live[i])
1759 fprintf (file, "\tfldds,ma 8(0,1),%s\n", reg_names[i]);
1760 }
1761 }
1762 else
1763 {
1764 for (i = 90; i >= 72; i -= 2)
1765 if (regs_ever_live[i] || regs_ever_live[i + 1])
1766 {
1767 fprintf (file, "\tfldds,ma 8(0,1),%s\n", reg_names[i]);
1768 }
87ad11b0 1769 }
87ad11b0 1770 }
1771 /* Reset stack pointer (and possibly frame pointer). The stack */
a1ab4fa3 1772 /* pointer is initially set to fp + 64 to avoid a race condition. */
87ad11b0 1773 if (frame_pointer_needed)
1774 {
a1ab4fa3 1775 fprintf (file, "\tldo 64(%%r4),%%r30\n");
83071196 1776 if (regs_ever_live[2] || profile_flag)
a1ab4fa3 1777 fprintf (file, "\tldw -84(%%r30),%%r2\n");
1778 fprintf (file, "\tbv 0(%%r2)\n\tldwm -64(%%r30),4\n");
87ad11b0 1779 }
1780 else if (actual_fsize)
1781 {
a1ab4fa3 1782 if (regs_ever_live[2] || profile_flag)
1783
1784 {
1785 if (VAL_14_BITS_P (actual_fsize + 20))
1786 fprintf (file, "\tldw %d(30),2\n\tbv 0(2)\n\tldo %d(30),30\n",
1787 -(actual_fsize + 20), -actual_fsize);
1788 else
1789 fprintf (file,
1790 "\taddil L'%d,30\n\tldw %d(1),2\n\tbv 0(2)\n\
1791\tldo R'%d(1),30\n",
1792 - actual_fsize,
1793 - (actual_fsize + 20 + ((-actual_fsize) & ~0x7ff)),
1794 - actual_fsize);
1795 }
87ad11b0 1796 else if (VAL_14_BITS_P (actual_fsize))
1797 fprintf (file, "\tbv 0(2)\n\tldo %d(30),30\n", - actual_fsize);
1798 else
a1ab4fa3 1799 fprintf (file, "\taddil L'%d,30\n\tbv 0(2)\n\tldo R'%d(1),30\n",
1800 - actual_fsize, - actual_fsize);
87ad11b0 1801 }
1802 else if (current_function_epilogue_delay_list)
1803 {
1804 fprintf (file, "\tbv 0(2)\n");
a1ab4fa3 1805 final_scan_insn (XEXP (current_function_epilogue_delay_list, 0), file,
1806 1, 0, 1);
87ad11b0 1807 }
1808 else
1809 fprintf (file, "\tbv,n 0(2)\n");
1810 fprintf (file, "\t.EXIT\n\t.PROCEND\n");
1811}
1812
1813rtx
1814gen_compare_reg (code, x, y)
1815 enum rtx_code code;
1816 rtx x, y;
1817{
fda4fc2e 1818 enum machine_mode mode = SELECT_CC_MODE (code, x, y);
87ad11b0 1819 rtx cc_reg = gen_rtx (REG, mode, 0);
1820
1821 emit_insn (gen_rtx (SET, VOIDmode, cc_reg,
1822 gen_rtx (COMPARE, mode, x, y)));
1823
1824 return cc_reg;
1825}
1826
a1ab4fa3 1827/* If there's a frame, it will be deallocated in the delay slot of the
1828 bv 0(2) return instruction. */
1829
1830int
1831hppa_epilogue_delay_slots ()
1832{
1833 return (compute_frame_size (get_frame_size (), 0) ? 0 : 1);
1834}
1835
87ad11b0 1836/* Return nonzero if TRIAL can go into the function epilogue's
1837 delay slot. SLOT is the slot we are trying to fill. */
1838
1839int
1840eligible_for_epilogue_delay (trial, slot)
1841 rtx trial;
1842 int slot;
1843{
1844 if (slot >= 1)
1845 return 0;
1846 if (GET_CODE (trial) != INSN
1847 || GET_CODE (PATTERN (trial)) != SET)
1848 return 0;
1849 if (get_attr_length (trial) != 1)
1850 return 0;
a1ab4fa3 1851 return (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_TRUE);
87ad11b0 1852}
1853
1854rtx
1855gen_scond_fp (code, operand0)
1856 enum rtx_code code;
1857 rtx operand0;
1858{
1859 return gen_rtx (SET, VOIDmode, operand0,
1860 gen_rtx (code, CCFPmode,
1861 gen_rtx (REG, CCFPmode, 0), const0_rtx));
1862}
1863
1864void
1865emit_bcond_fp (code, operand0)
1866 enum rtx_code code;
1867 rtx operand0;
1868{
1869 emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
1870 gen_rtx (IF_THEN_ELSE, VOIDmode,
1871 gen_rtx (code, VOIDmode,
1872 gen_rtx (REG, CCFPmode, 0),
1873 const0_rtx),
1874 gen_rtx (LABEL_REF, VOIDmode, operand0),
1875 pc_rtx)));
1876
1877}
1878
1879rtx
1880gen_cmp_fp (code, operand0, operand1)
1881 enum rtx_code code;
1882 rtx operand0, operand1;
1883{
1884 return gen_rtx (SET, VOIDmode, gen_rtx (REG, CCFPmode, 0),
1885 gen_rtx (code, CCFPmode, operand0, operand1));
1886}
1887
1888
1889/* Print operand X (an rtx) in assembler syntax to file FILE.
1890 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
1891 For `%' followed by punctuation, CODE is the punctuation and X is null. */
1892
1893void
1894print_operand (file, x, code)
1895 FILE *file;
1896 rtx x;
1897 int code;
1898{
1899 switch (code)
1900 {
1901 case '#':
1902 /* Output a 'nop' if there's nothing for the delay slot. */
1903 if (dbr_sequence_length () == 0)
1904 fputs ("\n\tnop", file);
1905 return;
1906 case '*':
1907 /* Output an nullification completer if there's nothing for the */
1908 /* delay slot or nullification is requested. */
1909 if (dbr_sequence_length () == 0 ||
1910 (final_sequence &&
1911 INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))))
1912 fputs (",n", file);
1913 return;
1914 case 'R':
1915 /* Print out the second register name of a register pair.
1916 I.e., R (6) => 7. */
1917 fputs (reg_names[REGNO (x)+1], file);
1918 return;
1919 case 'r':
1920 /* A register or zero. */
1921 if (x == const0_rtx)
1922 {
1923 fputs ("0", file);
1924 return;
1925 }
1926 else
1927 break;
1928 case 'O':
1929 switch (GET_CODE (x))
1930 {
1931 case PLUS:
1932 fprintf (file, "add%s",
1933 GET_CODE (XEXP (x, 1)) == CONST_INT ? "i" : ""); break;
1934 case MINUS:
1935 fprintf (file, "sub%s",
1936 GET_CODE (XEXP (x, 0)) == CONST_INT ? "i" : ""); break;
1937 case AND:
1938 fprintf (file, "and%s",
1939 GET_CODE (XEXP (x, 1)) == NOT ? "cm" : ""); break;
1940 case IOR:
1941 fprintf (file, "or"); break;
1942 case XOR:
1943 fprintf (file, "xor"); break;
1944 case ASHIFT:
1945 fprintf (file, "sh%dadd", INTVAL (XEXP (x, 1))); break;
1946 /* Too lazy to handle bitfield conditions yet. */
1947 default:
1948 printf ("Can't grok '%c' operator:\n", code);
1949 debug_rtx (x);
1950 abort ();
1951 }
1952 return;
1953 case 'C':
1954 case 'X':
1955 switch (GET_CODE (x))
1956 {
1957 case EQ:
1958 fprintf (file, "="); break;
1959 case NE:
9d887bf4 1960 fprintf (file, "<>"); break;
87ad11b0 1961 case GT:
1962 fprintf (file, ">"); break;
1963 case GE:
1964 fprintf (file, ">="); break;
1965 case GEU:
1966 fprintf (file, ">>="); break;
1967 case GTU:
1968 fprintf (file, ">>"); break;
1969 case LT:
1970 fprintf (file, "<"); break;
1971 case LE:
1972 fprintf (file, "<="); break;
1973 case LEU:
1974 fprintf (file, "<<="); break;
1975 case LTU:
1976 fprintf (file, "<<"); break;
1977 default:
1978 printf ("Can't grok '%c' operator:\n", code);
1979 debug_rtx (x);
1980 abort ();
1981 }
1982 return;
1983 case 'N':
1984 case 'Y':
1985 switch (GET_CODE (x))
1986 {
1987 case EQ:
9d887bf4 1988 fprintf (file, "<>"); break;
87ad11b0 1989 case NE:
1990 fprintf (file, "="); break;
1991 case GT:
1992 fprintf (file, "<="); break;
1993 case GE:
1994 fprintf (file, "<"); break;
1995 case GEU:
1996 fprintf (file, "<<"); break;
1997 case GTU:
1998 fprintf (file, "<<="); break;
1999 case LT:
2000 fprintf (file, ">="); break;
2001 case LE:
2002 fprintf (file, ">"); break;
2003 case LEU:
2004 fprintf (file, ">>"); break;
2005 case LTU:
2006 fprintf (file, ">>="); break;
2007 default:
2008 printf ("Can't grok '%c' operator:\n", code);
2009 debug_rtx (x);
2010 abort ();
2011 }
2012 return;
2013 case 'M':
2014 switch (GET_CODE (XEXP (x, 0)))
2015 {
2016 case PRE_DEC:
2017 case PRE_INC:
2018 fprintf (file, "s,mb");
2019 break;
2020 case POST_DEC:
2021 case POST_INC:
2022 fprintf (file, "s,ma");
2023 break;
2024 default:
2025 break;
2026 }
2027 return;
2028 case 'F':
2029 switch (GET_CODE (XEXP (x, 0)))
2030 {
2031 case PRE_DEC:
2032 case PRE_INC:
2033 fprintf (file, ",mb");
2034 break;
2035 case POST_DEC:
2036 case POST_INC:
2037 fprintf (file, ",ma");
2038 break;
2039 default:
2040 break;
2041 }
2042 return;
2043 case 'G':
2044 output_global_address (file, x);
2045 return;
2046 case 0: /* Don't do anything special */
2047 break;
2048 default:
2049 abort ();
2050 }
2051 if (GET_CODE (x) == REG)
2052 fprintf (file, "%s", reg_names [REGNO (x)]);
2053 else if (GET_CODE (x) == MEM)
2054 {
2055 int size = GET_MODE_SIZE (GET_MODE (x));
2056 rtx base = XEXP (XEXP (x, 0), 0);
2057 switch (GET_CODE (XEXP (x, 0)))
2058 {
2059 case PRE_DEC:
2060 case POST_DEC:
2061 fprintf (file, "-%d(0,%s)", size, reg_names [REGNO (base)]);
2062 break;
2063 case PRE_INC:
2064 case POST_INC:
2065 fprintf (file, "%d(0,%s)", size, reg_names [REGNO (base)]);
2066 break;
2067 default:
2068 output_address (XEXP (x, 0));
2069 break;
2070 }
2071 }
2072 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
2073 {
2074 union { double d; int i[2]; } u;
2075 union { float f; int i; } u1;
2076 u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1);
2077 u1.f = u.d;
2078 if (code == 'f')
2079 fprintf (file, "0r%.9g", u1.f);
2080 else
2081 fprintf (file, "0x%x", u1.i);
2082 }
2083 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != DImode)
2084 {
2085 union { double d; int i[2]; } u;
2086 u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1);
2087 fprintf (file, "0r%.20g", u.d);
2088 }
2089 else
2090 output_addr_const (file, x);
2091}
2092
2093/* output a SYMBOL_REF or a CONST expression involving a SYMBOL_REF. */
2094
2095void
2096output_global_address (file, x)
2097 FILE *file;
2098 rtx x;
2099{
2100 if (GET_CODE (x) == SYMBOL_REF && read_only_operand (x))
2101 assemble_name (file, XSTR (x, 0));
2102 else if (GET_CODE (x) == SYMBOL_REF)
2103 {
2104 assemble_name (file, XSTR (x, 0));
2105 fprintf (file, "-$global$");
2106 }
2107 else if (GET_CODE (x) == CONST)
2108 {
2109 char *sep = "";
2110 int offset = 0; /* assembler wants -$global$ at end */
2111 rtx base;
2112
2113 if (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
2114 {
2115 base = XEXP (XEXP (x, 0), 0);
2116 output_addr_const (file, base);
2117 }
2118 else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == CONST_INT)
2119 offset = INTVAL (XEXP (XEXP (x, 0), 0));
2120 else abort ();
2121
2122 if (GET_CODE (XEXP (XEXP (x, 0), 1)) == SYMBOL_REF)
2123 {
2124 base = XEXP (XEXP (x, 0), 1);
2125 output_addr_const (file, base);
2126 }
2127 else if (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2128 offset = INTVAL (XEXP (XEXP (x, 0),1));
2129 else abort ();
2130
2131 if (GET_CODE (XEXP (x, 0)) == PLUS)
2132 {
2133 if (offset < 0)
2134 {
2135 offset = -offset;
2136 sep = "-";
2137 }
2138 else
2139 sep = "+";
2140 }
2141 else if (GET_CODE (XEXP (x, 0)) == MINUS
2142 && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))
2143 sep = "-";
2144 else abort ();
2145
2146 if (!read_only_operand (base))
2147 fprintf (file, "-$global$");
2148 fprintf (file, "%s", sep);
2149 if (offset) fprintf (file,"%d", offset);
2150 }
2151 else
2152 output_addr_const (file, x);
2153}
2154
87ad11b0 2155enum rtx_code
2156reverse_relop (code)
2157 enum rtx_code code;
2158{
2159 switch (code)
2160 {
2161 case GT:
2162 return LT;
2163 case LT:
2164 return GT;
2165 case GE:
2166 return LE;
2167 case LE:
2168 return GE;
2169 case LTU:
2170 return GTU;
2171 case GTU:
2172 return LTU;
2173 case GEU:
2174 return LEU;
2175 case LEU:
2176 return GEU;
2177 default:
2178 abort ();
2179 }
2180}
2181
2182/* HP's millicode routines mean something special to the assembler.
2183 Keep track of which ones we have used. */
2184
2185enum millicodes { remI, remU, divI, divU, mulI, mulU, end1000 };
2186static char imported[(int)end1000];
2187static char *milli_names[] = {"remI", "remU", "divI", "divU", "mulI", "mulU"};
2188static char import_string[] = ".IMPORT $$....,MILLICODE";
2189#define MILLI_START 10
2190
2191static int
2192import_milli (code)
2193 enum millicodes code;
2194{
2195 char str[sizeof (import_string)];
2196
2197 if (!imported[(int)code])
2198 {
2199 imported[(int)code] = 1;
2200 strcpy (str, import_string);
2201 strncpy (str + MILLI_START, milli_names[(int)code], 4);
2202 output_asm_insn (str, 0);
2203 }
2204}
2205
2206/* The register constraints have put the operands and return value in
2207 the proper registers. */
2208
2209char *
2210output_mul_insn (unsignedp)
2211 int unsignedp;
2212{
2213 if (unsignedp)
2214 {
2215 import_milli (mulU);
d2daf090 2216 return "bl $$mulU,31%#";
87ad11b0 2217 }
2218 else
2219 {
2220 import_milli (mulI);
d2daf090 2221 return "bl $$mulI,31%#";
87ad11b0 2222 }
2223}
2224
2225/* If operands isn't NULL, then it's a CONST_INT with which we can do
2226 something */
2227
2228
2229/* Emit the rtl for doing a division by a constant. */
2230
2231 /* Do magic division millicodes exist for this value? */
2232
2233static int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
2234 1, 1};
2235
2236/* We'll use an array to keep track of the magic millicodes and
2237 whether or not we've used them already. [n][0] is signed, [n][1] is
2238 unsigned. */
2239
87ad11b0 2240static int div_milli[16][2];
2241
2242int
2243div_operand (op, mode)
2244 rtx op;
2245 enum machine_mode mode;
2246{
2247 return (mode == SImode
2248 && ((GET_CODE (op) == REG && REGNO (op) == 25)
2249 || (GET_CODE (op) == CONST_INT && INTVAL (op) > 0
2250 && INTVAL (op) < 16 && magic_milli[INTVAL (op)])));
2251}
2252
2253int
2254emit_hpdiv_const (operands, unsignedp)
2255 rtx *operands;
2256 int unsignedp;
2257{
2258 if (GET_CODE (operands[2]) == CONST_INT
2259 && INTVAL (operands[2]) > 0
2260 && INTVAL (operands[2]) < 16
2261 && magic_milli[INTVAL (operands[2])])
2262 {
2263 emit_move_insn ( gen_rtx (REG, SImode, 26), operands[1]);
2264 emit
2265 (gen_rtx
2266 (PARALLEL, VOIDmode,
2267 gen_rtvec (5, gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 29),
2268 gen_rtx (unsignedp ? UDIV : DIV, SImode,
2269 gen_rtx (REG, SImode, 26),
2270 operands[2])),
33bd7237 2271 gen_rtx (CLOBBER, VOIDmode, operands[3]),
87ad11b0 2272 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 26)),
2273 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 25)),
2274 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 31)))));
2275 emit_move_insn (operands[0], gen_rtx (REG, SImode, 29));
2276 return 1;
2277 }
2278 return 0;
2279}
2280
2281char *
2282output_div_insn (operands, unsignedp)
2283 rtx *operands;
2284 int unsignedp;
2285{
2286 int divisor;
2287
2288 /* If the divisor is a constant, try to use one of the special
2289 opcodes .*/
2290 if (GET_CODE (operands[0]) == CONST_INT)
2291 {
2292 divisor = INTVAL (operands[0]);
2293 if (!div_milli[divisor][unsignedp])
2294 {
2295 if (unsignedp)
2296 output_asm_insn (".IMPORT $$divU_%0,MILLICODE", operands);
2297 else
2298 output_asm_insn (".IMPORT $$divI_%0,MILLICODE", operands);
2299 div_milli[divisor][unsignedp] = 1;
2300 }
2301 if (unsignedp)
2302 return "bl $$divU_%0,31%#";
2303 return "bl $$divI_%0,31%#";
2304 }
2305 /* Divisor isn't a special constant. */
2306 else
2307 {
2308 if (unsignedp)
2309 {
2310 import_milli (divU);
2311 return "bl $$divU,31%#";
2312 }
2313 else
2314 {
2315 import_milli (divI);
2316 return "bl $$divI,31%#";
2317 }
2318 }
2319}
2320
2321/* Output a $$rem millicode to do mod. */
2322
2323char *
2324output_mod_insn (unsignedp)
2325 int unsignedp;
2326{
2327 if (unsignedp)
2328 {
2329 import_milli (remU);
2330 return "bl $$remU,31%#";
2331 }
2332 else
2333 {
2334 import_milli (remI);
2335 return "bl $$remI,31%#";
2336 }
2337}
2338
2339void
2340output_arg_descriptor (insn)
2341 rtx insn;
2342{
2343 char *arg_regs[4];
2344 enum machine_mode arg_mode;
2345 rtx prev_insn;
2346 int i, output_flag = 0;
2347 int regno;
2348
2349 for (i = 0; i < 4; i++)
2350 arg_regs[i] = 0;
2351
2352 for (prev_insn = PREV_INSN (insn); GET_CODE (prev_insn) == INSN;
2353 prev_insn = PREV_INSN (prev_insn))
2354 {
2355 if (!(GET_CODE (PATTERN (prev_insn)) == USE &&
2356 GET_CODE (XEXP (PATTERN (prev_insn), 0)) == REG &&
2357 FUNCTION_ARG_REGNO_P (REGNO (XEXP (PATTERN (prev_insn), 0)))))
2358 break;
2359 arg_mode = GET_MODE (XEXP (PATTERN (prev_insn), 0));
2360 regno = REGNO (XEXP (PATTERN (prev_insn), 0));
2361 if (regno >= 23 && regno <= 26)
372ef038 2362 {
2363 arg_regs[26 - regno] = "GR";
2364 if (arg_mode == DImode)
2365 arg_regs[25 - regno] = "GR";
2366 }
87ad11b0 2367 else if (!TARGET_SNAKE) /* fp args */
2368 {
2369 if (arg_mode == SFmode)
2370 arg_regs[regno - 36] = "FR";
2371 else
2372 {
2373#ifdef HP_FP_ARG_DESCRIPTOR_REVERSED
2374 arg_regs[regno - 37] = "FR";
2375 arg_regs[regno - 36] = "FU";
2376#else
2377 arg_regs[regno - 37] = "FU";
2378 arg_regs[regno - 36] = "FR";
2379#endif
2380 }
2381 }
2382 else
2383 {
2384 if (arg_mode == SFmode)
2385 arg_regs[(regno - 56) / 2] = "FR";
2386 else
2387 {
2388#ifdef HP_FP_ARG_DESCRIPTOR_REVERSED
2389 arg_regs[(regno - 58) / 2] = "FR";
2390 arg_regs[(regno - 58) / 2 + 1] = "FU";
2391#else
2392 arg_regs[(regno - 58) / 2] = "FU";
2393 arg_regs[(regno - 58) / 2 + 1] = "FR";
2394#endif
2395 }
2396 }
2397 }
2398 fputs ("\t.CALL ", asm_out_file);
2399 for (i = 0; i < 4; i++)
2400 {
2401 if (arg_regs[i])
2402 {
2403 if (output_flag++)
2404 fputc (',', asm_out_file);
2405 fprintf (asm_out_file, "ARGW%d=%s", i, arg_regs[i]);
2406 }
2407 }
2408 fputc ('\n', asm_out_file);
2409}
2410\f
d2c1d63d 2411/* Memory loads/stores to/from the shift need to go through
2412 the general registers. */
87ad11b0 2413
2414enum reg_class
2415secondary_reload_class (class, mode, in)
2416 enum reg_class class;
2417 enum machine_mode mode;
2418 rtx in;
2419{
2420 int regno = true_regnum (in);
2421
d6f01525 2422 if ((TARGET_SHARED_LIBS && function_label_operand (in, mode))
2423 || ((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
2424 && ((mode == QImode || mode == HImode || mode == SImode
2425 || mode == DImode)
2426 && (class == FP_REGS || class == SNAKE_FP_REGS
2427 || class == HI_SNAKE_FP_REGS)))
2428 || (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
9c6d4825 2429 return GENERAL_REGS;
d2c1d63d 2430
2431 return NO_REGS;
87ad11b0 2432}
2433
2434enum direction
2435function_arg_padding (mode, type)
2436 enum machine_mode mode;
2437 tree type;
2438{
2439 int size;
2440
2441 if (mode == BLKmode)
2442 {
2443 if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
2444 size = int_size_in_bytes (type) * BITS_PER_UNIT;
2445 else
2446 return upward; /* Don't know if this is right, but */
2447 /* same as old definition. */
2448 }
2449 else
2450 size = GET_MODE_BITSIZE (mode);
2451 if (size < PARM_BOUNDARY)
2452 return downward;
2453 else if (size % PARM_BOUNDARY)
2454 return upward;
2455 else
2456 return none;
2457}
2458
87ad11b0 2459\f
2460/* Do what is necessary for `va_start'. The argument is ignored;
2461 We look at the current function to determine if stdargs or varargs
2462 is used and fill in an initial va_list. A pointer to this constructor
2463 is returned. */
2464
2465struct rtx_def *
2466hppa_builtin_saveregs (arglist)
2467 tree arglist;
2468{
2469 rtx block, float_addr, offset, float_mem;
2470 tree fntype = TREE_TYPE (current_function_decl);
2471 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2472 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2473 != void_type_node)))
2474 ? UNITS_PER_WORD : 0);
2475
2476 if (argadj)
2477 offset = plus_constant (current_function_arg_offset_rtx, argadj);
2478 else
2479 offset = current_function_arg_offset_rtx;
9c6d4825 2480
87ad11b0 2481 /* Store general registers on the stack. */
2482 move_block_from_reg (23,
2483 gen_rtx (MEM, BLKmode,
2484 plus_constant
2485 (current_function_internal_arg_pointer, -16)),
2486 4);
9c6d4825 2487 return copy_to_reg (expand_binop (Pmode, add_optab,
2488 current_function_internal_arg_pointer,
2489 offset, 0, 0, OPTAB_LIB_WIDEN));
87ad11b0 2490}
d6f01525 2491
2492extern struct obstack *saveable_obstack;
2493
2494/* In HPUX 8.0's shared library scheme, special relocations are needed
2495 for function labels if they might be passed to a function
2496 in a shared library (because shared libraries don't live in code
2497 space), and special magic is needed to construct their address. */
2498
2499void
2500hppa_encode_label (sym)
2501 rtx sym;
2502{
2503 char *str = XSTR (sym, 0);
2504 int len = strlen (str);
2505 char *newstr = obstack_alloc (saveable_obstack, len + 2) ;
2506
c1b3411e 2507 if (str[0] == '*')
2508 *newstr++ = *str++;
d6f01525 2509 strcpy (newstr + 1, str);
c1b3411e 2510 *newstr = '@';
d6f01525 2511 XSTR (sym,0) = newstr;
2512}
2513
2514int
2515function_label_operand (op, mode)
2516 rtx op;
2517 enum machine_mode mode;
2518{
c1b3411e 2519 return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0));
d6f01525 2520}
f33e3942 2521
37580c80 2522/* Returns 1 if the 6 operands specified in OPERANDS are suitable for
2523 use in fmpyadd instructions. */
4ed6ee50 2524int
2525fmpyaddoperands(operands)
2526 rtx *operands;
2527{
2528
2529 /* All modes must be the same. */
2530 if (! (GET_MODE (operands[0]) == GET_MODE (operands[1])
2531 && GET_MODE (operands[0]) == GET_MODE (operands[2])
2532 && GET_MODE (operands[0]) == GET_MODE (operands[3])
2533 && GET_MODE (operands[0]) == GET_MODE (operands[4])
2534 && GET_MODE (operands[0]) == GET_MODE (operands[5])))
2535 return 0;
2536
2537 /* Both DFmode and SFmode should work. But using SFmode makes the
2538 assembler complain. Just turn it off for now. */
2539 if (GET_MODE (operands[0]) != DFmode)
2540 return 0;
2541
37580c80 2542 /* Only 2 real operands to the addition. One of the input operands must
2543 be the same as the output operand. */
4ed6ee50 2544 if (! rtx_equal_p (operands[3], operands[4])
2545 && ! rtx_equal_p (operands[3], operands[5]))
2546 return 0;
2547
2548 /* Inout operand of add can not conflict with any operands from multiply. */
2549 if (rtx_equal_p (operands[3], operands[0])
2550 || rtx_equal_p (operands[3], operands[1])
2551 || rtx_equal_p (operands[3], operands[2]))
2552 return 0;
2553
2554 /* multiply can not feed into addition operands. */
2555 if (rtx_equal_p (operands[4], operands[0])
2556 || rtx_equal_p (operands[5], operands[0]))
2557 return 0;
2558
4ed6ee50 2559 /* Passed. Operands are suitable for fmpyadd. */
2560 return 1;
2561}
2562
37580c80 2563/* Returns 1 if the 6 operands specified in OPERANDS are suitable for
2564 use in fmpysub instructions. */
4ed6ee50 2565int
2566fmpysuboperands(operands)
2567 rtx *operands;
2568{
2569
2570 /* All modes must be the same. */
2571 if (! (GET_MODE (operands[0]) == GET_MODE (operands[1])
2572 && GET_MODE (operands[0]) == GET_MODE (operands[2])
2573 && GET_MODE (operands[0]) == GET_MODE (operands[3])
2574 && GET_MODE (operands[0]) == GET_MODE (operands[4])
2575 && GET_MODE (operands[0]) == GET_MODE (operands[5])))
2576 return 0;
2577
2578 /* Both DFmode and SFmode should work. But using SFmode makes the
2579 assembler complain. Just turn it off for now. */
2580 if (GET_MODE (operands[0]) != DFmode)
2581 return 0;
2582
37580c80 2583 /* Only 2 real operands to the subtraction. Subtraction is not a commutative
2584 operation, so operands[4] must be the same as operand[3]. */
4ed6ee50 2585 if (! rtx_equal_p (operands[3], operands[4]))
2586 return 0;
2587
2588 /* multiply can not feed into subtraction. */
37580c80 2589 if (rtx_equal_p (operands[5], operands[0]))
4ed6ee50 2590 return 0;
2591
37580c80 2592 /* Inout operand of sub can not conflict with any operands from multiply. */
4ed6ee50 2593 if (rtx_equal_p (operands[3], operands[0])
2594 || rtx_equal_p (operands[3], operands[1])
2595 || rtx_equal_p (operands[3], operands[2]))
2596 return 0;
2597
2598 /* Passed. Operands are suitable for fmpysub. */
2599 return 1;
2600}
2601
621b5219 2602
2603/* Return 1 iff OP is a valid operator to use in an incscc
2604 instruction. Adding or subtracting the condition code
2605 to/from another operand is valid on the PA, so return 1
2606 for PLUS or MINUS. */
2607int
2608incscc_operator (op, mode)
2609 rtx op;
2610 enum machine_mode mode;
2611{
2612 return (GET_CODE (op) == PLUS || GET_CODE (op) == MINUS);
2613}
2614
2615
f33e3942 2616/* Return 1 if OP is suitable for the second add operand (the unshifed
2617 operand) in an shadd instruction. Allow CONST_INT to work around
2618 a reload bug. */
2619int
2620shadd_operand (op, mode)
2621 rtx op;
2622 enum machine_mode mode;
2623{
2624 if (GET_CODE (op) == REG)
2625 return 1;
2626 if (GET_CODE (op) == CONST_INT)
2627 return 1;
2628 return 0;
2629}
89f29d73 2630
2631int
2632plus_xor_ior_operator (op, mode)
2633 rtx op;
2634 enum machine_mode mode;
2635{
2636 return (GET_CODE (op) == PLUS || GET_CODE (op) == XOR
2637 || GET_CODE (op) == IOR);
2638}