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