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