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