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