]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/pa/pa.c
* pa.md (movqi, movhi, movsi, movdi, movsf, movdf): Discourage
[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:
1960 if (code == 'C')
1961 fprintf (file, "<>");
1962 else
1963 fprintf (file, "!=");
1964 break;
1965 case GT:
1966 fprintf (file, ">"); break;
1967 case GE:
1968 fprintf (file, ">="); break;
1969 case GEU:
1970 fprintf (file, ">>="); break;
1971 case GTU:
1972 fprintf (file, ">>"); break;
1973 case LT:
1974 fprintf (file, "<"); break;
1975 case LE:
1976 fprintf (file, "<="); break;
1977 case LEU:
1978 fprintf (file, "<<="); break;
1979 case LTU:
1980 fprintf (file, "<<"); break;
1981 default:
1982 printf ("Can't grok '%c' operator:\n", code);
1983 debug_rtx (x);
1984 abort ();
1985 }
1986 return;
1987 case 'N':
1988 case 'Y':
1989 switch (GET_CODE (x))
1990 {
1991 case EQ:
1992 if (code == 'N')
1993 fprintf (file, "<>");
1994 else
1995 fprintf (file, "!=");
1996 break;
1997 case NE:
1998 fprintf (file, "="); break;
1999 case GT:
2000 fprintf (file, "<="); break;
2001 case GE:
2002 fprintf (file, "<"); break;
2003 case GEU:
2004 fprintf (file, "<<"); break;
2005 case GTU:
2006 fprintf (file, "<<="); break;
2007 case LT:
2008 fprintf (file, ">="); break;
2009 case LE:
2010 fprintf (file, ">"); break;
2011 case LEU:
2012 fprintf (file, ">>"); break;
2013 case LTU:
2014 fprintf (file, ">>="); break;
2015 default:
2016 printf ("Can't grok '%c' operator:\n", code);
2017 debug_rtx (x);
2018 abort ();
2019 }
2020 return;
2021 case 'M':
2022 switch (GET_CODE (XEXP (x, 0)))
2023 {
2024 case PRE_DEC:
2025 case PRE_INC:
2026 fprintf (file, "s,mb");
2027 break;
2028 case POST_DEC:
2029 case POST_INC:
2030 fprintf (file, "s,ma");
2031 break;
2032 default:
2033 break;
2034 }
2035 return;
2036 case 'F':
2037 switch (GET_CODE (XEXP (x, 0)))
2038 {
2039 case PRE_DEC:
2040 case PRE_INC:
2041 fprintf (file, ",mb");
2042 break;
2043 case POST_DEC:
2044 case POST_INC:
2045 fprintf (file, ",ma");
2046 break;
2047 default:
2048 break;
2049 }
2050 return;
2051 case 'G':
2052 output_global_address (file, x);
2053 return;
2054 case 0: /* Don't do anything special */
2055 break;
2056 default:
2057 abort ();
2058 }
2059 if (GET_CODE (x) == REG)
2060 fprintf (file, "%s", reg_names [REGNO (x)]);
2061 else if (GET_CODE (x) == MEM)
2062 {
2063 int size = GET_MODE_SIZE (GET_MODE (x));
2064 rtx base = XEXP (XEXP (x, 0), 0);
2065 switch (GET_CODE (XEXP (x, 0)))
2066 {
2067 case PRE_DEC:
2068 case POST_DEC:
2069 fprintf (file, "-%d(0,%s)", size, reg_names [REGNO (base)]);
2070 break;
2071 case PRE_INC:
2072 case POST_INC:
2073 fprintf (file, "%d(0,%s)", size, reg_names [REGNO (base)]);
2074 break;
2075 default:
2076 output_address (XEXP (x, 0));
2077 break;
2078 }
2079 }
2080 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
2081 {
2082 union { double d; int i[2]; } u;
2083 union { float f; int i; } u1;
2084 u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1);
2085 u1.f = u.d;
2086 if (code == 'f')
2087 fprintf (file, "0r%.9g", u1.f);
2088 else
2089 fprintf (file, "0x%x", u1.i);
2090 }
2091 else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != DImode)
2092 {
2093 union { double d; int i[2]; } u;
2094 u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1);
2095 fprintf (file, "0r%.20g", u.d);
2096 }
2097 else
2098 output_addr_const (file, x);
2099}
2100
2101/* output a SYMBOL_REF or a CONST expression involving a SYMBOL_REF. */
2102
2103void
2104output_global_address (file, x)
2105 FILE *file;
2106 rtx x;
2107{
2108 if (GET_CODE (x) == SYMBOL_REF && read_only_operand (x))
2109 assemble_name (file, XSTR (x, 0));
2110 else if (GET_CODE (x) == SYMBOL_REF)
2111 {
2112 assemble_name (file, XSTR (x, 0));
2113 fprintf (file, "-$global$");
2114 }
2115 else if (GET_CODE (x) == CONST)
2116 {
2117 char *sep = "";
2118 int offset = 0; /* assembler wants -$global$ at end */
2119 rtx base;
2120
2121 if (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
2122 {
2123 base = XEXP (XEXP (x, 0), 0);
2124 output_addr_const (file, base);
2125 }
2126 else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == CONST_INT)
2127 offset = INTVAL (XEXP (XEXP (x, 0), 0));
2128 else abort ();
2129
2130 if (GET_CODE (XEXP (XEXP (x, 0), 1)) == SYMBOL_REF)
2131 {
2132 base = XEXP (XEXP (x, 0), 1);
2133 output_addr_const (file, base);
2134 }
2135 else if (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2136 offset = INTVAL (XEXP (XEXP (x, 0),1));
2137 else abort ();
2138
2139 if (GET_CODE (XEXP (x, 0)) == PLUS)
2140 {
2141 if (offset < 0)
2142 {
2143 offset = -offset;
2144 sep = "-";
2145 }
2146 else
2147 sep = "+";
2148 }
2149 else if (GET_CODE (XEXP (x, 0)) == MINUS
2150 && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))
2151 sep = "-";
2152 else abort ();
2153
2154 if (!read_only_operand (base))
2155 fprintf (file, "-$global$");
2156 fprintf (file, "%s", sep);
2157 if (offset) fprintf (file,"%d", offset);
2158 }
2159 else
2160 output_addr_const (file, x);
2161}
2162
2163/* MEM rtls here are never SYMBOL_REFs (I think), so fldws is safe. */
2164
2165char *
2166output_floatsisf2 (operands)
2167 rtx *operands;
2168{
2169 if (GET_CODE (operands[1]) == MEM)
2170 return "fldws %1,%0\n\tfcnvxf,sgl,sgl %0,%0";
2171 else if (FP_REG_P (operands[1]))
2172 return "fcnvxf,sgl,sgl %1,%0";
00704352 2173 abort();
87ad11b0 2174}
2175
2176char *
2177output_floatsidf2 (operands)
2178 rtx *operands;
2179{
2180 if (GET_CODE (operands[1]) == MEM)
2181 return "fldws %1,%0\n\tfcnvxf,sgl,dbl %0,%0";
2182 else if (FP_REG_P (operands[1]))
2183 return "fcnvxf,sgl,dbl %1,%0";
00704352 2184 abort();
87ad11b0 2185}
2186
2187enum rtx_code
2188reverse_relop (code)
2189 enum rtx_code code;
2190{
2191 switch (code)
2192 {
2193 case GT:
2194 return LT;
2195 case LT:
2196 return GT;
2197 case GE:
2198 return LE;
2199 case LE:
2200 return GE;
2201 case LTU:
2202 return GTU;
2203 case GTU:
2204 return LTU;
2205 case GEU:
2206 return LEU;
2207 case LEU:
2208 return GEU;
2209 default:
2210 abort ();
2211 }
2212}
2213
2214/* HP's millicode routines mean something special to the assembler.
2215 Keep track of which ones we have used. */
2216
2217enum millicodes { remI, remU, divI, divU, mulI, mulU, end1000 };
2218static char imported[(int)end1000];
2219static char *milli_names[] = {"remI", "remU", "divI", "divU", "mulI", "mulU"};
2220static char import_string[] = ".IMPORT $$....,MILLICODE";
2221#define MILLI_START 10
2222
2223static int
2224import_milli (code)
2225 enum millicodes code;
2226{
2227 char str[sizeof (import_string)];
2228
2229 if (!imported[(int)code])
2230 {
2231 imported[(int)code] = 1;
2232 strcpy (str, import_string);
2233 strncpy (str + MILLI_START, milli_names[(int)code], 4);
2234 output_asm_insn (str, 0);
2235 }
2236}
2237
2238/* The register constraints have put the operands and return value in
2239 the proper registers. */
2240
2241char *
2242output_mul_insn (unsignedp)
2243 int unsignedp;
2244{
2245 if (unsignedp)
2246 {
2247 import_milli (mulU);
d2daf090 2248 return "bl $$mulU,31%#";
87ad11b0 2249 }
2250 else
2251 {
2252 import_milli (mulI);
d2daf090 2253 return "bl $$mulI,31%#";
87ad11b0 2254 }
2255}
2256
2257/* If operands isn't NULL, then it's a CONST_INT with which we can do
2258 something */
2259
2260
2261/* Emit the rtl for doing a division by a constant. */
2262
2263 /* Do magic division millicodes exist for this value? */
2264
2265static int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
2266 1, 1};
2267
2268/* We'll use an array to keep track of the magic millicodes and
2269 whether or not we've used them already. [n][0] is signed, [n][1] is
2270 unsigned. */
2271
87ad11b0 2272static int div_milli[16][2];
2273
2274int
2275div_operand (op, mode)
2276 rtx op;
2277 enum machine_mode mode;
2278{
2279 return (mode == SImode
2280 && ((GET_CODE (op) == REG && REGNO (op) == 25)
2281 || (GET_CODE (op) == CONST_INT && INTVAL (op) > 0
2282 && INTVAL (op) < 16 && magic_milli[INTVAL (op)])));
2283}
2284
2285int
2286emit_hpdiv_const (operands, unsignedp)
2287 rtx *operands;
2288 int unsignedp;
2289{
2290 if (GET_CODE (operands[2]) == CONST_INT
2291 && INTVAL (operands[2]) > 0
2292 && INTVAL (operands[2]) < 16
2293 && magic_milli[INTVAL (operands[2])])
2294 {
2295 emit_move_insn ( gen_rtx (REG, SImode, 26), operands[1]);
2296 emit
2297 (gen_rtx
2298 (PARALLEL, VOIDmode,
2299 gen_rtvec (5, gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 29),
2300 gen_rtx (unsignedp ? UDIV : DIV, SImode,
2301 gen_rtx (REG, SImode, 26),
2302 operands[2])),
33bd7237 2303 gen_rtx (CLOBBER, VOIDmode, operands[3]),
87ad11b0 2304 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 26)),
2305 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 25)),
2306 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 31)))));
2307 emit_move_insn (operands[0], gen_rtx (REG, SImode, 29));
2308 return 1;
2309 }
2310 return 0;
2311}
2312
2313char *
2314output_div_insn (operands, unsignedp)
2315 rtx *operands;
2316 int unsignedp;
2317{
2318 int divisor;
2319
2320 /* If the divisor is a constant, try to use one of the special
2321 opcodes .*/
2322 if (GET_CODE (operands[0]) == CONST_INT)
2323 {
2324 divisor = INTVAL (operands[0]);
2325 if (!div_milli[divisor][unsignedp])
2326 {
2327 if (unsignedp)
2328 output_asm_insn (".IMPORT $$divU_%0,MILLICODE", operands);
2329 else
2330 output_asm_insn (".IMPORT $$divI_%0,MILLICODE", operands);
2331 div_milli[divisor][unsignedp] = 1;
2332 }
2333 if (unsignedp)
2334 return "bl $$divU_%0,31%#";
2335 return "bl $$divI_%0,31%#";
2336 }
2337 /* Divisor isn't a special constant. */
2338 else
2339 {
2340 if (unsignedp)
2341 {
2342 import_milli (divU);
2343 return "bl $$divU,31%#";
2344 }
2345 else
2346 {
2347 import_milli (divI);
2348 return "bl $$divI,31%#";
2349 }
2350 }
2351}
2352
2353/* Output a $$rem millicode to do mod. */
2354
2355char *
2356output_mod_insn (unsignedp)
2357 int unsignedp;
2358{
2359 if (unsignedp)
2360 {
2361 import_milli (remU);
2362 return "bl $$remU,31%#";
2363 }
2364 else
2365 {
2366 import_milli (remI);
2367 return "bl $$remI,31%#";
2368 }
2369}
2370
2371void
2372output_arg_descriptor (insn)
2373 rtx insn;
2374{
2375 char *arg_regs[4];
2376 enum machine_mode arg_mode;
2377 rtx prev_insn;
2378 int i, output_flag = 0;
2379 int regno;
2380
2381 for (i = 0; i < 4; i++)
2382 arg_regs[i] = 0;
2383
2384 for (prev_insn = PREV_INSN (insn); GET_CODE (prev_insn) == INSN;
2385 prev_insn = PREV_INSN (prev_insn))
2386 {
2387 if (!(GET_CODE (PATTERN (prev_insn)) == USE &&
2388 GET_CODE (XEXP (PATTERN (prev_insn), 0)) == REG &&
2389 FUNCTION_ARG_REGNO_P (REGNO (XEXP (PATTERN (prev_insn), 0)))))
2390 break;
2391 arg_mode = GET_MODE (XEXP (PATTERN (prev_insn), 0));
2392 regno = REGNO (XEXP (PATTERN (prev_insn), 0));
2393 if (regno >= 23 && regno <= 26)
372ef038 2394 {
2395 arg_regs[26 - regno] = "GR";
2396 if (arg_mode == DImode)
2397 arg_regs[25 - regno] = "GR";
2398 }
87ad11b0 2399 else if (!TARGET_SNAKE) /* fp args */
2400 {
2401 if (arg_mode == SFmode)
2402 arg_regs[regno - 36] = "FR";
2403 else
2404 {
2405#ifdef HP_FP_ARG_DESCRIPTOR_REVERSED
2406 arg_regs[regno - 37] = "FR";
2407 arg_regs[regno - 36] = "FU";
2408#else
2409 arg_regs[regno - 37] = "FU";
2410 arg_regs[regno - 36] = "FR";
2411#endif
2412 }
2413 }
2414 else
2415 {
2416 if (arg_mode == SFmode)
2417 arg_regs[(regno - 56) / 2] = "FR";
2418 else
2419 {
2420#ifdef HP_FP_ARG_DESCRIPTOR_REVERSED
2421 arg_regs[(regno - 58) / 2] = "FR";
2422 arg_regs[(regno - 58) / 2 + 1] = "FU";
2423#else
2424 arg_regs[(regno - 58) / 2] = "FU";
2425 arg_regs[(regno - 58) / 2 + 1] = "FR";
2426#endif
2427 }
2428 }
2429 }
2430 fputs ("\t.CALL ", asm_out_file);
2431 for (i = 0; i < 4; i++)
2432 {
2433 if (arg_regs[i])
2434 {
2435 if (output_flag++)
2436 fputc (',', asm_out_file);
2437 fprintf (asm_out_file, "ARGW%d=%s", i, arg_regs[i]);
2438 }
2439 }
2440 fputc ('\n', asm_out_file);
2441}
2442\f
d2c1d63d 2443/* Memory loads/stores to/from the shift need to go through
2444 the general registers. */
87ad11b0 2445
2446enum reg_class
2447secondary_reload_class (class, mode, in)
2448 enum reg_class class;
2449 enum machine_mode mode;
2450 rtx in;
2451{
2452 int regno = true_regnum (in);
2453
d6f01525 2454 if ((TARGET_SHARED_LIBS && function_label_operand (in, mode))
2455 || ((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
2456 && ((mode == QImode || mode == HImode || mode == SImode
2457 || mode == DImode)
2458 && (class == FP_REGS || class == SNAKE_FP_REGS
2459 || class == HI_SNAKE_FP_REGS)))
2460 || (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
9c6d4825 2461 return GENERAL_REGS;
d2c1d63d 2462
2463 return NO_REGS;
87ad11b0 2464}
2465
2466enum direction
2467function_arg_padding (mode, type)
2468 enum machine_mode mode;
2469 tree type;
2470{
2471 int size;
2472
2473 if (mode == BLKmode)
2474 {
2475 if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
2476 size = int_size_in_bytes (type) * BITS_PER_UNIT;
2477 else
2478 return upward; /* Don't know if this is right, but */
2479 /* same as old definition. */
2480 }
2481 else
2482 size = GET_MODE_BITSIZE (mode);
2483 if (size < PARM_BOUNDARY)
2484 return downward;
2485 else if (size % PARM_BOUNDARY)
2486 return upward;
2487 else
2488 return none;
2489}
2490
87ad11b0 2491\f
2492/* Do what is necessary for `va_start'. The argument is ignored;
2493 We look at the current function to determine if stdargs or varargs
2494 is used and fill in an initial va_list. A pointer to this constructor
2495 is returned. */
2496
2497struct rtx_def *
2498hppa_builtin_saveregs (arglist)
2499 tree arglist;
2500{
2501 rtx block, float_addr, offset, float_mem;
2502 tree fntype = TREE_TYPE (current_function_decl);
2503 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2504 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2505 != void_type_node)))
2506 ? UNITS_PER_WORD : 0);
2507
2508 if (argadj)
2509 offset = plus_constant (current_function_arg_offset_rtx, argadj);
2510 else
2511 offset = current_function_arg_offset_rtx;
9c6d4825 2512
87ad11b0 2513 /* Store general registers on the stack. */
2514 move_block_from_reg (23,
2515 gen_rtx (MEM, BLKmode,
2516 plus_constant
2517 (current_function_internal_arg_pointer, -16)),
2518 4);
9c6d4825 2519 return copy_to_reg (expand_binop (Pmode, add_optab,
2520 current_function_internal_arg_pointer,
2521 offset, 0, 0, OPTAB_LIB_WIDEN));
87ad11b0 2522}
d6f01525 2523
2524extern struct obstack *saveable_obstack;
2525
2526/* In HPUX 8.0's shared library scheme, special relocations are needed
2527 for function labels if they might be passed to a function
2528 in a shared library (because shared libraries don't live in code
2529 space), and special magic is needed to construct their address. */
2530
2531void
2532hppa_encode_label (sym)
2533 rtx sym;
2534{
2535 char *str = XSTR (sym, 0);
2536 int len = strlen (str);
2537 char *newstr = obstack_alloc (saveable_obstack, len + 2) ;
2538
c1b3411e 2539 if (str[0] == '*')
2540 *newstr++ = *str++;
d6f01525 2541 strcpy (newstr + 1, str);
c1b3411e 2542 *newstr = '@';
d6f01525 2543 XSTR (sym,0) = newstr;
2544}
2545
2546int
2547function_label_operand (op, mode)
2548 rtx op;
2549 enum machine_mode mode;
2550{
c1b3411e 2551 return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0));
d6f01525 2552}
f33e3942 2553
4ed6ee50 2554/* Returns 1 if the 5 operands specified in OPERANDS are suitable for
2555 use in fmpyadd instructions. Because of the inout operand in the
2556 add part this function may swap operands[3] and operands[4] to make them
2557 suitable for fmpyadd instructions. */
2558int
2559fmpyaddoperands(operands)
2560 rtx *operands;
2561{
2562
2563 /* All modes must be the same. */
2564 if (! (GET_MODE (operands[0]) == GET_MODE (operands[1])
2565 && GET_MODE (operands[0]) == GET_MODE (operands[2])
2566 && GET_MODE (operands[0]) == GET_MODE (operands[3])
2567 && GET_MODE (operands[0]) == GET_MODE (operands[4])
2568 && GET_MODE (operands[0]) == GET_MODE (operands[5])))
2569 return 0;
2570
2571 /* Both DFmode and SFmode should work. But using SFmode makes the
2572 assembler complain. Just turn it off for now. */
2573 if (GET_MODE (operands[0]) != DFmode)
2574 return 0;
2575
2576 /* Only 2 real operands to the addition. One input must be the output. */
2577 if (! rtx_equal_p (operands[3], operands[4])
2578 && ! rtx_equal_p (operands[3], operands[5]))
2579 return 0;
2580
2581 /* Inout operand of add can not conflict with any operands from multiply. */
2582 if (rtx_equal_p (operands[3], operands[0])
2583 || rtx_equal_p (operands[3], operands[1])
2584 || rtx_equal_p (operands[3], operands[2]))
2585 return 0;
2586
2587 /* multiply can not feed into addition operands. */
2588 if (rtx_equal_p (operands[4], operands[0])
2589 || rtx_equal_p (operands[5], operands[0]))
2590 return 0;
2591
2592 /* Make the inout operand be operands[5] and operands[3]. Output template
2593 assumes operands[4] is the read-only add operand. */
2594 if (rtx_equal_p (operands[3], operands[4]))
2595 {
2596 rtx tmp;
2597 tmp = operands[4];
2598 operands[4] = operands[5];
2599 operands[5] = tmp;
2600 }
2601
2602 /* Passed. Operands are suitable for fmpyadd. */
2603 return 1;
2604}
2605
2606/* Returns 1 if the 5 operands specified in OPERANDS are suitable for
2607 use in fmpysub instructions. It is very similar to fmpyaddoperands
2608 above except operands[3] and operands[4] must be the same without
2609 swapping. */
2610int
2611fmpysuboperands(operands)
2612 rtx *operands;
2613{
2614
2615 /* All modes must be the same. */
2616 if (! (GET_MODE (operands[0]) == GET_MODE (operands[1])
2617 && GET_MODE (operands[0]) == GET_MODE (operands[2])
2618 && GET_MODE (operands[0]) == GET_MODE (operands[3])
2619 && GET_MODE (operands[0]) == GET_MODE (operands[4])
2620 && GET_MODE (operands[0]) == GET_MODE (operands[5])))
2621 return 0;
2622
2623 /* Both DFmode and SFmode should work. But using SFmode makes the
2624 assembler complain. Just turn it off for now. */
2625 if (GET_MODE (operands[0]) != DFmode)
2626 return 0;
2627
2628 /* Only 2 real operands to the subtraction. One input must be the output. */
2629 if (! rtx_equal_p (operands[3], operands[4]))
2630 return 0;
2631
2632 /* multiply can not feed into subtraction. */
2633 if (rtx_equal_p (operands[4], operands[0])
2634 || rtx_equal_p (operands[5], operands[0]))
2635 return 0;
2636
2637 /* Inout operand of add can not conflict with any operands from multiply. */
2638 if (rtx_equal_p (operands[3], operands[0])
2639 || rtx_equal_p (operands[3], operands[1])
2640 || rtx_equal_p (operands[3], operands[2]))
2641 return 0;
2642
2643 /* Passed. Operands are suitable for fmpysub. */
2644 return 1;
2645}
2646
621b5219 2647
2648/* Return 1 iff OP is a valid operator to use in an incscc
2649 instruction. Adding or subtracting the condition code
2650 to/from another operand is valid on the PA, so return 1
2651 for PLUS or MINUS. */
2652int
2653incscc_operator (op, mode)
2654 rtx op;
2655 enum machine_mode mode;
2656{
2657 return (GET_CODE (op) == PLUS || GET_CODE (op) == MINUS);
2658}
2659
2660
f33e3942 2661/* Return 1 if OP is suitable for the second add operand (the unshifed
2662 operand) in an shadd instruction. Allow CONST_INT to work around
2663 a reload bug. */
2664int
2665shadd_operand (op, mode)
2666 rtx op;
2667 enum machine_mode mode;
2668{
2669 if (GET_CODE (op) == REG)
2670 return 1;
2671 if (GET_CODE (op) == CONST_INT)
2672 return 1;
2673 return 0;
2674}