00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "rtl.h"
00026 #include "regs.h"
00027 #include "hard-reg-set.h"
00028 #include "real.h"
00029 #include "insn-config.h"
00030 #include "conditions.h"
00031 #include "output.h"
00032 #include "insn-attr.h"
00033 #include "flags.h"
00034 #include "tree.h"
00035 #include "expr.h"
00036 #include "optabs.h"
00037 #include "libfuncs.h"
00038 #include "reload.h"
00039 #include "c-tree.h"
00040 #include "integrate.h"
00041 #include "function.h"
00042 #include "obstack.h"
00043 #include "toplev.h"
00044 #include "ggc.h"
00045 #include "recog.h"
00046 #include "tm_p.h"
00047 #include "target.h"
00048 #include "target-def.h"
00049
00050 #ifndef DO_FRAME_NOTES
00051 #ifdef INCOMING_RETURN_ADDR_RTX
00052 #define DO_FRAME_NOTES 1
00053 #else
00054 #define DO_FRAME_NOTES 0
00055 #endif
00056 #endif
00057
00058 #if DO_FRAME_NOTES
00059 #define FRP(INSN) \
00060 do \
00061 { \
00062 rtx insn = INSN; \
00063 RTX_FRAME_RELATED_P (insn) = 1; \
00064 } \
00065 while (0)
00066 #else
00067 #define FRP(INSN) INSN
00068 #endif
00069
00070 static inline rtx force_mode PARAMS ((enum machine_mode, rtx));
00071 static void pa_combine_instructions PARAMS ((rtx));
00072 static int pa_can_combine_p PARAMS ((rtx, rtx, rtx, int, rtx, rtx, rtx));
00073 static int forward_branch_p PARAMS ((rtx));
00074 static int shadd_constant_p PARAMS ((int));
00075 static void pa_add_gc_roots PARAMS ((void));
00076 static void mark_deferred_plabels PARAMS ((void *));
00077 static void compute_zdepwi_operands PARAMS ((unsigned HOST_WIDE_INT, unsigned *));
00078 static int compute_movstrsi_length PARAMS ((rtx));
00079 static bool pa_assemble_integer PARAMS ((rtx, unsigned int, int));
00080 static void remove_useless_addtr_insns PARAMS ((rtx, int));
00081 static void store_reg PARAMS ((int, int, int));
00082 static void load_reg PARAMS ((int, int, int));
00083 static void set_reg_plus_d PARAMS ((int, int, int));
00084 static rtx get_last_nonnote_insn PARAMS ((void));
00085 static void pa_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00086 static int pa_adjust_cost PARAMS ((rtx, rtx, rtx, int));
00087 static int pa_adjust_priority PARAMS ((rtx, int));
00088 static int pa_issue_rate PARAMS ((void));
00089
00090
00091
00092
00093 rtx hppa_compare_op0, hppa_compare_op1;
00094 enum cmp_type hppa_branch_type;
00095
00096
00097 enum processor_type pa_cpu;
00098
00099
00100 const char *pa_cpu_string;
00101
00102
00103 enum architecture_type pa_arch;
00104
00105
00106 const char *pa_arch_string;
00107
00108
00109
00110 static int gr_saved, fr_saved;
00111
00112 static rtx find_addr_reg PARAMS ((rtx));
00113
00114
00115
00116
00117 unsigned int total_code_bytes;
00118
00119
00120
00121
00122 struct deferred_plabel
00123 {
00124 rtx internal_label;
00125 char *name;
00126 } *deferred_plabels = 0;
00127 int n_deferred_plabels = 0;
00128
00129
00130
00131 #undef TARGET_ASM_ALIGNED_HI_OP
00132 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
00133 #undef TARGET_ASM_ALIGNED_SI_OP
00134 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
00135 #undef TARGET_ASM_ALIGNED_DI_OP
00136 #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
00137 #undef TARGET_ASM_UNALIGNED_HI_OP
00138 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
00139 #undef TARGET_ASM_UNALIGNED_SI_OP
00140 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
00141 #undef TARGET_ASM_UNALIGNED_DI_OP
00142 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
00143 #undef TARGET_ASM_INTEGER
00144 #define TARGET_ASM_INTEGER pa_assemble_integer
00145
00146 #undef TARGET_ASM_FUNCTION_PROLOGUE
00147 #define TARGET_ASM_FUNCTION_PROLOGUE pa_output_function_prologue
00148 #undef TARGET_ASM_FUNCTION_EPILOGUE
00149 #define TARGET_ASM_FUNCTION_EPILOGUE pa_output_function_epilogue
00150
00151 #undef TARGET_SCHED_ADJUST_COST
00152 #define TARGET_SCHED_ADJUST_COST pa_adjust_cost
00153 #undef TARGET_SCHED_ADJUST_PRIORITY
00154 #define TARGET_SCHED_ADJUST_PRIORITY pa_adjust_priority
00155 #undef TARGET_SCHED_ISSUE_RATE
00156 #define TARGET_SCHED_ISSUE_RATE pa_issue_rate
00157
00158 struct gcc_target targetm = TARGET_INITIALIZER;
00159
00160 void
00161 override_options ()
00162 {
00163
00164 if (pa_cpu_string && ! strcmp (pa_cpu_string, "7100"))
00165 {
00166 pa_cpu_string = "7100";
00167 pa_cpu = PROCESSOR_7100;
00168 }
00169 else if (pa_cpu_string && ! strcmp (pa_cpu_string, "700"))
00170 {
00171 pa_cpu_string = "700";
00172 pa_cpu = PROCESSOR_700;
00173 }
00174 else if (pa_cpu_string == NULL
00175 || ! strcmp (pa_cpu_string, "7100LC"))
00176 {
00177 pa_cpu_string = "7100LC";
00178 pa_cpu = PROCESSOR_7100LC;
00179 }
00180 else if (pa_cpu_string && ! strcmp (pa_cpu_string, "7200"))
00181 {
00182 pa_cpu_string = "7200";
00183 pa_cpu = PROCESSOR_7200;
00184 }
00185 else if (pa_cpu_string && ! strcmp (pa_cpu_string, "8000"))
00186 {
00187 pa_cpu_string = "8000";
00188 pa_cpu = PROCESSOR_8000;
00189 }
00190 else
00191 {
00192 warning ("unknown -mschedule= option (%s).\nValid options are 700, 7100, 7100LC, 7200, and 8000\n", pa_cpu_string);
00193 }
00194
00195
00196 if (pa_arch_string && ! strcmp (pa_arch_string, "1.0"))
00197 {
00198 pa_arch_string = "1.0";
00199 pa_arch = ARCHITECTURE_10;
00200 target_flags &= ~(MASK_PA_11 | MASK_PA_20);
00201 }
00202 else if (pa_arch_string && ! strcmp (pa_arch_string, "1.1"))
00203 {
00204 pa_arch_string = "1.1";
00205 pa_arch = ARCHITECTURE_11;
00206 target_flags &= ~MASK_PA_20;
00207 target_flags |= MASK_PA_11;
00208 }
00209 else if (pa_arch_string && ! strcmp (pa_arch_string, "2.0"))
00210 {
00211 pa_arch_string = "2.0";
00212 pa_arch = ARCHITECTURE_20;
00213 target_flags |= MASK_PA_11 | MASK_PA_20;
00214 }
00215 else if (pa_arch_string)
00216 {
00217 warning ("unknown -march= option (%s).\nValid options are 1.0, 1.1, and 2.0\n", pa_arch_string);
00218 }
00219
00220 if (flag_pic && TARGET_PORTABLE_RUNTIME)
00221 {
00222 warning ("PIC code generation is not supported in the portable runtime model\n");
00223 }
00224
00225 if (flag_pic && TARGET_FAST_INDIRECT_CALLS)
00226 {
00227 warning ("PIC code generation is not compatible with fast indirect calls\n");
00228 }
00229
00230 if (! TARGET_GAS && write_symbols != NO_DEBUG)
00231 {
00232 warning ("-g is only supported when using GAS on this processor,");
00233 warning ("-g option disabled");
00234 write_symbols = NO_DEBUG;
00235 }
00236
00237
00238
00239 if (flag_pic == 1 || TARGET_64BIT)
00240 flag_pic = 2;
00241
00242
00243 if (UNITS_PER_WORD == 4)
00244 targetm.asm_out.aligned_op.di = NULL;
00245
00246
00247 if (!TARGET_GAS)
00248 {
00249 targetm.asm_out.unaligned_op.hi = NULL;
00250 targetm.asm_out.unaligned_op.si = NULL;
00251 targetm.asm_out.unaligned_op.di = NULL;
00252 }
00253
00254
00255 pa_add_gc_roots ();
00256 }
00257
00258
00259
00260 int
00261 reg_or_0_operand (op, mode)
00262 rtx op;
00263 enum machine_mode mode;
00264 {
00265 return (op == CONST0_RTX (mode) || register_operand (op, mode));
00266 }
00267
00268
00269
00270
00271
00272
00273 int
00274 call_operand_address (op, mode)
00275 rtx op;
00276 enum machine_mode mode ATTRIBUTE_UNUSED;
00277 {
00278 return (GET_MODE (op) == word_mode
00279 && CONSTANT_P (op) && ! TARGET_PORTABLE_RUNTIME);
00280 }
00281
00282
00283
00284
00285 int
00286 symbolic_expression_p (x)
00287 register rtx x;
00288 {
00289
00290
00291 if (GET_CODE (x) == HIGH)
00292 x = XEXP (x, 0);
00293
00294 return (symbolic_operand (x, VOIDmode));
00295 }
00296
00297 int
00298 symbolic_operand (op, mode)
00299 register rtx op;
00300 enum machine_mode mode ATTRIBUTE_UNUSED;
00301 {
00302 switch (GET_CODE (op))
00303 {
00304 case SYMBOL_REF:
00305 case LABEL_REF:
00306 return 1;
00307 case CONST:
00308 op = XEXP (op, 0);
00309 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
00310 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
00311 && GET_CODE (XEXP (op, 1)) == CONST_INT);
00312 default:
00313 return 0;
00314 }
00315 }
00316
00317
00318
00319
00320 int
00321 symbolic_memory_operand (op, mode)
00322 rtx op;
00323 enum machine_mode mode ATTRIBUTE_UNUSED;
00324 {
00325 if (GET_CODE (op) == SUBREG)
00326 op = SUBREG_REG (op);
00327 if (GET_CODE (op) != MEM)
00328 return 0;
00329 op = XEXP (op, 0);
00330 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
00331 || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
00332 }
00333
00334
00335
00336
00337 int
00338 reg_or_nonsymb_mem_operand (op, mode)
00339 register rtx op;
00340 enum machine_mode mode;
00341 {
00342 if (register_operand (op, mode))
00343 return 1;
00344
00345 if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
00346 return 1;
00347
00348 return 0;
00349 }
00350
00351
00352
00353
00354 int
00355 reg_or_0_or_nonsymb_mem_operand (op, mode)
00356 register rtx op;
00357 enum machine_mode mode;
00358 {
00359 if (register_operand (op, mode))
00360 return 1;
00361
00362 if (op == CONST0_RTX (mode))
00363 return 1;
00364
00365 if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
00366 return 1;
00367
00368 return 0;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377 int
00378 reg_before_reload_operand (op, mode)
00379 register rtx op;
00380 enum machine_mode mode;
00381 {
00382
00383 if (GET_CODE (op) == SUBREG)
00384 return 0;
00385
00386 if (register_operand (op, mode))
00387 return 1;
00388
00389 if (reload_completed
00390 && memory_operand (op, mode)
00391 && ! symbolic_memory_operand (op, mode))
00392 return 1;
00393
00394 return 0;
00395 }
00396
00397
00398
00399 int
00400 cint_ok_for_move (intval)
00401 HOST_WIDE_INT intval;
00402 {
00403
00404 return (CONST_OK_FOR_LETTER_P (intval, 'J')
00405 || CONST_OK_FOR_LETTER_P (intval, 'N')
00406 || CONST_OK_FOR_LETTER_P (intval, 'K'));
00407 }
00408
00409
00410
00411 int
00412 move_operand (op, mode)
00413 rtx op;
00414 enum machine_mode mode;
00415 {
00416 if (register_operand (op, mode))
00417 return 1;
00418
00419 if (GET_CODE (op) == CONSTANT_P_RTX)
00420 return 1;
00421
00422 if (GET_CODE (op) == CONST_INT)
00423 return cint_ok_for_move (INTVAL (op));
00424
00425 if (GET_CODE (op) == SUBREG)
00426 op = SUBREG_REG (op);
00427 if (GET_CODE (op) != MEM)
00428 return 0;
00429
00430 op = XEXP (op, 0);
00431
00432
00433
00434 if (GET_CODE (op) == LO_SUM
00435 && GET_CODE (XEXP (op, 0)) == REG
00436 && REG_OK_FOR_BASE_P (XEXP (op, 0))
00437 && GET_CODE (XEXP (op, 1)) == UNSPEC
00438 && GET_MODE (op) == Pmode)
00439 return 1;
00440
00441
00442
00443 if (! TARGET_DISABLE_INDEXING
00444 && GET_CODE (op) == PLUS
00445 && ((GET_CODE (XEXP (op, 0)) == MULT
00446 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
00447 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
00448 && INTVAL (XEXP (XEXP (op, 0), 1))
00449 == (HOST_WIDE_INT) GET_MODE_SIZE (mode)
00450 && GET_CODE (XEXP (op, 1)) == REG)
00451 || (GET_CODE (XEXP (op, 1)) == MULT
00452 &&GET_CODE (XEXP (XEXP (op, 1), 0)) == REG
00453 && GET_CODE (XEXP (XEXP (op, 1), 1)) == CONST_INT
00454 && INTVAL (XEXP (XEXP (op, 1), 1))
00455 == (HOST_WIDE_INT) GET_MODE_SIZE (mode)
00456 && GET_CODE (XEXP (op, 0)) == REG)))
00457 return 1;
00458
00459 return memory_address_p (mode, op);
00460 }
00461
00462
00463
00464 int
00465 reg_or_cint_move_operand (op, mode)
00466 rtx op;
00467 enum machine_mode mode;
00468 {
00469 if (register_operand (op, mode))
00470 return 1;
00471
00472 if (GET_CODE (op) == CONST_INT)
00473 return cint_ok_for_move (INTVAL (op));
00474
00475 return 0;
00476 }
00477
00478 int
00479 pic_label_operand (op, mode)
00480 rtx op;
00481 enum machine_mode mode ATTRIBUTE_UNUSED;
00482 {
00483 if (!flag_pic)
00484 return 0;
00485
00486 switch (GET_CODE (op))
00487 {
00488 case LABEL_REF:
00489 return 1;
00490 case CONST:
00491 op = XEXP (op, 0);
00492 return (GET_CODE (XEXP (op, 0)) == LABEL_REF
00493 && GET_CODE (XEXP (op, 1)) == CONST_INT);
00494 default:
00495 return 0;
00496 }
00497 }
00498
00499 int
00500 fp_reg_operand (op, mode)
00501 rtx op;
00502 enum machine_mode mode ATTRIBUTE_UNUSED;
00503 {
00504 return reg_renumber && FP_REG_P (op);
00505 }
00506
00507
00508
00509
00510
00511
00512 int
00513 arith_operand (op, mode)
00514 rtx op;
00515 enum machine_mode mode;
00516 {
00517 return (register_operand (op, mode)
00518 || (GET_CODE (op) == CONST_INT && INT_14_BITS (op)));
00519 }
00520
00521
00522
00523
00524 int
00525 arith11_operand (op, mode)
00526 rtx op;
00527 enum machine_mode mode;
00528 {
00529 return (register_operand (op, mode)
00530 || (GET_CODE (op) == CONST_INT && INT_11_BITS (op)));
00531 }
00532
00533
00534
00535 int
00536 adddi3_operand (op, mode)
00537 rtx op;
00538 enum machine_mode mode;
00539 {
00540 return (register_operand (op, mode)
00541 || (GET_CODE (op) == CONST_INT
00542 && (TARGET_64BIT ? INT_14_BITS (op) : INT_11_BITS (op))));
00543 }
00544
00545
00546
00547 int
00548 pre_cint_operand (op, mode)
00549 rtx op;
00550 enum machine_mode mode ATTRIBUTE_UNUSED;
00551 {
00552 return (GET_CODE (op) == CONST_INT
00553 && INTVAL (op) >= -0x2000 && INTVAL (op) < 0x10);
00554 }
00555
00556
00557
00558 int
00559 post_cint_operand (op, mode)
00560 rtx op;
00561 enum machine_mode mode ATTRIBUTE_UNUSED;
00562 {
00563 return (GET_CODE (op) == CONST_INT
00564 && INTVAL (op) < 0x2000 && INTVAL (op) >= -0x10);
00565 }
00566
00567 int
00568 arith_double_operand (op, mode)
00569 rtx op;
00570 enum machine_mode mode;
00571 {
00572 return (register_operand (op, mode)
00573 || (GET_CODE (op) == CONST_DOUBLE
00574 && GET_MODE (op) == mode
00575 && VAL_14_BITS_P (CONST_DOUBLE_LOW (op))
00576 && ((CONST_DOUBLE_HIGH (op) >= 0)
00577 == ((CONST_DOUBLE_LOW (op) & 0x1000) == 0))));
00578 }
00579
00580
00581
00582
00583
00584 int
00585 ireg_or_int5_operand (op, mode)
00586 rtx op;
00587 enum machine_mode mode ATTRIBUTE_UNUSED;
00588 {
00589 return ((GET_CODE (op) == CONST_INT && INT_5_BITS (op))
00590 || (GET_CODE (op) == REG && REGNO (op) > 0 && REGNO (op) < 32));
00591 }
00592
00593
00594 int
00595 ireg_operand (op, mode)
00596 rtx op;
00597 enum machine_mode mode ATTRIBUTE_UNUSED;
00598 {
00599 return (GET_CODE (op) == REG && REGNO (op) > 0 && REGNO (op) < 32);
00600 }
00601
00602
00603
00604
00605 int
00606 int5_operand (op, mode)
00607 rtx op;
00608 enum machine_mode mode ATTRIBUTE_UNUSED;
00609 {
00610 return (GET_CODE (op) == CONST_INT && INT_5_BITS (op));
00611 }
00612
00613 int
00614 uint5_operand (op, mode)
00615 rtx op;
00616 enum machine_mode mode ATTRIBUTE_UNUSED;
00617 {
00618 return (GET_CODE (op) == CONST_INT && INT_U5_BITS (op));
00619 }
00620
00621 int
00622 int11_operand (op, mode)
00623 rtx op;
00624 enum machine_mode mode ATTRIBUTE_UNUSED;
00625 {
00626 return (GET_CODE (op) == CONST_INT && INT_11_BITS (op));
00627 }
00628
00629 int
00630 uint32_operand (op, mode)
00631 rtx op;
00632 enum machine_mode mode ATTRIBUTE_UNUSED;
00633 {
00634 #if HOST_BITS_PER_WIDE_INT > 32
00635
00636 return (GET_CODE (op) == CONST_INT
00637 && (INTVAL (op) >= 0 && INTVAL (op) < (HOST_WIDE_INT) 1 << 32));
00638 #else
00639 return (GET_CODE (op) == CONST_INT
00640 || (GET_CODE (op) == CONST_DOUBLE
00641 && CONST_DOUBLE_HIGH (op) == 0));
00642 #endif
00643 }
00644
00645 int
00646 arith5_operand (op, mode)
00647 rtx op;
00648 enum machine_mode mode;
00649 {
00650 return register_operand (op, mode) || int5_operand (op, mode);
00651 }
00652
00653
00654
00655
00656 int
00657 zdepi_cint_p (x)
00658 unsigned HOST_WIDE_INT x;
00659 {
00660 unsigned HOST_WIDE_INT lsb_mask, t;
00661
00662
00663
00664 lsb_mask = x & -x;
00665 t = ((x >> 4) + lsb_mask) & ~(lsb_mask - 1);
00666
00667 return ((t & (t - 1)) == 0);
00668 }
00669
00670
00671
00672
00673
00674
00675 int
00676 and_mask_p (mask)
00677 unsigned HOST_WIDE_INT mask;
00678 {
00679 mask = ~mask;
00680 mask += mask & -mask;
00681 return (mask & (mask - 1)) == 0;
00682 }
00683
00684
00685 int
00686 and_operand (op, mode)
00687 rtx op;
00688 enum machine_mode mode;
00689 {
00690 return (register_operand (op, mode)
00691 || (GET_CODE (op) == CONST_INT && and_mask_p (INTVAL (op))));
00692 }
00693
00694
00695 int
00696 ior_mask_p (mask)
00697 unsigned HOST_WIDE_INT mask;
00698 {
00699 mask += mask & -mask;
00700 return (mask & (mask - 1)) == 0;
00701 }
00702
00703
00704 int
00705 ior_operand (op, mode)
00706 rtx op;
00707 enum machine_mode mode ATTRIBUTE_UNUSED;
00708 {
00709 return (GET_CODE (op) == CONST_INT && ior_mask_p (INTVAL (op)));
00710 }
00711
00712 int
00713 lhs_lshift_operand (op, mode)
00714 rtx op;
00715 enum machine_mode mode;
00716 {
00717 return register_operand (op, mode) || lhs_lshift_cint_operand (op, mode);
00718 }
00719
00720
00721
00722
00723 int
00724 lhs_lshift_cint_operand (op, mode)
00725 rtx op;
00726 enum machine_mode mode ATTRIBUTE_UNUSED;
00727 {
00728 unsigned HOST_WIDE_INT x;
00729 if (GET_CODE (op) != CONST_INT)
00730 return 0;
00731 x = INTVAL (op) >> 4;
00732 return (x & (x + 1)) == 0;
00733 }
00734
00735 int
00736 arith32_operand (op, mode)
00737 rtx op;
00738 enum machine_mode mode;
00739 {
00740 return register_operand (op, mode) || GET_CODE (op) == CONST_INT;
00741 }
00742
00743 int
00744 pc_or_label_operand (op, mode)
00745 rtx op;
00746 enum machine_mode mode ATTRIBUTE_UNUSED;
00747 {
00748 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
00749 }
00750
00751
00752
00753
00754
00755
00756 rtx
00757 legitimize_pic_address (orig, mode, reg)
00758 rtx orig, reg;
00759 enum machine_mode mode;
00760 {
00761 rtx pic_ref = orig;
00762
00763
00764 if (pic_label_operand (orig, mode))
00765 {
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775 emit_insn (gen_rtx_SET (VOIDmode, reg, orig));
00776 current_function_uses_pic_offset_table = 1;
00777 return reg;
00778 }
00779 if (GET_CODE (orig) == SYMBOL_REF)
00780 {
00781 if (reg == 0)
00782 abort ();
00783
00784 emit_move_insn (reg,
00785 gen_rtx_PLUS (word_mode, pic_offset_table_rtx,
00786 gen_rtx_HIGH (word_mode, orig)));
00787 pic_ref
00788 = gen_rtx_MEM (Pmode,
00789 gen_rtx_LO_SUM (Pmode, reg,
00790 gen_rtx_UNSPEC (Pmode,
00791 gen_rtvec (1, orig),
00792 0)));
00793
00794 current_function_uses_pic_offset_table = 1;
00795 RTX_UNCHANGING_P (pic_ref) = 1;
00796 emit_move_insn (reg, pic_ref);
00797 return reg;
00798 }
00799 else if (GET_CODE (orig) == CONST)
00800 {
00801 rtx base;
00802
00803 if (GET_CODE (XEXP (orig, 0)) == PLUS
00804 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
00805 return orig;
00806
00807 if (reg == 0)
00808 abort ();
00809
00810 if (GET_CODE (XEXP (orig, 0)) == PLUS)
00811 {
00812 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
00813 orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
00814 base == reg ? 0 : reg);
00815 }
00816 else abort ();
00817 if (GET_CODE (orig) == CONST_INT)
00818 {
00819 if (INT_14_BITS (orig))
00820 return plus_constant (base, INTVAL (orig));
00821 orig = force_reg (Pmode, orig);
00822 }
00823 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
00824
00825 }
00826 return pic_ref;
00827 }
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880 rtx
00881 hppa_legitimize_address (x, oldx, mode)
00882 rtx x, oldx ATTRIBUTE_UNUSED;
00883 enum machine_mode mode;
00884 {
00885 rtx orig = x;
00886
00887 if (flag_pic)
00888 return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode));
00889
00890
00891 if (GET_CODE (x) == CONST)
00892 x = XEXP (x, 0);
00893
00894
00895
00896 if (GET_CODE (x) == PLUS
00897 && GET_CODE (XEXP (x, 0)) == REG
00898 && GET_CODE (XEXP (x, 1)) == SYMBOL_REF)
00899 {
00900 rtx reg = force_reg (Pmode, XEXP (x, 1));
00901 return force_reg (Pmode, gen_rtx_PLUS (Pmode, reg, XEXP (x, 0)));
00902 }
00903
00904
00905
00906 if (GET_CODE (x) == PLUS
00907 && GET_CODE (XEXP (x, 1)) == CONST_INT
00908 && ((GET_CODE (XEXP (x, 0)) == SYMBOL_REF
00909 && !FUNCTION_NAME_P (XSTR (XEXP (x, 0), 0)))
00910 || GET_CODE (XEXP (x, 0)) == REG))
00911 {
00912 rtx int_part, ptr_reg;
00913 int newoffset;
00914 int offset = INTVAL (XEXP (x, 1));
00915 int mask;
00916
00917 mask = (GET_MODE_CLASS (mode) == MODE_FLOAT
00918 ? (TARGET_PA_20 ? 0x3fff : 0x1f) : 0x3fff);
00919
00920
00921
00922 if ((offset & mask) >= ((mask + 1) / 2))
00923 newoffset = (offset & ~ mask) + mask + 1;
00924 else
00925 newoffset = (offset & ~ mask);
00926
00927
00928
00929
00930
00931
00932
00933 if (! VAL_14_BITS_P (newoffset)
00934 && GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
00935 {
00936 rtx const_part = plus_constant (XEXP (x, 0), newoffset);
00937 rtx tmp_reg
00938 = force_reg (Pmode,
00939 gen_rtx_HIGH (Pmode, const_part));
00940 ptr_reg
00941 = force_reg (Pmode,
00942 gen_rtx_LO_SUM (Pmode,
00943 tmp_reg, const_part));
00944 }
00945 else
00946 {
00947 if (! VAL_14_BITS_P (newoffset))
00948 int_part = force_reg (Pmode, GEN_INT (newoffset));
00949 else
00950 int_part = GEN_INT (newoffset);
00951
00952 ptr_reg = force_reg (Pmode,
00953 gen_rtx_PLUS (Pmode,
00954 force_reg (Pmode, XEXP (x, 0)),
00955 int_part));
00956 }
00957 return plus_constant (ptr_reg, offset - newoffset);
00958 }
00959
00960
00961
00962 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
00963 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
00964 && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
00965 && (GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == 'o'
00966 || GET_CODE (XEXP (x, 1)) == SUBREG)
00967 && GET_CODE (XEXP (x, 1)) != CONST)
00968 {
00969 int val = INTVAL (XEXP (XEXP (x, 0), 1));
00970 rtx reg1, reg2;
00971
00972 reg1 = XEXP (x, 1);
00973 if (GET_CODE (reg1) != REG)
00974 reg1 = force_reg (Pmode, force_operand (reg1, 0));
00975
00976 reg2 = XEXP (XEXP (x, 0), 0);
00977 if (GET_CODE (reg2) != REG)
00978 reg2 = force_reg (Pmode, force_operand (reg2, 0));
00979
00980 return force_reg (Pmode, gen_rtx_PLUS (Pmode,
00981 gen_rtx_MULT (Pmode,
00982 reg2,
00983 GEN_INT (val)),
00984 reg1));
00985 }
00986
00987
00988
00989
00990
00991 if (GET_CODE (x) == PLUS
00992 && GET_CODE (XEXP (x, 0)) == PLUS
00993 && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
00994 && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
00995 && shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)))
00996 && (mode == SFmode || mode == DFmode))
00997 {
00998
00999
01000 rtx reg1, reg2, base, idx, orig_base;
01001
01002 reg1 = XEXP (XEXP (x, 0), 1);
01003 reg2 = XEXP (x, 1);
01004 base = NULL_RTX;
01005 idx = NULL_RTX;
01006
01007
01008
01009
01010 if (GET_CODE (reg1) != REG)
01011 reg1 = force_reg (Pmode, force_operand (reg1, 0));
01012
01013 if (GET_CODE (reg2) != REG)
01014 reg2 = force_reg (Pmode, force_operand (reg2, 0));
01015
01016
01017
01018 if (GET_CODE (reg1) == REG
01019 && REG_POINTER (reg1))
01020 {
01021 base = reg1;
01022 orig_base = XEXP (XEXP (x, 0), 1);
01023 idx = gen_rtx_PLUS (Pmode,
01024 gen_rtx_MULT (Pmode,
01025 XEXP (XEXP (XEXP (x, 0), 0), 0),
01026 XEXP (XEXP (XEXP (x, 0), 0), 1)),
01027 XEXP (x, 1));
01028 }
01029 else if (GET_CODE (reg2) == REG
01030 && REG_POINTER (reg2))
01031 {
01032 base = reg2;
01033 orig_base = XEXP (x, 1);
01034 idx = XEXP (x, 0);
01035 }
01036
01037 if (base == 0)
01038 return orig;
01039
01040
01041
01042 if (GET_CODE (XEXP (idx, 1)) == CONST_INT
01043 && VAL_14_BITS_P (INTVAL (XEXP (idx, 1))
01044 / INTVAL (XEXP (XEXP (idx, 0), 1)))
01045 && INTVAL (XEXP (idx, 1)) % INTVAL (XEXP (XEXP (idx, 0), 1)) == 0)
01046 {
01047
01048 int val = INTVAL (XEXP (idx, 1));
01049
01050 val /= INTVAL (XEXP (XEXP (idx, 0), 1));
01051 reg1 = XEXP (XEXP (idx, 0), 0);
01052 if (GET_CODE (reg1) != REG)
01053 reg1 = force_reg (Pmode, force_operand (reg1, 0));
01054
01055 reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, reg1, GEN_INT (val)));
01056
01057
01058 return
01059 force_reg
01060 (Pmode, gen_rtx_PLUS (Pmode,
01061 gen_rtx_MULT (Pmode, reg1,
01062 XEXP (XEXP (idx, 0), 1)),
01063 base));
01064 }
01065
01066
01067 if (GET_CODE (XEXP (idx, 1)) == CONST_INT
01068 && INTVAL (XEXP (idx, 1)) <= 4096
01069 && INTVAL (XEXP (idx, 1)) >= -4096)
01070 {
01071 int val = INTVAL (XEXP (XEXP (idx, 0), 1));
01072 rtx reg1, reg2;
01073
01074 reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, XEXP (idx, 1)));
01075
01076 reg2 = XEXP (XEXP (idx, 0), 0);
01077 if (GET_CODE (reg2) != CONST_INT)
01078 reg2 = force_reg (Pmode, force_operand (reg2, 0));
01079
01080 return force_reg (Pmode, gen_rtx_PLUS (Pmode,
01081 gen_rtx_MULT (Pmode,
01082 reg2,
01083 GEN_INT (val)),
01084 reg1));
01085 }
01086
01087
01088
01089
01090
01091 reg1 = XEXP (XEXP (idx, 0), 0);
01092 if (GET_CODE (reg1) != REG)
01093 reg1 = force_reg (Pmode, force_operand (reg1, 0));
01094
01095
01096 reg2 = XEXP (idx, 1);
01097 if (GET_CODE (reg2) != REG)
01098 reg2 = force_reg (Pmode, force_operand (reg2, 0));
01099
01100 reg1 = force_reg (Pmode,
01101 gen_rtx_PLUS (Pmode,
01102 gen_rtx_MULT (Pmode, reg1,
01103 XEXP (XEXP (idx, 0), 1)),
01104 reg2));
01105
01106
01107 return force_reg (Pmode, gen_rtx_PLUS (Pmode, base, reg1));
01108
01109 }
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122 if (GET_CODE (x) == PLUS
01123 && symbolic_expression_p (XEXP (x, 1)))
01124 {
01125
01126
01127
01128
01129 rtx regx1, regx2, regy1, regy2, y;
01130
01131
01132 y = XEXP (x, 1);
01133 if (GET_CODE (y) == CONST)
01134 y = XEXP (y, 0);
01135
01136 if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)
01137 {
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147 if (GET_CODE (XEXP (y, 0)) == SYMBOL_REF
01148 && GET_CODE (XEXP (x, 0)) == MULT
01149 && GET_CODE (XEXP (y, 1)) == CONST_INT
01150 && INTVAL (XEXP (y, 1)) >= -4096
01151 && INTVAL (XEXP (y, 1)) <= 4095
01152 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
01153 && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
01154 {
01155 int val = INTVAL (XEXP (XEXP (x, 0), 1));
01156 rtx reg1, reg2;
01157
01158 reg1 = XEXP (x, 1);
01159 if (GET_CODE (reg1) != REG)
01160 reg1 = force_reg (Pmode, force_operand (reg1, 0));
01161
01162 reg2 = XEXP (XEXP (x, 0), 0);
01163 if (GET_CODE (reg2) != REG)
01164 reg2 = force_reg (Pmode, force_operand (reg2, 0));
01165
01166 return force_reg (Pmode,
01167 gen_rtx_PLUS (Pmode,
01168 gen_rtx_MULT (Pmode,
01169 reg2,
01170 GEN_INT (val)),
01171 reg1));
01172 }
01173 else if ((mode == DFmode || mode == SFmode)
01174 && GET_CODE (XEXP (y, 0)) == SYMBOL_REF
01175 && GET_CODE (XEXP (x, 0)) == MULT
01176 && GET_CODE (XEXP (y, 1)) == CONST_INT
01177 && INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0
01178 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
01179 && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
01180 {
01181 regx1
01182 = force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1))
01183 / INTVAL (XEXP (XEXP (x, 0), 1))));
01184 regx2 = XEXP (XEXP (x, 0), 0);
01185 if (GET_CODE (regx2) != REG)
01186 regx2 = force_reg (Pmode, force_operand (regx2, 0));
01187 regx2 = force_reg (Pmode, gen_rtx_fmt_ee (GET_CODE (y), Pmode,
01188 regx2, regx1));
01189 return
01190 force_reg (Pmode,
01191 gen_rtx_PLUS (Pmode,
01192 gen_rtx_MULT (Pmode, regx2,
01193 XEXP (XEXP (x, 0), 1)),
01194 force_reg (Pmode, XEXP (y, 0))));
01195 }
01196 else if (GET_CODE (XEXP (y, 1)) == CONST_INT
01197 && INTVAL (XEXP (y, 1)) >= -4096
01198 && INTVAL (XEXP (y, 1)) <= 4095)
01199 {
01200
01201
01202
01203 return orig;
01204 }
01205 else
01206 {
01207
01208 regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));
01209 regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
01210 regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
01211 regx1 = force_reg (Pmode,
01212 gen_rtx_fmt_ee (GET_CODE (y), Pmode,
01213 regx1, regy2));
01214 return force_reg (Pmode, gen_rtx_PLUS (Pmode, regx1, regy1));
01215 }
01216 }
01217 }
01218
01219 return orig;
01220 }
01221
01222
01223
01224
01225
01226
01227
01228
01229 int
01230 hppa_address_cost (X)
01231 rtx X;
01232 {
01233 if (GET_CODE (X) == PLUS)
01234 return 1;
01235 else if (GET_CODE (X) == LO_SUM)
01236 return 1;
01237 else if (GET_CODE (X) == HIGH)
01238 return 2;
01239 return 4;
01240 }
01241
01242
01243
01244 static inline rtx
01245 force_mode (mode, orig)
01246 enum machine_mode mode;
01247 rtx orig;
01248 {
01249 if (mode == GET_MODE (orig))
01250 return orig;
01251
01252 if (REGNO (orig) >= FIRST_PSEUDO_REGISTER)
01253 abort ();
01254
01255 return gen_rtx_REG (mode, REGNO (orig));
01256 }
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268 int
01269 emit_move_sequence (operands, mode, scratch_reg)
01270 rtx *operands;
01271 enum machine_mode mode;
01272 rtx scratch_reg;
01273 {
01274 register rtx operand0 = operands[0];
01275 register rtx operand1 = operands[1];
01276 register rtx tem;
01277
01278 if (scratch_reg
01279 && reload_in_progress && GET_CODE (operand0) == REG
01280 && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)
01281 operand0 = reg_equiv_mem[REGNO (operand0)];
01282 else if (scratch_reg
01283 && reload_in_progress && GET_CODE (operand0) == SUBREG
01284 && GET_CODE (SUBREG_REG (operand0)) == REG
01285 && REGNO (SUBREG_REG (operand0)) >= FIRST_PSEUDO_REGISTER)
01286 {
01287
01288
01289 rtx temp = gen_rtx_SUBREG (GET_MODE (operand0),
01290 reg_equiv_mem [REGNO (SUBREG_REG (operand0))],
01291 SUBREG_BYTE (operand0));
01292 operand0 = alter_subreg (&temp);
01293 }
01294
01295 if (scratch_reg
01296 && reload_in_progress && GET_CODE (operand1) == REG
01297 && REGNO (operand1) >= FIRST_PSEUDO_REGISTER)
01298 operand1 = reg_equiv_mem[REGNO (operand1)];
01299 else if (scratch_reg
01300 && reload_in_progress && GET_CODE (operand1) == SUBREG
01301 && GET_CODE (SUBREG_REG (operand1)) == REG
01302 && REGNO (SUBREG_REG (operand1)) >= FIRST_PSEUDO_REGISTER)
01303 {
01304
01305
01306 rtx temp = gen_rtx_SUBREG (GET_MODE (operand1),
01307 reg_equiv_mem [REGNO (SUBREG_REG (operand1))],
01308 SUBREG_BYTE (operand1));
01309 operand1 = alter_subreg (&temp);
01310 }
01311
01312 if (scratch_reg && reload_in_progress && GET_CODE (operand0) == MEM
01313 && ((tem = find_replacement (&XEXP (operand0, 0)))
01314 != XEXP (operand0, 0)))
01315 operand0 = gen_rtx_MEM (GET_MODE (operand0), tem);
01316 if (scratch_reg && reload_in_progress && GET_CODE (operand1) == MEM
01317 && ((tem = find_replacement (&XEXP (operand1, 0)))
01318 != XEXP (operand1, 0)))
01319 operand1 = gen_rtx_MEM (GET_MODE (operand1), tem);
01320
01321
01322
01323
01324 if (fp_reg_operand (operand0, mode)
01325 && ((GET_CODE (operand1) == MEM
01326 && ! memory_address_p (DFmode, XEXP (operand1, 0)))
01327 || ((GET_CODE (operand1) == SUBREG
01328 && GET_CODE (XEXP (operand1, 0)) == MEM
01329 && !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0)))))
01330 && scratch_reg)
01331 {
01332 if (GET_CODE (operand1) == SUBREG)
01333 operand1 = XEXP (operand1, 0);
01334
01335
01336
01337
01338 scratch_reg = force_mode (word_mode, scratch_reg);
01339
01340
01341
01342 if (!memory_address_p (Pmode, XEXP (operand1, 0)))
01343 {
01344 emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));
01345 emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1, 0)),
01346 Pmode,
01347 XEXP (XEXP (operand1, 0), 0),
01348 scratch_reg));
01349 }
01350 else
01351 emit_move_insn (scratch_reg, XEXP (operand1, 0));
01352 emit_insn (gen_rtx_SET (VOIDmode, operand0,
01353 gen_rtx_MEM (mode, scratch_reg)));
01354 return 1;
01355 }
01356 else if (fp_reg_operand (operand1, mode)
01357 && ((GET_CODE (operand0) == MEM
01358 && ! memory_address_p (DFmode, XEXP (operand0, 0)))
01359 || ((GET_CODE (operand0) == SUBREG)
01360 && GET_CODE (XEXP (operand0, 0)) == MEM
01361 && !memory_address_p (DFmode, XEXP (XEXP (operand0, 0), 0))))
01362 && scratch_reg)
01363 {
01364 if (GET_CODE (operand0) == SUBREG)
01365 operand0 = XEXP (operand0, 0);
01366
01367
01368
01369
01370 scratch_reg = force_mode (word_mode, scratch_reg);
01371
01372
01373
01374 if (!memory_address_p (Pmode, XEXP (operand0, 0)))
01375 {
01376 emit_move_insn (scratch_reg, XEXP (XEXP (operand0, 0), 1));
01377 emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand0,
01378 0)),
01379 Pmode,
01380 XEXP (XEXP (operand0, 0),
01381 0),
01382 scratch_reg));
01383 }
01384 else
01385 emit_move_insn (scratch_reg, XEXP (operand0, 0));
01386 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (mode, scratch_reg),
01387 operand1));
01388 return 1;
01389 }
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399 else if (fp_reg_operand (operand0, mode)
01400 && CONSTANT_P (operand1)
01401 && scratch_reg)
01402 {
01403 rtx xoperands[2];
01404
01405
01406
01407
01408 scratch_reg = force_mode (word_mode, scratch_reg);
01409
01410
01411
01412 xoperands[0] = scratch_reg;
01413 xoperands[1] = XEXP (force_const_mem (mode, operand1), 0);
01414 emit_move_sequence (xoperands, Pmode, 0);
01415
01416
01417 emit_insn (gen_rtx_SET (mode, operand0,
01418 gen_rtx_MEM (mode, scratch_reg)));
01419 return 1;
01420 }
01421
01422
01423 else if (GET_CODE (operand0) == REG
01424 && REGNO (operand0) < FIRST_PSEUDO_REGISTER
01425 && REGNO_REG_CLASS (REGNO (operand0)) == SHIFT_REGS
01426 && (GET_CODE (operand1) == MEM
01427 || GET_CODE (operand1) == CONST_INT
01428 || (GET_CODE (operand1) == REG
01429 && FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1)))))
01430 && scratch_reg)
01431 {
01432
01433
01434 if (GET_CODE (operand1) == MEM
01435 && !memory_address_p (Pmode, XEXP (operand1, 0)))
01436 {
01437
01438
01439 scratch_reg = force_mode (word_mode, scratch_reg);
01440
01441 emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));
01442 emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1,
01443 0)),
01444 Pmode,
01445 XEXP (XEXP (operand1, 0),
01446 0),
01447 scratch_reg));
01448
01449
01450
01451
01452
01453 scratch_reg = force_mode (GET_MODE (operand0), scratch_reg);
01454
01455 emit_move_insn (scratch_reg, gen_rtx_MEM (GET_MODE (operand0),
01456 scratch_reg));
01457 }
01458 else
01459 {
01460
01461
01462 scratch_reg = force_mode (GET_MODE (operand0), scratch_reg);
01463
01464 emit_move_insn (scratch_reg, operand1);
01465 }
01466
01467
01468
01469
01470 emit_move_insn (operand0, scratch_reg);
01471 return 1;
01472 }
01473
01474 else if (register_operand (operand0, mode))
01475 {
01476 if (register_operand (operand1, mode)
01477 || (GET_CODE (operand1) == CONST_INT
01478 && cint_ok_for_move (INTVAL (operand1)))
01479 || (operand1 == CONST0_RTX (mode))
01480 || (GET_CODE (operand1) == HIGH
01481 && !symbolic_operand (XEXP (operand1, 0), VOIDmode))
01482
01483 || GET_CODE (operand1) == MEM)
01484 {
01485
01486 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
01487 return 1;
01488 }
01489 }
01490 else if (GET_CODE (operand0) == MEM)
01491 {
01492 if (mode == DFmode && operand1 == CONST0_RTX (mode)
01493 && !(reload_in_progress || reload_completed))
01494 {
01495 rtx temp = gen_reg_rtx (DFmode);
01496
01497 emit_insn (gen_rtx_SET (VOIDmode, temp, operand1));
01498 emit_insn (gen_rtx_SET (VOIDmode, operand0, temp));
01499 return 1;
01500 }
01501 if (register_operand (operand1, mode) || operand1 == CONST0_RTX (mode))
01502 {
01503
01504 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
01505 return 1;
01506 }
01507 if (! (reload_in_progress || reload_completed))
01508 {
01509 operands[0] = validize_mem (operand0);
01510 operands[1] = operand1 = force_reg (mode, operand1);
01511 }
01512 }
01513
01514
01515
01516
01517
01518 if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
01519 || function_label_operand (operand1, mode)
01520 || (GET_CODE (operand1) == HIGH
01521 && symbolic_operand (XEXP (operand1, 0), mode)))
01522 {
01523 int ishighonly = 0;
01524
01525 if (GET_CODE (operand1) == HIGH)
01526 {
01527 ishighonly = 1;
01528 operand1 = XEXP (operand1, 0);
01529 }
01530 if (symbolic_operand (operand1, mode))
01531 {
01532
01533
01534
01535
01536
01537 if ((GET_CODE (operand1) == CONST
01538 && GET_CODE (XEXP (operand1, 0)) == PLUS
01539 && function_label_operand (XEXP (XEXP (operand1, 0), 0), Pmode))
01540 || function_label_operand (operand1, mode))
01541 {
01542 rtx temp, const_part;
01543
01544
01545 if (reload_in_progress || reload_completed)
01546 {
01547 scratch_reg = scratch_reg ? scratch_reg : operand0;
01548
01549
01550
01551 scratch_reg = force_mode (word_mode, scratch_reg);
01552 }
01553 else if (flag_pic)
01554 scratch_reg = gen_reg_rtx (Pmode);
01555
01556 if (GET_CODE (operand1) == CONST)
01557 {
01558
01559 const_part = XEXP (XEXP (operand1, 0), 1);
01560 if (GET_CODE (const_part) != CONST_INT)
01561 abort ();
01562
01563
01564 temp = force_const_mem (mode, XEXP (XEXP (operand1, 0), 0));
01565 }
01566 else
01567 {
01568
01569 const_part = NULL_RTX;
01570
01571
01572 temp = force_const_mem (mode, operand1);
01573 }
01574
01575
01576
01577
01578 temp = XEXP (temp, 0);
01579 if (flag_pic)
01580 temp = legitimize_pic_address (temp, mode, scratch_reg);
01581
01582
01583
01584 operands[1] = temp;
01585 emit_move_sequence (operands, mode, scratch_reg);
01586
01587
01588
01589 operands[1] = gen_rtx_MEM (Pmode, operands[0]);
01590 emit_move_sequence (operands, mode, scratch_reg);
01591
01592
01593 if (const_part != NULL_RTX)
01594 expand_inc (operand0, const_part);
01595
01596 return 1;
01597 }
01598
01599 if (flag_pic)
01600 {
01601 rtx temp;
01602
01603 if (reload_in_progress || reload_completed)
01604 {
01605 temp = scratch_reg ? scratch_reg : operand0;
01606
01607
01608
01609 temp = force_mode (word_mode, temp);
01610 }
01611 else
01612 temp = gen_reg_rtx (Pmode);
01613
01614
01615
01616
01617 if (GET_CODE (operand1) == CONST
01618 && GET_CODE (XEXP (operand1, 0)) == PLUS
01619 && GET_CODE (XEXP (XEXP (operand1, 0), 1)) == CONST_INT
01620 && !INT_14_BITS (XEXP (XEXP (operand1, 0), 1))
01621 && (reload_completed || reload_in_progress)
01622 && flag_pic)
01623 {
01624 operands[1] = force_const_mem (mode, operand1);
01625 operands[1] = legitimize_pic_address (XEXP (operands[1], 0),
01626 mode, temp);
01627 emit_move_sequence (operands, mode, temp);
01628 }
01629 else
01630 {
01631 operands[1] = legitimize_pic_address (operand1, mode, temp);
01632 emit_insn (gen_rtx_SET (VOIDmode, operand0, operands[1]));
01633 }
01634 }
01635
01636
01637
01638 else
01639 {
01640 rtx temp, set;
01641
01642 if (reload_in_progress || reload_completed)
01643 {
01644 temp = scratch_reg ? scratch_reg : operand0;
01645
01646
01647
01648 temp = force_mode (word_mode, temp);
01649 }
01650 else
01651 temp = gen_reg_rtx (mode);
01652
01653
01654
01655
01656
01657 if (GET_CODE (operand0) == REG
01658 && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)
01659 REG_POINTER (operand0) = 1;
01660 if (REGNO (temp) >= FIRST_PSEUDO_REGISTER)
01661 REG_POINTER (temp) = 1;
01662 if (ishighonly)
01663 set = gen_rtx_SET (mode, operand0, temp);
01664 else
01665 set = gen_rtx_SET (VOIDmode,
01666 operand0,
01667 gen_rtx_LO_SUM (mode, temp, operand1));
01668
01669 emit_insn (gen_rtx_SET (VOIDmode,
01670 temp,
01671 gen_rtx_HIGH (mode, operand1)));
01672 emit_insn (set);
01673
01674 }
01675 return 1;
01676 }
01677 else if (GET_CODE (operand1) != CONST_INT
01678 || ! cint_ok_for_move (INTVAL (operand1)))
01679 {
01680 rtx extend = NULL_RTX;
01681 rtx temp;
01682
01683 if (TARGET_64BIT && GET_CODE (operand1) == CONST_INT
01684 && HOST_BITS_PER_WIDE_INT > 32
01685 && GET_MODE_BITSIZE (GET_MODE (operand0)) > 32)
01686 {
01687 HOST_WIDE_INT val = INTVAL (operand1);
01688 HOST_WIDE_INT nval;
01689
01690
01691
01692
01693
01694
01695 nval = ((val & (((HOST_WIDE_INT) 2 << 31) - 1))
01696 ^ ((HOST_WIDE_INT) 1 << 31)) - ((HOST_WIDE_INT) 1 << 31);
01697 if (val != nval)
01698 {
01699 #if HOST_BITS_PER_WIDE_INT > 32
01700 extend = GEN_INT (val >> 32);
01701 #endif
01702 operand1 = GEN_INT (nval);
01703 }
01704 }
01705
01706 if (reload_in_progress || reload_completed)
01707 temp = operand0;
01708 else
01709 temp = gen_reg_rtx (mode);
01710
01711
01712
01713
01714 if (GET_CODE (operand1) == CONST_INT
01715 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
01716 {
01717
01718
01719
01720
01721
01722
01723 HOST_WIDE_INT value = INTVAL (operand1);
01724 HOST_WIDE_INT low = value & 0x3fff;
01725 HOST_WIDE_INT high = value & ~ 0x3fff;
01726
01727 if (low >= 0x2000)
01728 {
01729 if (high == 0x7fffc000 || (mode == HImode && high == 0x4000))
01730 high += 0x2000;
01731 else
01732 high += 0x4000;
01733 }
01734
01735 low = value - high;
01736
01737 emit_insn (gen_rtx_SET (VOIDmode, temp, GEN_INT (high)));
01738 operands[1] = gen_rtx_PLUS (mode, temp, GEN_INT (low));
01739 }
01740 else
01741 {
01742 emit_insn (gen_rtx_SET (VOIDmode, temp,
01743 gen_rtx_HIGH (mode, operand1)));
01744 operands[1] = gen_rtx_LO_SUM (mode, temp, operand1);
01745 }
01746
01747 emit_move_insn (operands[0], operands[1]);
01748
01749 if (extend != NULL_RTX)
01750 emit_insn (gen_insv (operands[0], GEN_INT (32), const0_rtx,
01751 extend));
01752
01753 return 1;
01754 }
01755 }
01756
01757 return 0;
01758 }
01759
01760
01761
01762
01763 int
01764 reloc_needed (exp)
01765 tree exp;
01766 {
01767 int reloc = 0;
01768
01769 switch (TREE_CODE (exp))
01770 {
01771 case ADDR_EXPR:
01772 return 1;
01773
01774 case PLUS_EXPR:
01775 case MINUS_EXPR:
01776 reloc = reloc_needed (TREE_OPERAND (exp, 0));
01777 reloc |= reloc_needed (TREE_OPERAND (exp, 1));
01778 break;
01779
01780 case NOP_EXPR:
01781 case CONVERT_EXPR:
01782 case NON_LVALUE_EXPR:
01783 reloc = reloc_needed (TREE_OPERAND (exp, 0));
01784 break;
01785
01786 case CONSTRUCTOR:
01787 {
01788 register tree link;
01789 for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
01790 if (TREE_VALUE (link) != 0)
01791 reloc |= reloc_needed (TREE_VALUE (link));
01792 }
01793 break;
01794
01795 case ERROR_MARK:
01796 break;
01797
01798 default:
01799 break;
01800 }
01801 return reloc;
01802 }
01803
01804
01805
01806
01807 int
01808 read_only_operand (operand, mode)
01809 rtx operand;
01810 enum machine_mode mode ATTRIBUTE_UNUSED;
01811 {
01812 if (GET_CODE (operand) == CONST)
01813 operand = XEXP (XEXP (operand, 0), 0);
01814 if (flag_pic)
01815 {
01816 if (GET_CODE (operand) == SYMBOL_REF)
01817 return SYMBOL_REF_FLAG (operand) && !CONSTANT_POOL_ADDRESS_P (operand);
01818 }
01819 else
01820 {
01821 if (GET_CODE (operand) == SYMBOL_REF)
01822 return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
01823 }
01824 return 1;
01825 }
01826
01827
01828
01829
01830 const char *
01831 singlemove_string (operands)
01832 rtx *operands;
01833 {
01834 HOST_WIDE_INT intval;
01835
01836 if (GET_CODE (operands[0]) == MEM)
01837 return "stw %r1,%0";
01838 if (GET_CODE (operands[1]) == MEM)
01839 return "ldw %1,%0";
01840 if (GET_CODE (operands[1]) == CONST_DOUBLE)
01841 {
01842 long i;
01843 REAL_VALUE_TYPE d;
01844
01845 if (GET_MODE (operands[1]) != SFmode)
01846 abort ();
01847
01848
01849
01850 REAL_VALUE_FROM_CONST_DOUBLE (d, operands[1]);
01851 REAL_VALUE_TO_TARGET_SINGLE (d, i);
01852
01853 operands[1] = GEN_INT (i);
01854
01855 }
01856 if (GET_CODE (operands[1]) == CONST_INT)
01857 {
01858 intval = INTVAL (operands[1]);
01859
01860 if (VAL_14_BITS_P (intval))
01861 return "ldi %1,%0";
01862 else if ((intval & 0x7ff) == 0)
01863 return "ldil L'%1,%0";
01864 else if (zdepi_cint_p (intval))
01865 return "{zdepi %Z1,%0|depwi,z %Z1,%0}";
01866 else
01867 return "ldil L'%1,%0\n\tldo R'%1(%0),%0";
01868 }
01869 return "copy %1,%0";
01870 }
01871
01872
01873
01874
01875
01876 static void
01877 compute_zdepwi_operands (imm, op)
01878 unsigned HOST_WIDE_INT imm;
01879 unsigned *op;
01880 {
01881 int lsb, len;
01882
01883
01884 for (lsb = 0; lsb < 32; lsb++)
01885 {
01886 if ((imm & 1) != 0)
01887 break;
01888 imm >>= 1;
01889 }
01890
01891
01892 if ((imm & 0x10) == 0)
01893 len = (lsb <= 28) ? 4 : 32 - lsb;
01894 else
01895 {
01896
01897 for (len = 5; len < 32; len++)
01898 {
01899 if ((imm & (1 << len)) == 0)
01900 break;
01901 }
01902
01903
01904 imm = (imm & 0xf) - 0x10;
01905 }
01906
01907 op[0] = imm;
01908 op[1] = 31 - lsb;
01909 op[2] = len;
01910 }
01911
01912
01913
01914
01915 void
01916 compute_zdepdi_operands (imm, op)
01917 unsigned HOST_WIDE_INT imm;
01918 unsigned *op;
01919 {
01920 HOST_WIDE_INT lsb, len;
01921
01922
01923 for (lsb = 0; lsb < HOST_BITS_PER_WIDE_INT; lsb++)
01924 {
01925 if ((imm & 1) != 0)
01926 break;
01927 imm >>= 1;
01928 }
01929
01930
01931 if ((imm & 0x10) == 0)
01932 len = ((lsb <= HOST_BITS_PER_WIDE_INT - 4)
01933 ? 4 : HOST_BITS_PER_WIDE_INT - lsb);
01934 else
01935 {
01936
01937 for (len = 5; len < HOST_BITS_PER_WIDE_INT; len++)
01938 {
01939 if ((imm & ((unsigned HOST_WIDE_INT) 1 << len)) == 0)
01940 break;
01941 }
01942
01943
01944 imm = (imm & 0xf) - 0x10;
01945 }
01946
01947 op[0] = imm;
01948 op[1] = 63 - lsb;
01949 op[2] = len;
01950 }
01951
01952
01953
01954
01955 const char *
01956 output_move_double (operands)
01957 rtx *operands;
01958 {
01959 enum { REGOP, OFFSOP, MEMOP, CNSTOP, RNDOP } optype0, optype1;
01960 rtx latehalf[2];
01961 rtx addreg0 = 0, addreg1 = 0;
01962
01963
01964
01965 if (REG_P (operands[0]))
01966 optype0 = REGOP;
01967 else if (offsettable_memref_p (operands[0]))
01968 optype0 = OFFSOP;
01969 else if (GET_CODE (operands[0]) == MEM)
01970 optype0 = MEMOP;
01971 else
01972 optype0 = RNDOP;
01973
01974 if (REG_P (operands[1]))
01975 optype1 = REGOP;
01976 else if (CONSTANT_P (operands[1]))
01977 optype1 = CNSTOP;
01978 else if (offsettable_memref_p (operands[1]))
01979 optype1 = OFFSOP;
01980 else if (GET_CODE (operands[1]) == MEM)
01981 optype1 = MEMOP;
01982 else
01983 optype1 = RNDOP;
01984
01985
01986
01987
01988
01989 if (optype0 != REGOP && optype1 != REGOP)
01990 abort ();
01991
01992
01993
01994
01995
01996
01997
01998 if (optype0 == MEMOP)
01999 {
02000
02001
02002
02003 rtx addr = XEXP (operands[0], 0);
02004 if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)
02005 {
02006 rtx high_reg = gen_rtx_SUBREG (SImode, operands[1], 0);
02007
02008 operands[0] = XEXP (addr, 0);
02009 if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)
02010 abort ();
02011
02012 if (!reg_overlap_mentioned_p (high_reg, addr))
02013 {
02014
02015
02016
02017 if (GET_CODE (addr) == POST_INC)
02018 return "{stws|stw},ma %1,8(%0)\n\tstw %R1,-4(%0)";
02019 return "{stws|stw},ma %1,-8(%0)\n\tstw %R1,12(%0)";
02020 }
02021 else
02022 abort ();
02023 }
02024 else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
02025 {
02026 rtx high_reg = gen_rtx_SUBREG (SImode, operands[1], 0);
02027
02028 operands[0] = XEXP (addr, 0);
02029 if (GET_CODE (operands[1]) != REG || GET_CODE (operands[0]) != REG)
02030 abort ();
02031
02032 if (!reg_overlap_mentioned_p (high_reg, addr))
02033 {
02034
02035
02036
02037 if (GET_CODE (addr) == PRE_INC)
02038 return "{stws|stw},mb %1,8(%0)\n\tstw %R1,4(%0)";
02039 return "{stws|stw},mb %1,-8(%0)\n\tstw %R1,4(%0)";
02040 }
02041 else
02042 abort ();
02043 }
02044 }
02045 if (optype1 == MEMOP)
02046 {
02047
02048
02049
02050 rtx addr = XEXP (operands[1], 0);
02051 if (GET_CODE (addr) == POST_INC || GET_CODE (addr) == POST_DEC)
02052 {
02053 rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0);
02054
02055 operands[1] = XEXP (addr, 0);
02056 if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG)
02057 abort ();
02058
02059 if (!reg_overlap_mentioned_p (high_reg, addr))
02060 {
02061
02062
02063
02064 if (GET_CODE (addr) == POST_INC)
02065 return "{ldws|ldw},ma 8(%1),%0\n\tldw -4(%1),%R0";
02066 return "{ldws|ldw},ma -8(%1),%0\n\tldw 12(%1),%R0";
02067 }
02068 else
02069 {
02070
02071
02072
02073 if (GET_CODE (addr) == POST_INC)
02074 return "ldw 4(%1),%R0\n\t{ldws|ldw},ma 8(%1),%0";
02075 return "ldw 4(%1),%R0\n\t{ldws|ldw},ma -8(%1),%0";
02076 }
02077 }
02078 else if (GET_CODE (addr) == PRE_INC || GET_CODE (addr) == PRE_DEC)
02079 {
02080 rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0);
02081
02082 operands[1] = XEXP (addr, 0);
02083 if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG)
02084 abort ();
02085
02086 if (!reg_overlap_mentioned_p (high_reg, addr))
02087 {
02088
02089
02090
02091 if (GET_CODE (addr) == PRE_INC)
02092 return "{ldws|ldw},mb 8(%1),%0\n\tldw 4(%1),%R0";
02093 return "{ldws|ldw},mb -8(%1),%0\n\tldw 4(%1),%R0";
02094 }
02095 else
02096 {
02097
02098
02099
02100 if (GET_CODE (addr) == PRE_INC)
02101 return "ldw 12(%1),%R0\n\t{ldws|ldw},mb 8(%1),%0";
02102 return "ldw -4(%1),%R0\n\t{ldws|ldw},mb -8(%1),%0";
02103 }
02104 }
02105 else if (GET_CODE (addr) == PLUS
02106 && GET_CODE (XEXP (addr, 0)) == MULT)
02107 {
02108 rtx high_reg = gen_rtx_SUBREG (SImode, operands[0], 0);
02109
02110 if (!reg_overlap_mentioned_p (high_reg, addr))
02111 {
02112 rtx xoperands[3];
02113
02114 xoperands[0] = high_reg;
02115 xoperands[1] = XEXP (addr, 1);
02116 xoperands[2] = XEXP (XEXP (addr, 0), 0);
02117 xoperands[3] = XEXP (XEXP (addr, 0), 1);
02118 output_asm_insn ("{sh%O3addl %2,%1,%0|shladd,l %2,%O3,%1,%0}",
02119 xoperands);
02120 return "ldw 4(%0),%R0\n\tldw 0(%0),%0";
02121 }
02122 else
02123 {
02124 rtx xoperands[3];
02125
02126 xoperands[0] = high_reg;
02127 xoperands[1] = XEXP (addr, 1);
02128 xoperands[2] = XEXP (XEXP (addr, 0), 0);
02129 xoperands[3] = XEXP (XEXP (addr, 0), 1);
02130 output_asm_insn ("{sh%O3addl %2,%1,%R0|shladd,l %2,%O3,%1,%R0}",
02131 xoperands);
02132 return "ldw 0(%R0),%0\n\tldw 4(%R0),%R0";
02133 }
02134 }
02135 }
02136
02137
02138
02139
02140 if (optype0 == MEMOP)
02141 addreg0 = find_addr_reg (XEXP (operands[0], 0));
02142
02143 if (optype1 == MEMOP)
02144 addreg1 = find_addr_reg (XEXP (operands[1], 0));
02145
02146
02147
02148
02149
02150
02151
02152
02153 if (optype0 == REGOP)
02154 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
02155 else if (optype0 == OFFSOP)
02156 latehalf[0] = adjust_address (operands[0], SImode, 4);
02157 else
02158 latehalf[0] = operands[0];
02159
02160 if (optype1 == REGOP)
02161 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
02162 else if (optype1 == OFFSOP)
02163 latehalf[1] = adjust_address (operands[1], SImode, 4);
02164 else if (optype1 == CNSTOP)
02165 split_double (operands[1], &operands[1], &latehalf[1]);
02166 else
02167 latehalf[1] = operands[1];
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185 if (optype0 == REGOP
02186 && (optype1 == MEMOP || optype1 == OFFSOP)
02187 && refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
02188 operands[1], 0))
02189 {
02190
02191 if (addreg1)
02192 output_asm_insn ("ldo 4(%0),%0", &addreg1);
02193 output_asm_insn (singlemove_string (latehalf), latehalf);
02194
02195
02196 if (addreg1)
02197 output_asm_insn ("ldo -4(%0),%0", &addreg1);
02198 return singlemove_string (operands);
02199 }
02200
02201
02202 if (optype0 == REGOP && optype1 == REGOP
02203 && REGNO (operands[0]) == REGNO (operands[1]) + 1)
02204 {
02205 output_asm_insn (singlemove_string (latehalf), latehalf);
02206 return singlemove_string (operands);
02207 }
02208
02209
02210
02211 output_asm_insn (singlemove_string (operands), operands);
02212
02213
02214 if (addreg0)
02215 output_asm_insn ("ldo 4(%0),%0", &addreg0);
02216 if (addreg1)
02217 output_asm_insn ("ldo 4(%0),%0", &addreg1);
02218
02219
02220 output_asm_insn (singlemove_string (latehalf), latehalf);
02221
02222
02223 if (addreg0)
02224 output_asm_insn ("ldo -4(%0),%0", &addreg0);
02225 if (addreg1)
02226 output_asm_insn ("ldo -4(%0),%0", &addreg1);
02227
02228 return "";
02229 }
02230
02231 const char *
02232 output_fp_move_double (operands)
02233 rtx *operands;
02234 {
02235 if (FP_REG_P (operands[0]))
02236 {
02237 if (FP_REG_P (operands[1])
02238 || operands[1] == CONST0_RTX (GET_MODE (operands[0])))
02239 output_asm_insn ("fcpy,dbl %f1,%0", operands);
02240 else
02241 output_asm_insn ("fldd%F1 %1,%0", operands);
02242 }
02243 else if (FP_REG_P (operands[1]))
02244 {
02245 output_asm_insn ("fstd%F0 %1,%0", operands);
02246 }
02247 else if (operands[1] == CONST0_RTX (GET_MODE (operands[0])))
02248 {
02249 if (GET_CODE (operands[0]) == REG)
02250 {
02251 rtx xoperands[2];
02252 xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
02253 xoperands[0] = operands[0];
02254 output_asm_insn ("copy %%r0,%0\n\tcopy %%r0,%1", xoperands);
02255 }
02256
02257
02258
02259
02260 else
02261 abort ();
02262 }
02263 else abort ();
02264 return "";
02265 }
02266
02267
02268
02269
02270 static rtx
02271 find_addr_reg (addr)
02272 rtx addr;
02273 {
02274 while (GET_CODE (addr) == PLUS)
02275 {
02276 if (GET_CODE (XEXP (addr, 0)) == REG)
02277 addr = XEXP (addr, 0);
02278 else if (GET_CODE (XEXP (addr, 1)) == REG)
02279 addr = XEXP (addr, 1);
02280 else if (CONSTANT_P (XEXP (addr, 0)))
02281 addr = XEXP (addr, 1);
02282 else if (CONSTANT_P (XEXP (addr, 1)))
02283 addr = XEXP (addr, 0);
02284 else
02285 abort ();
02286 }
02287 if (GET_CODE (addr) == REG)
02288 return addr;
02289 abort ();
02290 }
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302 const char *
02303 output_block_move (operands, size_is_constant)
02304 rtx *operands;
02305 int size_is_constant ATTRIBUTE_UNUSED;
02306 {
02307 int align = INTVAL (operands[5]);
02308 unsigned long n_bytes = INTVAL (operands[4]);
02309
02310
02311
02312 if (align > 4)
02313 align = 4;
02314
02315
02316
02317 switch (align)
02318 {
02319 case 4:
02320
02321 operands[4] = GEN_INT (n_bytes - 8);
02322 output_asm_insn ("ldi %4,%2", operands);
02323
02324
02325 output_asm_insn ("{ldws|ldw},ma 4(%1),%3", operands);
02326 output_asm_insn ("{ldws|ldw},ma 4(%1),%6", operands);
02327 output_asm_insn ("{stws|stw},ma %3,4(%0)", operands);
02328 output_asm_insn ("addib,>= -8,%2,.-12", operands);
02329 output_asm_insn ("{stws|stw},ma %6,4(%0)", operands);
02330
02331
02332
02333 if (n_bytes % 8 != 0)
02334 {
02335 operands[4] = GEN_INT (n_bytes % 4);
02336 if (n_bytes % 8 >= 4)
02337 output_asm_insn ("{ldws|ldw},ma 4(%1),%3", operands);
02338 if (n_bytes % 4 != 0)
02339 output_asm_insn ("ldw 0(%1),%6", operands);
02340 if (n_bytes % 8 >= 4)
02341 output_asm_insn ("{stws|stw},ma %3,4(%0)", operands);
02342 if (n_bytes % 4 != 0)
02343 output_asm_insn ("{stbys|stby},e %6,%4(%0)", operands);
02344 }
02345 return "";
02346
02347 case 2:
02348
02349 operands[4] = GEN_INT (n_bytes - 4);
02350 output_asm_insn ("ldi %4,%2", operands);
02351
02352
02353 output_asm_insn ("{ldhs|ldh},ma 2(%1),%3", operands);
02354 output_asm_insn ("{ldhs|ldh},ma 2(%1),%6", operands);
02355 output_asm_insn ("{sths|sth},ma %3,2(%0)", operands);
02356 output_asm_insn ("addib,>= -4,%2,.-12", operands);
02357 output_asm_insn ("{sths|sth},ma %6,2(%0)", operands);
02358
02359
02360 if (n_bytes % 4 != 0)
02361 {
02362 if (n_bytes % 4 >= 2)
02363 output_asm_insn ("{ldhs|ldh},ma 2(%1),%3", operands);
02364 if (n_bytes % 2 != 0)
02365 output_asm_insn ("ldb 0(%1),%6", operands);
02366 if (n_bytes % 4 >= 2)
02367 output_asm_insn ("{sths|sth},ma %3,2(%0)", operands);
02368 if (n_bytes % 2 != 0)
02369 output_asm_insn ("stb %6,0(%0)", operands);
02370 }
02371 return "";
02372
02373 case 1:
02374
02375 operands[4] = GEN_INT (n_bytes - 2);
02376 output_asm_insn ("ldi %4,%2", operands);
02377
02378
02379 output_asm_insn ("{ldbs|ldb},ma 1(%1),%3", operands);
02380 output_asm_insn ("{ldbs|ldb},ma 1(%1),%6", operands);
02381 output_asm_insn ("{stbs|stb},ma %3,1(%0)", operands);
02382 output_asm_insn ("addib,>= -2,%2,.-12", operands);
02383 output_asm_insn ("{stbs|stb},ma %6,1(%0)", operands);
02384
02385
02386 if (n_bytes % 2 != 0)
02387 {
02388 output_asm_insn ("ldb 0(%1),%3", operands);
02389 output_asm_insn ("stb %3,0(%0)", operands);
02390 }
02391 return "";
02392
02393 default:
02394 abort ();
02395 }
02396 }
02397
02398
02399
02400
02401
02402
02403 static int
02404 compute_movstrsi_length (insn)
02405 rtx insn;
02406 {
02407 rtx pat = PATTERN (insn);
02408 unsigned int align = INTVAL (XEXP (XVECEXP (pat, 0, 7), 0));
02409 unsigned long n_bytes = INTVAL (XEXP (XVECEXP (pat, 0, 6), 0));
02410 unsigned int n_insns = 0;
02411
02412
02413
02414 if (align > 4)
02415 align = 4;
02416
02417
02418 n_insns = 6;
02419
02420
02421 if (n_bytes % (2 * align) != 0)
02422 {
02423 if ((n_bytes % (2 * align)) >= align)
02424 n_insns += 2;
02425
02426 if ((n_bytes % align) != 0)
02427 n_insns += 2;
02428 }
02429
02430
02431 return n_insns * 4;
02432 }
02433
02434
02435 const char *
02436 output_and (operands)
02437 rtx *operands;
02438 {
02439 if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
02440 {
02441 unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
02442 int ls0, ls1, ms0, p, len;
02443
02444 for (ls0 = 0; ls0 < 32; ls0++)
02445 if ((mask & (1 << ls0)) == 0)
02446 break;
02447
02448 for (ls1 = ls0; ls1 < 32; ls1++)
02449 if ((mask & (1 << ls1)) != 0)
02450 break;
02451
02452 for (ms0 = ls1; ms0 < 32; ms0++)
02453 if ((mask & (1 << ms0)) == 0)
02454 break;
02455
02456 if (ms0 != 32)
02457 abort ();
02458
02459 if (ls1 == 32)
02460 {
02461 len = ls0;
02462
02463 if (len == 0)
02464 abort ();
02465
02466 operands[2] = GEN_INT (len);
02467 return "{extru|extrw,u} %1,31,%2,%0";
02468 }
02469 else
02470 {
02471
02472
02473
02474 p = 31 - ls0;
02475 len = ls1 - ls0;
02476
02477 operands[2] = GEN_INT (p);
02478 operands[3] = GEN_INT (len);
02479 return "{depi|depwi} 0,%2,%3,%0";
02480 }
02481 }
02482 else
02483 return "and %1,%2,%0";
02484 }
02485
02486
02487
02488 const char *
02489 output_64bit_and (operands)
02490 rtx *operands;
02491 {
02492 if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
02493 {
02494 unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
02495 int ls0, ls1, ms0, p, len;
02496
02497 for (ls0 = 0; ls0 < HOST_BITS_PER_WIDE_INT; ls0++)
02498 if ((mask & ((unsigned HOST_WIDE_INT) 1 << ls0)) == 0)
02499 break;
02500
02501 for (ls1 = ls0; ls1 < HOST_BITS_PER_WIDE_INT; ls1++)
02502 if ((mask & ((unsigned HOST_WIDE_INT) 1 << ls1)) != 0)
02503 break;
02504
02505 for (ms0 = ls1; ms0 < HOST_BITS_PER_WIDE_INT; ms0++)
02506 if ((mask & ((unsigned HOST_WIDE_INT) 1 << ms0)) == 0)
02507 break;
02508
02509 if (ms0 != HOST_BITS_PER_WIDE_INT)
02510 abort ();
02511
02512 if (ls1 == HOST_BITS_PER_WIDE_INT)
02513 {
02514 len = ls0;
02515
02516 if (len == 0)
02517 abort ();
02518
02519 operands[2] = GEN_INT (len);
02520 return "extrd,u %1,63,%2,%0";
02521 }
02522 else
02523 {
02524
02525
02526
02527 p = 63 - ls0;
02528 len = ls1 - ls0;
02529
02530 operands[2] = GEN_INT (p);
02531 operands[3] = GEN_INT (len);
02532 return "depdi 0,%2,%3,%0";
02533 }
02534 }
02535 else
02536 return "and %1,%2,%0";
02537 }
02538
02539 const char *
02540 output_ior (operands)
02541 rtx *operands;
02542 {
02543 unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
02544 int bs0, bs1, p, len;
02545
02546 if (INTVAL (operands[2]) == 0)
02547 return "copy %1,%0";
02548
02549 for (bs0 = 0; bs0 < 32; bs0++)
02550 if ((mask & (1 << bs0)) != 0)
02551 break;
02552
02553 for (bs1 = bs0; bs1 < 32; bs1++)
02554 if ((mask & (1 << bs1)) == 0)
02555 break;
02556
02557 if (bs1 != 32 && ((unsigned HOST_WIDE_INT) 1 << bs1) <= mask)
02558 abort ();
02559
02560 p = 31 - bs0;
02561 len = bs1 - bs0;
02562
02563 operands[2] = GEN_INT (p);
02564 operands[3] = GEN_INT (len);
02565 return "{depi|depwi} -1,%2,%3,%0";
02566 }
02567
02568
02569
02570 const char *
02571 output_64bit_ior (operands)
02572 rtx *operands;
02573 {
02574 unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
02575 int bs0, bs1, p, len;
02576
02577 if (INTVAL (operands[2]) == 0)
02578 return "copy %1,%0";
02579
02580 for (bs0 = 0; bs0 < HOST_BITS_PER_WIDE_INT; bs0++)
02581 if ((mask & ((unsigned HOST_WIDE_INT) 1 << bs0)) != 0)
02582 break;
02583
02584 for (bs1 = bs0; bs1 < HOST_BITS_PER_WIDE_INT; bs1++)
02585 if ((mask & ((unsigned HOST_WIDE_INT) 1 << bs1)) == 0)
02586 break;
02587
02588 if (bs1 != HOST_BITS_PER_WIDE_INT
02589 && ((unsigned HOST_WIDE_INT) 1 << bs1) <= mask)
02590 abort ();
02591
02592 p = 63 - bs0;
02593 len = bs1 - bs0;
02594
02595 operands[2] = GEN_INT (p);
02596 operands[3] = GEN_INT (len);
02597 return "depdi -1,%2,%3,%0";
02598 }
02599
02600
02601
02602
02603
02604 static bool
02605 pa_assemble_integer (x, size, aligned_p)
02606 rtx x;
02607 unsigned int size;
02608 int aligned_p;
02609 {
02610 if (size == UNITS_PER_WORD && aligned_p
02611 && function_label_operand (x, VOIDmode))
02612 {
02613 fputs (size == 8? "\t.dword\tP%" : "\t.word\tP%", asm_out_file);
02614 output_addr_const (asm_out_file, x);
02615 fputc ('\n', asm_out_file);
02616 return true;
02617 }
02618 return default_assemble_integer (x, size, aligned_p);
02619 }
02620
02621
02622 void
02623 output_ascii (file, p, size)
02624 FILE *file;
02625 const char *p;
02626 int size;
02627 {
02628 int i;
02629 int chars_output;
02630 unsigned char partial_output[16];
02631
02632
02633
02634
02635
02636
02637
02638 fputs ("\t.STRING \"", file);
02639
02640 chars_output = 0;
02641 for (i = 0; i < size; i += 4)
02642 {
02643 int co = 0;
02644 int io = 0;
02645 for (io = 0, co = 0; io < MIN (4, size - i); io++)
02646 {
02647 register unsigned int c = (unsigned char) p[i + io];
02648
02649 if (c == '\"' || c == '\\')
02650 partial_output[co++] = '\\';
02651 if (c >= ' ' && c < 0177)
02652 partial_output[co++] = c;
02653 else
02654 {
02655 unsigned int hexd;
02656 partial_output[co++] = '\\';
02657 partial_output[co++] = 'x';
02658 hexd = c / 16 - 0 + '0';
02659 if (hexd > '9')
02660 hexd -= '9' - 'a' + 1;
02661 partial_output[co++] = hexd;
02662 hexd = c % 16 - 0 + '0';
02663 if (hexd > '9')
02664 hexd -= '9' - 'a' + 1;
02665 partial_output[co++] = hexd;
02666 }
02667 }
02668 if (chars_output + co > 243)
02669 {
02670 fputs ("\"\n\t.STRING \"", file);
02671 chars_output = 0;
02672 }
02673 fwrite (partial_output, 1, co, file);
02674 chars_output += co;
02675 co = 0;
02676 }
02677 fputs ("\"\n", file);
02678 }
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692 static void
02693 remove_useless_addtr_insns (insns, check_notes)
02694 rtx insns;
02695 int check_notes;
02696 {
02697 rtx insn;
02698 static int pass = 0;
02699
02700
02701 if (optimize > 0)
02702 {
02703 int fcmp_count = 0;
02704 int fbranch_count = 0;
02705
02706
02707
02708 insns = get_insns ();
02709 for (insn = insns; insn; insn = next_insn (insn))
02710 {
02711 rtx tmp;
02712
02713
02714 if (GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN)
02715 continue;
02716
02717 tmp = PATTERN (insn);
02718
02719
02720 if (GET_CODE (tmp) != SET)
02721 continue;
02722
02723
02724 tmp = SET_DEST (tmp);
02725 if (GET_CODE (tmp) == REG && REGNO (tmp) == 0)
02726 {
02727 fcmp_count++;
02728 continue;
02729 }
02730
02731 tmp = PATTERN (insn);
02732
02733 if (GET_CODE (tmp) == SET
02734 && SET_DEST (tmp) == pc_rtx
02735 && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
02736 && GET_CODE (XEXP (SET_SRC (tmp), 0)) == NE
02737 && GET_CODE (XEXP (XEXP (SET_SRC (tmp), 0), 0)) == REG
02738 && REGNO (XEXP (XEXP (SET_SRC (tmp), 0), 0)) == 0)
02739 {
02740 fbranch_count++;
02741 continue;
02742 }
02743 }
02744
02745
02746
02747
02748 for (insn = insns; insn; insn = next_insn (insn))
02749 {
02750 rtx tmp, next;
02751
02752
02753 if (GET_CODE (insn) != INSN)
02754 continue;
02755
02756 tmp = PATTERN (insn);
02757
02758
02759 if (GET_CODE (tmp) != SET)
02760 continue;
02761
02762
02763 tmp = SET_DEST (tmp);
02764 if (GET_CODE (tmp) != REG || REGNO (tmp) != 0)
02765 continue;
02766
02767
02768
02769
02770
02771
02772 next = next_insn (insn);
02773 while (next)
02774 {
02775
02776 if (GET_CODE (next) == JUMP_INSN
02777 || GET_CODE (next) == CALL_INSN
02778 || GET_CODE (next) == CODE_LABEL)
02779 break;
02780
02781
02782 if (GET_CODE (next) == INSN
02783 && GET_CODE (PATTERN (next)) == SET
02784 && GET_CODE (SET_DEST (PATTERN (next))) == REG
02785 && REGNO (SET_DEST (PATTERN (next))) == 0)
02786 break;
02787
02788 next = next_insn (next);
02789 }
02790
02791
02792 if (next
02793 && GET_CODE (next) == JUMP_INSN)
02794 {
02795 rtx pattern = PATTERN (next);
02796
02797
02798
02799
02800 if (GET_CODE (pattern) == SET
02801 && SET_DEST (pattern) == pc_rtx
02802 && GET_CODE (SET_SRC (pattern)) == IF_THEN_ELSE
02803 && GET_CODE (XEXP (SET_SRC (pattern), 0)) == NE
02804 && GET_CODE (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == REG
02805 && REGNO (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == 0
02806 && GET_CODE (XEXP (SET_SRC (pattern), 1)) == PC
02807 && (fcmp_count == fbranch_count
02808 || (check_notes
02809 && find_regno_note (next, REG_DEAD, 0))))
02810 {
02811
02812 tmp = XEXP (SET_SRC (pattern), 1);
02813 XEXP (SET_SRC (pattern), 1) = XEXP (SET_SRC (pattern), 2);
02814 XEXP (SET_SRC (pattern), 2) = tmp;
02815 INSN_CODE (next) = -1;
02816
02817
02818 tmp = PATTERN (insn);
02819 PUT_CODE (XEXP (tmp, 1),
02820 (reverse_condition_maybe_unordered
02821 (GET_CODE (XEXP (tmp, 1)))));
02822 }
02823 }
02824 }
02825 }
02826
02827 pass = !pass;
02828
02829 }
02830
02831
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897 static int actual_fsize;
02898 static int local_fsize, save_fregs;
02899
02900
02901
02902
02903
02904
02905
02906 static void
02907 store_reg (reg, disp, base)
02908 int reg, disp, base;
02909 {
02910 rtx insn, dest, src, basereg;
02911
02912 src = gen_rtx_REG (word_mode, reg);
02913 basereg = gen_rtx_REG (Pmode, base);
02914 if (VAL_14_BITS_P (disp))
02915 {
02916 dest = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
02917 insn = emit_move_insn (dest, src);
02918 }
02919 else
02920 {
02921 rtx delta = GEN_INT (disp);
02922 rtx high = gen_rtx_PLUS (Pmode, basereg, gen_rtx_HIGH (Pmode, delta));
02923 rtx tmpreg = gen_rtx_REG (Pmode, 1);
02924 emit_move_insn (tmpreg, high);
02925 dest = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
02926 insn = emit_move_insn (dest, src);
02927 if (DO_FRAME_NOTES)
02928 {
02929 REG_NOTES (insn)
02930 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
02931 gen_rtx_SET (VOIDmode,
02932 gen_rtx_MEM (word_mode,
02933 gen_rtx_PLUS (word_mode, basereg,
02934 delta)),
02935 src),
02936 REG_NOTES (insn));
02937 }
02938 }
02939
02940 if (DO_FRAME_NOTES)
02941 RTX_FRAME_RELATED_P (insn) = 1;
02942 }
02943
02944
02945
02946
02947
02948
02949
02950 static void
02951 set_reg_plus_d (reg, base, disp)
02952 int reg, base, disp;
02953 {
02954 rtx insn;
02955
02956 if (VAL_14_BITS_P (disp))
02957 {
02958 insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
02959 plus_constant (gen_rtx_REG (Pmode, base), disp));
02960 }
02961 else
02962 {
02963 rtx basereg = gen_rtx_REG (Pmode, base);
02964 rtx delta = GEN_INT (disp);
02965
02966 emit_move_insn (gen_rtx_REG (Pmode, 1),
02967 gen_rtx_PLUS (Pmode, basereg,
02968 gen_rtx_HIGH (Pmode, delta)));
02969 insn = emit_move_insn (gen_rtx_REG (Pmode, reg),
02970 gen_rtx_LO_SUM (Pmode, gen_rtx_REG (Pmode, 1),
02971 delta));
02972 }
02973
02974 if (DO_FRAME_NOTES && reg == STACK_POINTER_REGNUM)
02975 RTX_FRAME_RELATED_P (insn) = 1;
02976 }
02977
02978 int
02979 compute_frame_size (size, fregs_live)
02980 int size;
02981 int *fregs_live;
02982 {
02983 int i, fsize;
02984
02985
02986
02987
02988
02989
02990 fsize = size + (size || frame_pointer_needed ? STARTING_FRAME_OFFSET : 0);
02991
02992
02993 for (i = 18; i >= 3; i--)
02994 if (regs_ever_live[i])
02995 fsize += UNITS_PER_WORD;
02996
02997
02998 fsize = (fsize + 7) & ~7;
02999
03000
03001 for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
03002 if (regs_ever_live[i]
03003 || (! TARGET_64BIT && regs_ever_live[i + 1]))
03004 {
03005 if (fregs_live)
03006 *fregs_live = 1;
03007
03008
03009
03010 fsize += 8;
03011 }
03012
03013
03014
03015 fsize += current_function_outgoing_args_size;
03016
03017
03018
03019
03020 if (!current_function_is_leaf || fsize)
03021 fsize += TARGET_64BIT ? 16 : 32;
03022
03023 return (fsize + STACK_BOUNDARY - 1) & ~(STACK_BOUNDARY - 1);
03024 }
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043 void
03044 pa_output_function_prologue (file, size)
03045 FILE *file;
03046 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
03047 {
03048
03049
03050
03051 ASM_OUTPUT_LABEL (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
03052 fputs ("\t.PROC\n", file);
03053
03054
03055
03056
03057 fprintf (file, "\t.CALLINFO FRAME=%d", actual_fsize);
03058 if (regs_ever_live[2])
03059 fputs (",CALLS,SAVE_RP", file);
03060 else
03061 fputs (",NO_CALLS", file);
03062
03063 if (frame_pointer_needed)
03064 fputs (",SAVE_SP", file);
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074 if (gr_saved)
03075 fprintf (file, ",ENTRY_GR=%d", gr_saved + 2);
03076
03077 if (fr_saved)
03078 fprintf (file, ",ENTRY_FR=%d", fr_saved + 11);
03079
03080 fputs ("\n\t.ENTRY\n", file);
03081
03082 remove_useless_addtr_insns (get_insns (), 0);
03083 }
03084
03085 void
03086 hppa_expand_prologue ()
03087 {
03088 int size = get_frame_size ();
03089 int merge_sp_adjust_with_store = 0;
03090 int i, offset;
03091 rtx tmpreg, size_rtx;
03092
03093 gr_saved = 0;
03094 fr_saved = 0;
03095 save_fregs = 0;
03096
03097
03098
03099
03100
03101
03102 local_fsize = size + (size || frame_pointer_needed
03103 ? STARTING_FRAME_OFFSET : 0);
03104
03105 actual_fsize = compute_frame_size (size, &save_fregs);
03106
03107
03108 tmpreg = gen_rtx_REG (word_mode, 1);
03109 size_rtx = GEN_INT (actual_fsize);
03110
03111
03112
03113
03114 if (regs_ever_live[2])
03115 store_reg (2, TARGET_64BIT ? -16 : -20, STACK_POINTER_REGNUM);
03116
03117
03118 if (actual_fsize != 0)
03119 {
03120 if (frame_pointer_needed)
03121 {
03122
03123
03124
03125
03126
03127
03128 emit_move_insn (tmpreg, frame_pointer_rtx);
03129 FRP (emit_move_insn (frame_pointer_rtx, stack_pointer_rtx));
03130 if (VAL_14_BITS_P (actual_fsize))
03131 {
03132 rtx insn = emit_insn (gen_post_store (stack_pointer_rtx, tmpreg,
03133 size_rtx));
03134 if (DO_FRAME_NOTES)
03135 {
03136 rtvec vec;
03137 RTX_FRAME_RELATED_P (insn) = 1;
03138 vec = gen_rtvec (2,
03139 gen_rtx_SET (VOIDmode,
03140 gen_rtx_MEM (word_mode,
03141 stack_pointer_rtx),
03142 frame_pointer_rtx),
03143 gen_rtx_SET (VOIDmode,
03144 stack_pointer_rtx,
03145 gen_rtx_PLUS (word_mode,
03146 stack_pointer_rtx,
03147 size_rtx)));
03148 REG_NOTES (insn)
03149 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03150 gen_rtx_SEQUENCE (VOIDmode, vec),
03151 REG_NOTES (insn));
03152 }
03153 }
03154 else
03155 {
03156
03157
03158
03159
03160
03161
03162 int adjust1 = 8192 - 64;
03163 int adjust2 = actual_fsize - adjust1;
03164 rtx delta = GEN_INT (adjust1);
03165 rtx insn = emit_insn (gen_post_store (stack_pointer_rtx, tmpreg,
03166 delta));
03167 if (DO_FRAME_NOTES)
03168 {
03169 rtvec vec;
03170 RTX_FRAME_RELATED_P (insn) = 1;
03171 vec = gen_rtvec (2,
03172 gen_rtx_SET (VOIDmode,
03173 gen_rtx_MEM (word_mode,
03174 stack_pointer_rtx),
03175 frame_pointer_rtx),
03176 gen_rtx_SET (VOIDmode,
03177 stack_pointer_rtx,
03178 gen_rtx_PLUS (word_mode,
03179 stack_pointer_rtx,
03180 delta)));
03181 REG_NOTES (insn)
03182 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03183 gen_rtx_SEQUENCE (VOIDmode, vec),
03184 REG_NOTES (insn));
03185 }
03186
03187 set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
03188 adjust2);
03189 }
03190
03191
03192
03193
03194 emit_insn (gen_blockage ());
03195 }
03196
03197 else
03198 {
03199
03200
03201
03202
03203 if (VAL_14_BITS_P (actual_fsize) && local_fsize == 0)
03204 merge_sp_adjust_with_store = 1;
03205
03206
03207 else
03208 set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
03209 actual_fsize);
03210 }
03211 }
03212
03213
03214
03215
03216
03217 if (frame_pointer_needed)
03218 {
03219 for (i = 18, offset = local_fsize; i >= 4; i--)
03220 if (regs_ever_live[i] && ! call_used_regs[i])
03221 {
03222 store_reg (i, offset, FRAME_POINTER_REGNUM);
03223 offset += UNITS_PER_WORD;
03224 gr_saved++;
03225 }
03226
03227 gr_saved++;
03228 }
03229
03230 else
03231 {
03232 for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)
03233 if (regs_ever_live[i] && ! call_used_regs[i])
03234 {
03235
03236
03237 if (merge_sp_adjust_with_store)
03238 {
03239 rtx delta = GEN_INT (-offset);
03240 merge_sp_adjust_with_store = 0;
03241 FRP (emit_insn (gen_post_store (stack_pointer_rtx,
03242 gen_rtx_REG (word_mode, i),
03243 delta)));
03244 }
03245 else
03246 store_reg (i, offset, STACK_POINTER_REGNUM);
03247 offset += UNITS_PER_WORD;
03248 gr_saved++;
03249 }
03250
03251
03252
03253 if (merge_sp_adjust_with_store)
03254 set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM,
03255 actual_fsize);
03256 }
03257
03258
03259
03260
03261
03262
03263
03264 if (flag_pic && actual_fsize != 0 && !TARGET_64BIT)
03265 store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM);
03266
03267
03268 offset = (offset + 7) & ~7;
03269
03270
03271 if (save_fregs)
03272 {
03273
03274
03275 if (frame_pointer_needed)
03276 set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset);
03277 else
03278 set_reg_plus_d (1, STACK_POINTER_REGNUM, offset);
03279
03280
03281 for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
03282 {
03283 if (regs_ever_live[i]
03284 || (! TARGET_64BIT && regs_ever_live[i + 1]))
03285 {
03286 rtx addr, insn, reg;
03287 addr = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
03288 reg = gen_rtx_REG (DFmode, i);
03289 insn = emit_move_insn (addr, reg);
03290 if (DO_FRAME_NOTES)
03291 {
03292 RTX_FRAME_RELATED_P (insn) = 1;
03293 REG_NOTES (insn)
03294 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03295 gen_rtx_SET (VOIDmode,
03296 gen_rtx_MEM (DFmode,
03297 plus_constant (stack_pointer_rtx,
03298 offset)),
03299 reg),
03300 REG_NOTES (insn));
03301 }
03302 offset += GET_MODE_SIZE (DFmode);
03303 fr_saved++;
03304 }
03305 }
03306 }
03307 }
03308
03309
03310
03311
03312 static void
03313 load_reg (reg, disp, base)
03314 int reg, disp, base;
03315 {
03316 rtx src, dest, basereg;
03317
03318 dest = gen_rtx_REG (word_mode, reg);
03319 basereg = gen_rtx_REG (Pmode, base);
03320 if (VAL_14_BITS_P (disp))
03321 {
03322 src = gen_rtx_MEM (word_mode, plus_constant (basereg, disp));
03323 emit_move_insn (dest, src);
03324 }
03325 else
03326 {
03327 rtx delta = GEN_INT (disp);
03328 rtx high = gen_rtx_PLUS (Pmode, basereg, gen_rtx_HIGH (Pmode, delta));
03329 rtx tmpreg = gen_rtx_REG (Pmode, 1);
03330 emit_move_insn (tmpreg, high);
03331 src = gen_rtx_MEM (word_mode, gen_rtx_LO_SUM (Pmode, tmpreg, delta));
03332 emit_move_insn (dest, src);
03333 }
03334 }
03335
03336
03337
03338
03339 static rtx
03340 get_last_nonnote_insn ()
03341 {
03342 rtx insn = get_last_insn ();
03343
03344 while (insn)
03345 {
03346 insn = previous_insn (insn);
03347 if (insn == 0 || GET_CODE (insn) != NOTE)
03348 break;
03349 }
03350
03351 return insn;
03352 }
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362 static void
03363 pa_output_function_epilogue (file, size)
03364 FILE *file;
03365 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
03366 {
03367 int last_address = 0;
03368 rtx insn = get_last_insn ();
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379
03380 if (GET_CODE (insn) == NOTE)
03381 insn = prev_real_insn (insn);
03382
03383
03384 if (insn && GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
03385 insn = XVECEXP (PATTERN (insn), 0, 0);
03386
03387
03388
03389 if (insn && GET_CODE (insn) == CALL_INSN)
03390 {
03391 fputs ("\tnop\n", file);
03392 last_address += 4;
03393 }
03394
03395 fputs ("\t.EXIT\n\t.PROCEND\n", file);
03396
03397
03398 if ((TARGET_PORTABLE_RUNTIME || !TARGET_GAS || !TARGET_SOM)
03399 && !flag_function_sections)
03400 {
03401 if (INSN_ADDRESSES_SET_P ())
03402 {
03403 unsigned long old_total = total_code_bytes;
03404
03405 insn = get_last_nonnote_insn ();
03406 last_address += INSN_ADDRESSES (INSN_UID (insn));
03407 if (INSN_P (insn))
03408 last_address += insn_default_length (insn);
03409
03410 total_code_bytes += last_address;
03411 total_code_bytes += FUNCTION_BOUNDARY / BITS_PER_UNIT;
03412
03413
03414 if (old_total > total_code_bytes)
03415 total_code_bytes = -1;
03416 }
03417 else
03418 total_code_bytes = -1;
03419 }
03420 }
03421
03422 void
03423 hppa_expand_epilogue ()
03424 {
03425 rtx tmpreg;
03426 int offset, i;
03427 int merge_sp_adjust_with_load = 0;
03428 int ret_off = 0;
03429
03430
03431 tmpreg = gen_rtx_REG (word_mode, 1);
03432
03433
03434
03435
03436 if (regs_ever_live [2])
03437 {
03438 ret_off = TARGET_64BIT ? -16 : -20;
03439 if (frame_pointer_needed)
03440 {
03441 load_reg (2, ret_off, FRAME_POINTER_REGNUM);
03442 ret_off = 0;
03443 }
03444 else
03445 {
03446
03447 if (VAL_14_BITS_P (ret_off - actual_fsize))
03448 {
03449 load_reg (2, ret_off - actual_fsize, STACK_POINTER_REGNUM);
03450 ret_off = 0;
03451 }
03452 }
03453 }
03454
03455
03456 if (frame_pointer_needed)
03457 {
03458 for (i = 18, offset = local_fsize; i >= 4; i--)
03459 if (regs_ever_live[i] && ! call_used_regs[i])
03460 {
03461 load_reg (i, offset, FRAME_POINTER_REGNUM);
03462 offset += UNITS_PER_WORD;
03463 }
03464 }
03465 else
03466 {
03467 for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)
03468 {
03469 if (regs_ever_live[i] && ! call_used_regs[i])
03470 {
03471
03472
03473
03474 if (merge_sp_adjust_with_load == 0
03475 && local_fsize == 0
03476 && VAL_14_BITS_P (-actual_fsize))
03477 merge_sp_adjust_with_load = i;
03478 else
03479 load_reg (i, offset, STACK_POINTER_REGNUM);
03480 offset += UNITS_PER_WORD;
03481 }
03482 }
03483 }
03484
03485
03486 offset = (offset + 7) & ~7;
03487
03488
03489 if (save_fregs)
03490 {
03491
03492 if (frame_pointer_needed)
03493 set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset);
03494 else
03495 set_reg_plus_d (1, STACK_POINTER_REGNUM, offset);
03496
03497
03498 for (i = FP_SAVED_REG_LAST; i >= FP_SAVED_REG_FIRST; i -= FP_REG_STEP)
03499 if (regs_ever_live[i]
03500 || (! TARGET_64BIT && regs_ever_live[i + 1]))
03501 {
03502 rtx src = gen_rtx_MEM (DFmode, gen_rtx_POST_INC (DFmode, tmpreg));
03503 rtx dest = gen_rtx_REG (DFmode, i);
03504 emit_move_insn (dest, src);
03505 }
03506 }
03507
03508
03509
03510
03511
03512
03513 emit_insn (gen_blockage ());
03514
03515
03516
03517 if (frame_pointer_needed)
03518 {
03519 rtx delta = GEN_INT (-64);
03520 rtx insn;
03521 set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64);
03522 insn = emit_insn (gen_pre_load (frame_pointer_rtx, stack_pointer_rtx,
03523 delta));
03524 if (DO_FRAME_NOTES)
03525 {
03526 RTX_FRAME_RELATED_P (insn) = 1;
03527 REG_NOTES (insn)
03528 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03529 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
03530 gen_rtx_PLUS (word_mode, stack_pointer_rtx,
03531 delta)),
03532 REG_NOTES (insn));
03533 }
03534 }
03535
03536 else if (merge_sp_adjust_with_load)
03537 {
03538 rtx delta = GEN_INT (-actual_fsize);
03539 rtx dest = gen_rtx_REG (word_mode, merge_sp_adjust_with_load);
03540 rtx insn = emit_insn (gen_pre_load (dest, stack_pointer_rtx, delta));
03541 if (DO_FRAME_NOTES)
03542 {
03543 RTX_FRAME_RELATED_P (insn) = 1;
03544 REG_NOTES (insn)
03545 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03546 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
03547 gen_rtx_PLUS (word_mode, stack_pointer_rtx,
03548 delta)),
03549 REG_NOTES (insn));
03550 }
03551 }
03552 else if (actual_fsize != 0)
03553 set_reg_plus_d (STACK_POINTER_REGNUM, STACK_POINTER_REGNUM, - actual_fsize);
03554
03555
03556
03557 if (ret_off != 0)
03558 load_reg (2, ret_off, STACK_POINTER_REGNUM);
03559 }
03560
03561 rtx
03562 hppa_pic_save_rtx ()
03563 {
03564 return get_hard_reg_initial_val (word_mode, PIC_OFFSET_TABLE_REGNUM);
03565 }
03566
03567 void
03568 hppa_profile_hook (label_no)
03569 int label_no;
03570 {
03571 rtx begin_label_rtx, call_insn;
03572 char begin_label_name[16];
03573
03574 ASM_GENERATE_INTERNAL_LABEL (begin_label_name, FUNC_BEGIN_PROLOG_LABEL,
03575 label_no);
03576 begin_label_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (begin_label_name));
03577
03578 if (TARGET_64BIT)
03579 emit_move_insn (arg_pointer_rtx,
03580 gen_rtx_PLUS (word_mode, virtual_outgoing_args_rtx,
03581 GEN_INT (64)));
03582
03583 emit_move_insn (gen_rtx_REG (word_mode, 26), gen_rtx_REG (word_mode, 2));
03584
03585 #ifndef NO_PROFILE_COUNTERS
03586 {
03587 rtx count_label_rtx, addr, r24;
03588 char count_label_name[16];
03589
03590 ASM_GENERATE_INTERNAL_LABEL (count_label_name, "LP", label_no);
03591 count_label_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (count_label_name));
03592
03593 addr = force_reg (Pmode, count_label_rtx);
03594 r24 = gen_rtx_REG (Pmode, 24);
03595 emit_move_insn (r24, addr);
03596
03597
03598 call_insn =
03599 emit_call_insn (gen_call_profiler (gen_rtx_SYMBOL_REF (Pmode, "_mcount"),
03600 GEN_INT (TARGET_64BIT ? 24 : 12),
03601 begin_label_rtx));
03602
03603 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), r24);
03604 }
03605 #else
03606
03607 call_insn =
03608 emit_call_insn (gen_call_profiler (gen_rtx_SYMBOL_REF (Pmode, "_mcount"),
03609 GEN_INT (TARGET_64BIT ? 16 : 8),
03610 begin_label_rtx));
03611 #endif
03612
03613
03614
03615 REG_NOTES (call_insn)
03616 = gen_rtx_EXPR_LIST (REG_EH_REGION, constm1_rtx, REG_NOTES (call_insn));
03617
03618 if (flag_pic)
03619 {
03620 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx);
03621 if (TARGET_64BIT)
03622 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), arg_pointer_rtx);
03623
03624 emit_move_insn (pic_offset_table_rtx, hppa_pic_save_rtx ());
03625 }
03626 }
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639
03640
03641
03642
03643
03644
03645
03646
03647
03648
03649
03650
03651
03652
03653
03654 rtx
03655 return_addr_rtx (count, frameaddr)
03656 int count;
03657 rtx frameaddr;
03658 {
03659 rtx label;
03660 rtx rp;
03661 rtx saved_rp;
03662 rtx ins;
03663
03664 if (count != 0)
03665 return NULL_RTX;
03666
03667 rp = get_hard_reg_initial_val (Pmode, 2);
03668
03669 if (TARGET_64BIT || TARGET_NO_SPACE_REGS)
03670 return rp;
03671
03672 saved_rp = gen_reg_rtx (Pmode);
03673 emit_move_insn (saved_rp, rp);
03674
03675
03676
03677
03678
03679 ins = copy_to_reg (gen_rtx_AND (Pmode, rp, MASK_RETURN_ADDR));
03680 label = gen_label_rtx ();
03681
03682
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693 emit_cmp_insn (gen_rtx_MEM (SImode, ins), GEN_INT (0x4bc23fd1), NE,
03694 NULL_RTX, SImode, 1);
03695 emit_jump_insn (gen_bne (label));
03696
03697 emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 4)),
03698 GEN_INT (0x004010a1), NE, NULL_RTX, SImode, 1);
03699 emit_jump_insn (gen_bne (label));
03700
03701 emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 8)),
03702 GEN_INT (0x00011820), NE, NULL_RTX, SImode, 1);
03703 emit_jump_insn (gen_bne (label));
03704
03705 emit_cmp_insn (gen_rtx_MEM (SImode, plus_constant (ins, 12)),
03706 GEN_INT (0xe0400002), NE, NULL_RTX, SImode, 1);
03707
03708
03709
03710
03711 emit_jump_insn (gen_bne (label));
03712
03713
03714
03715
03716
03717
03718 emit_move_insn (saved_rp,
03719 gen_rtx_MEM (Pmode,
03720 memory_address (Pmode,
03721 plus_constant (frameaddr,
03722 -24))));
03723
03724 emit_label (label);
03725 return saved_rp;
03726 }
03727
03728
03729
03730
03731
03732
03733
03734
03735 int
03736 hppa_can_use_return_insn_p ()
03737 {
03738 return (reload_completed
03739 && (compute_frame_size (get_frame_size (), 0) ? 0 : 1)
03740 && ! regs_ever_live[2]
03741 && ! frame_pointer_needed);
03742 }
03743
03744 void
03745 emit_bcond_fp (code, operand0)
03746 enum rtx_code code;
03747 rtx operand0;
03748 {
03749 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
03750 gen_rtx_IF_THEN_ELSE (VOIDmode,
03751 gen_rtx_fmt_ee (code,
03752 VOIDmode,
03753 gen_rtx_REG (CCFPmode, 0),
03754 const0_rtx),
03755 gen_rtx_LABEL_REF (VOIDmode, operand0),
03756 pc_rtx)));
03757
03758 }
03759
03760 rtx
03761 gen_cmp_fp (code, operand0, operand1)
03762 enum rtx_code code;
03763 rtx operand0, operand1;
03764 {
03765 return gen_rtx_SET (VOIDmode, gen_rtx_REG (CCFPmode, 0),
03766 gen_rtx_fmt_ee (code, CCFPmode, operand0, operand1));
03767 }
03768
03769
03770
03771
03772 static int
03773 pa_adjust_cost (insn, link, dep_insn, cost)
03774 rtx insn;
03775 rtx link;
03776 rtx dep_insn;
03777 int cost;
03778 {
03779 enum attr_type attr_type;
03780
03781
03782 if (pa_cpu >= PROCESSOR_8000)
03783 return cost;
03784
03785 if (! recog_memoized (insn))
03786 return 0;
03787
03788 attr_type = get_attr_type (insn);
03789
03790 if (REG_NOTE_KIND (link) == 0)
03791 {
03792
03793
03794
03795 if (attr_type == TYPE_FPSTORE)
03796 {
03797 rtx pat = PATTERN (insn);
03798 rtx dep_pat = PATTERN (dep_insn);
03799 if (GET_CODE (pat) == PARALLEL)
03800 {
03801
03802 pat = XVECEXP (pat, 0, 0);
03803 }
03804 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
03805
03806
03807 return 0;
03808
03809 if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat)))
03810 {
03811 if (! recog_memoized (dep_insn))
03812 return 0;
03813
03814
03815 switch (get_attr_type (dep_insn))
03816 {
03817 case TYPE_FPLOAD:
03818
03819
03820 return cost + 1;
03821
03822 case TYPE_FPALU:
03823 case TYPE_FPMULSGL:
03824 case TYPE_FPMULDBL:
03825 case TYPE_FPDIVSGL:
03826 case TYPE_FPDIVDBL:
03827 case TYPE_FPSQRTSGL:
03828 case TYPE_FPSQRTDBL:
03829
03830
03831 return cost - 1;
03832
03833 default:
03834 return cost;
03835 }
03836 }
03837 }
03838
03839
03840
03841 return cost;
03842 }
03843 else if (REG_NOTE_KIND (link) == REG_DEP_ANTI)
03844 {
03845
03846
03847
03848 if (attr_type == TYPE_FPLOAD)
03849 {
03850 rtx pat = PATTERN (insn);
03851 rtx dep_pat = PATTERN (dep_insn);
03852 if (GET_CODE (pat) == PARALLEL)
03853 {
03854
03855 pat = XVECEXP (pat, 0, 0);
03856 }
03857 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
03858
03859
03860 return 0;
03861
03862 if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat)))
03863 {
03864 if (! recog_memoized (dep_insn))
03865 return 0;
03866 switch (get_attr_type (dep_insn))
03867 {
03868 case TYPE_FPALU:
03869 case TYPE_FPMULSGL:
03870 case TYPE_FPMULDBL:
03871 case TYPE_FPDIVSGL:
03872 case TYPE_FPDIVDBL:
03873 case TYPE_FPSQRTSGL:
03874 case TYPE_FPSQRTDBL:
03875
03876
03877
03878
03879 return cost - 1;
03880
03881 default:
03882 return 0;
03883 }
03884 }
03885 }
03886 else if (attr_type == TYPE_FPALU)
03887 {
03888 rtx pat = PATTERN (insn);
03889 rtx dep_pat = PATTERN (dep_insn);
03890 if (GET_CODE (pat) == PARALLEL)
03891 {
03892
03893 pat = XVECEXP (pat, 0, 0);
03894 }
03895 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
03896
03897
03898 return 0;
03899
03900 if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat)))
03901 {
03902 if (! recog_memoized (dep_insn))
03903 return 0;
03904 switch (get_attr_type (dep_insn))
03905 {
03906 case TYPE_FPDIVSGL:
03907 case TYPE_FPDIVDBL:
03908 case TYPE_FPSQRTSGL:
03909 case TYPE_FPSQRTDBL:
03910
03911
03912
03913
03914 return cost - 2;
03915
03916 default:
03917 return 0;
03918 }
03919 }
03920 }
03921
03922
03923 return 0;
03924 }
03925 else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
03926 {
03927
03928
03929 if (attr_type == TYPE_FPLOAD)
03930 {
03931 rtx pat = PATTERN (insn);
03932 rtx dep_pat = PATTERN (dep_insn);
03933 if (GET_CODE (pat) == PARALLEL)
03934 {
03935
03936 pat = XVECEXP (pat, 0, 0);
03937 }
03938 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
03939
03940
03941 return 0;
03942
03943 if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat)))
03944 {
03945 if (! recog_memoized (dep_insn))
03946 return 0;
03947 switch (get_attr_type (dep_insn))
03948 {
03949 case TYPE_FPALU:
03950 case TYPE_FPMULSGL:
03951 case TYPE_FPMULDBL:
03952 case TYPE_FPDIVSGL:
03953 case TYPE_FPDIVDBL:
03954 case TYPE_FPSQRTSGL:
03955 case TYPE_FPSQRTDBL:
03956
03957
03958
03959
03960 return cost - 1;
03961
03962 default:
03963 return 0;
03964 }
03965 }
03966 }
03967 else if (attr_type == TYPE_FPALU)
03968 {
03969 rtx pat = PATTERN (insn);
03970 rtx dep_pat = PATTERN (dep_insn);
03971 if (GET_CODE (pat) == PARALLEL)
03972 {
03973
03974 pat = XVECEXP (pat, 0, 0);
03975 }
03976 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
03977
03978
03979 return 0;
03980
03981 if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat)))
03982 {
03983 if (! recog_memoized (dep_insn))
03984 return 0;
03985 switch (get_attr_type (dep_insn))
03986 {
03987 case TYPE_FPDIVSGL:
03988 case TYPE_FPDIVDBL:
03989 case TYPE_FPSQRTSGL:
03990 case TYPE_FPSQRTDBL:
03991
03992
03993
03994
03995 return cost - 2;
03996
03997 default:
03998 return 0;
03999 }
04000 }
04001 }
04002
04003
04004 return 0;
04005 }
04006 else
04007 abort ();
04008 }
04009
04010
04011
04012 static int
04013 pa_adjust_priority (insn, priority)
04014 rtx insn;
04015 int priority;
04016 {
04017 rtx set = single_set (insn);
04018 rtx src, dest;
04019 if (set)
04020 {
04021 src = SET_SRC (set);
04022 dest = SET_DEST (set);
04023 if (GET_CODE (src) == LO_SUM
04024 && symbolic_operand (XEXP (src, 1), VOIDmode)
04025 && ! read_only_operand (XEXP (src, 1), VOIDmode))
04026 priority >>= 3;
04027
04028 else if (GET_CODE (src) == MEM
04029 && GET_CODE (XEXP (src, 0)) == LO_SUM
04030 && symbolic_operand (XEXP (XEXP (src, 0), 1), VOIDmode)
04031 && ! read_only_operand (XEXP (XEXP (src, 0), 1), VOIDmode))
04032 priority >>= 1;
04033
04034 else if (GET_CODE (dest) == MEM
04035 && GET_CODE (XEXP (dest, 0)) == LO_SUM
04036 && symbolic_operand (XEXP (XEXP (dest, 0), 1), VOIDmode)
04037 && ! read_only_operand (XEXP (XEXP (dest, 0), 1), VOIDmode))
04038 priority >>= 3;
04039 }
04040 return priority;
04041 }
04042
04043
04044
04045
04046 static int
04047 pa_issue_rate ()
04048 {
04049 switch (pa_cpu)
04050 {
04051 case PROCESSOR_700: return 1;
04052 case PROCESSOR_7100: return 2;
04053 case PROCESSOR_7100LC: return 2;
04054 case PROCESSOR_7200: return 2;
04055 case PROCESSOR_8000: return 4;
04056
04057 default:
04058 abort ();
04059 }
04060 }
04061
04062
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073 int
04074 pa_adjust_insn_length (insn, length)
04075 rtx insn;
04076 int length;
04077 {
04078 rtx pat = PATTERN (insn);
04079
04080
04081 if (GET_CODE (insn) == CALL_INSN)
04082 {
04083
04084 if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL
04085 && GET_CODE (XEXP (XEXP (XVECEXP (pat, 0, 0), 0), 0)) == SYMBOL_REF)
04086 return 4;
04087 else if (GET_CODE (XVECEXP (pat, 0, 0)) == SET
04088 && GET_CODE (XEXP (XEXP (XEXP (XVECEXP (pat, 0, 0), 1), 0), 0))
04089 == SYMBOL_REF)
04090 return 4;
04091 else
04092 return 0;
04093 }
04094
04095
04096 else if (GET_CODE (insn) == JUMP_INSN
04097 && simplejump_p (insn)
04098 && GET_MODE (insn) == SImode)
04099 return 4;
04100
04101 else if (GET_CODE (insn) == INSN
04102 && GET_CODE (pat) != SEQUENCE
04103 && GET_CODE (pat) != USE
04104 && GET_CODE (pat) != CLOBBER
04105 && get_attr_type (insn) == TYPE_MILLI)
04106 return 4;
04107
04108 else if (GET_CODE (insn) == INSN
04109 && GET_CODE (pat) == PARALLEL
04110 && GET_CODE (XVECEXP (pat, 0, 0)) == SET
04111 && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 0)) == MEM
04112 && GET_CODE (XEXP (XVECEXP (pat, 0, 0), 1)) == MEM
04113 && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode
04114 && GET_MODE (XEXP (XVECEXP (pat, 0, 0), 1)) == BLKmode)
04115 return compute_movstrsi_length (insn) - 4;
04116
04117 else if (GET_CODE (insn) == JUMP_INSN && ! simplejump_p (insn))
04118 {
04119
04120 if (GET_CODE (pat) == SET
04121 && length == 4
04122 && ! forward_branch_p (insn))
04123 return 4;
04124 else if (GET_CODE (pat) == PARALLEL
04125 && get_attr_type (insn) == TYPE_PARALLEL_BRANCH
04126 && length == 4)
04127 return 4;
04128
04129
04130
04131 else if (GET_CODE (pat) == PARALLEL
04132 && GET_CODE (XVECEXP (pat, 0, 1)) == SET
04133 && GET_CODE (XEXP (XVECEXP (pat, 0, 1), 0)) == REG
04134 && ! FP_REG_P (XEXP (XVECEXP (pat, 0, 1), 0))
04135 && length == 4
04136 && ! forward_branch_p (insn))
04137 return 4;
04138 else
04139 return 0;
04140 }
04141 return 0;
04142 }
04143
04144
04145
04146
04147
04148 void
04149 print_operand (file, x, code)
04150 FILE *file;
04151 rtx x;
04152 int code;
04153 {
04154 switch (code)
04155 {
04156 case '#':
04157
04158 if (dbr_sequence_length () == 0)
04159 fputs ("\n\tnop", file);
04160 return;
04161 case '*':
04162
04163
04164 if (dbr_sequence_length () == 0 ||
04165 (final_sequence &&
04166 INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))))
04167 fputs (",n", file);
04168 return;
04169 case 'R':
04170
04171
04172 fputs (reg_names[REGNO (x) + 1], file);
04173 return;
04174 case 'r':
04175
04176 if (x == const0_rtx
04177 || (x == CONST0_RTX (DFmode))
04178 || (x == CONST0_RTX (SFmode)))
04179 {
04180 fputs ("%r0", file);
04181 return;
04182 }
04183 else
04184 break;
04185 case 'f':
04186
04187 if (x == const0_rtx
04188 || (x == CONST0_RTX (DFmode))
04189 || (x == CONST0_RTX (SFmode)))
04190 {
04191 fputs ("%fr0", file);
04192 return;
04193 }
04194 else
04195 break;
04196 case 'A':
04197 {
04198 rtx xoperands[2];
04199
04200 xoperands[0] = XEXP (XEXP (x, 0), 0);
04201 xoperands[1] = XVECEXP (XEXP (XEXP (x, 0), 1), 0, 0);
04202 output_global_address (file, xoperands[1], 0);
04203 fprintf (file, "(%s)", reg_names [REGNO (xoperands[0])]);
04204 return;
04205 }
04206
04207 case 'C':
04208 case 'X':
04209 switch (GET_CODE (x))
04210 {
04211 case EQ:
04212 fputs ("=", file); break;
04213 case NE:
04214 fputs ("<>", file); break;
04215 case GT:
04216 fputs (">", file); break;
04217 case GE:
04218 fputs (">=", file); break;
04219 case GEU:
04220 fputs (">>=", file); break;
04221 case GTU:
04222 fputs (">>", file); break;
04223 case LT:
04224 fputs ("<", file); break;
04225 case LE:
04226 fputs ("<=", file); break;
04227 case LEU:
04228 fputs ("<<=", file); break;
04229 case LTU:
04230 fputs ("<<", file); break;
04231 default:
04232 abort ();
04233 }
04234 return;
04235 case 'N':
04236 switch (GET_CODE (x))
04237 {
04238 case EQ:
04239 fputs ("<>", file); break;
04240 case NE:
04241 fputs ("=", file); break;
04242 case GT:
04243 fputs ("<=", file); break;
04244 case GE:
04245 fputs ("<", file); break;
04246 case GEU:
04247 fputs ("<<", file); break;
04248 case GTU:
04249 fputs ("<<=", file); break;
04250 case LT:
04251 fputs (">=", file); break;
04252 case LE:
04253 fputs (">", file); break;
04254 case LEU:
04255 fputs (">>", file); break;
04256 case LTU:
04257 fputs (">>=", file); break;
04258 default:
04259 abort ();
04260 }
04261 return;
04262
04263
04264 case 'Y':
04265 switch (GET_CODE (x))
04266 {
04267 case EQ:
04268 fputs ("!=", file); break;
04269 case NE:
04270 fputs ("=", file); break;
04271 case GT:
04272 fputs ("!>", file); break;
04273 case GE:
04274 fputs ("!>=", file); break;
04275 case LT:
04276 fputs ("!<", file); break;
04277 case LE:
04278 fputs ("!<=", file); break;
04279 case LTGT:
04280 fputs ("!<>", file); break;
04281 case UNLE:
04282 fputs (">", file); break;
04283 case UNLT:
04284 fputs (">=", file); break;
04285 case UNGE:
04286 fputs ("<", file); break;
04287 case UNGT:
04288 fputs ("<=", file); break;
04289 case UNEQ:
04290 fputs ("<>", file); break;
04291 case UNORDERED:
04292 fputs ("<=>", file); break;
04293 case ORDERED:
04294 fputs ("!<=>", file); break;
04295 default:
04296 abort ();
04297 }
04298 return;
04299 case 'S':
04300 switch (GET_CODE (x))
04301 {
04302 case EQ:
04303 fputs ("=", file); break;
04304 case NE:
04305 fputs ("<>", file); break;
04306 case GT:
04307 fputs ("<", file); break;
04308 case GE:
04309 fputs ("<=", file); break;
04310 case GEU:
04311 fputs ("<<=", file); break;
04312 case GTU:
04313 fputs ("<<", file); break;
04314 case LT:
04315 fputs (">", file); break;
04316 case LE:
04317 fputs (">=", file); break;
04318 case LEU:
04319 fputs (">>=", file); break;
04320 case LTU:
04321 fputs (">>", file); break;
04322 default:
04323 abort ();
04324 }
04325 return;
04326 case 'B':
04327 switch (GET_CODE (x))
04328 {
04329 case EQ:
04330 fputs ("<>", file); break;
04331 case NE:
04332 fputs ("=", file); break;
04333 case GT:
04334 fputs (">=", file); break;
04335 case GE:
04336 fputs (">", file); break;
04337 case GEU:
04338 fputs (">>", file); break;
04339 case GTU:
04340 fputs (">>=", file); break;
04341 case LT:
04342 fputs ("<=", file); break;
04343 case LE:
04344 fputs ("<", file); break;
04345 case LEU:
04346 fputs ("<<", file); break;
04347 case LTU:
04348 fputs ("<<=", file); break;
04349 default:
04350 abort ();
04351 }
04352 return;
04353 case 'k':
04354 if (GET_CODE (x) == CONST_INT)
04355 {
04356 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~INTVAL (x));
04357 return;
04358 }
04359 abort ();
04360 case 'Q':
04361 if (GET_CODE (x) == CONST_INT)
04362 {
04363 fprintf (file, HOST_WIDE_INT_PRINT_DEC, 64 - (INTVAL (x) & 63));
04364 return;
04365 }
04366 abort ();
04367 case 'L':
04368 if (GET_CODE (x) == CONST_INT)
04369 {
04370 fprintf (file, HOST_WIDE_INT_PRINT_DEC, 32 - (INTVAL (x) & 31));
04371 return;
04372 }
04373 abort ();
04374 case 'O':
04375 if (GET_CODE (x) == CONST_INT && exact_log2 (INTVAL (x)) >= 0)
04376 {
04377 fprintf (file, "%d", exact_log2 (INTVAL (x)));
04378 return;
04379 }
04380 abort ();
04381 case 'p':
04382 if (GET_CODE (x) == CONST_INT)
04383 {
04384 fprintf (file, HOST_WIDE_INT_PRINT_DEC, 63 - (INTVAL (x) & 63));
04385 return;
04386 }
04387 abort ();
04388 case 'P':
04389 if (GET_CODE (x) == CONST_INT)
04390 {
04391 fprintf (file, HOST_WIDE_INT_PRINT_DEC, 31 - (INTVAL (x) & 31));
04392 return;
04393 }
04394 abort ();
04395 case 'I':
04396 if (GET_CODE (x) == CONST_INT)
04397 fputs ("i", file);
04398 return;
04399 case 'M':
04400 case 'F':
04401 switch (GET_CODE (XEXP (x, 0)))
04402 {
04403 case PRE_DEC:
04404 case PRE_INC:
04405 if (ASSEMBLER_DIALECT == 0)
04406 fputs ("s,mb", file);
04407 else
04408 fputs (",mb", file);
04409 break;
04410 case POST_DEC:
04411 case POST_INC:
04412 if (ASSEMBLER_DIALECT == 0)
04413 fputs ("s,ma", file);
04414 else
04415 fputs (",ma", file);
04416 break;
04417 case PLUS:
04418 if (GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
04419 || GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT)
04420 {
04421 if (ASSEMBLER_DIALECT == 0)
04422 fputs ("x,s", file);
04423 else
04424 fputs (",s", file);
04425 }
04426 else if (code == 'F' && ASSEMBLER_DIALECT == 0)
04427 fputs ("s", file);
04428 break;
04429 default:
04430 if (code == 'F' && ASSEMBLER_DIALECT == 0)
04431 fputs ("s", file);
04432 break;
04433 }
04434 return;
04435 case 'G':
04436 output_global_address (file, x, 0);
04437 return;
04438 case 'H':
04439 output_global_address (file, x, 1);
04440 return;
04441 case 0:
04442 break;
04443 case 'Z':
04444 {
04445 unsigned op[3];
04446 compute_zdepwi_operands (INTVAL (x), op);
04447 fprintf (file, "%d,%d,%d", op[0], op[1], op[2]);
04448 return;
04449 }
04450 case 'z':
04451 {
04452 unsigned op[3];
04453 compute_zdepdi_operands (INTVAL (x), op);
04454 fprintf (file, "%d,%d,%d", op[0], op[1], op[2]);
04455 return;
04456 }
04457 case 'c':
04458
04459
04460
04461 break;
04462 default:
04463 abort ();
04464 }
04465 if (GET_CODE (x) == REG)
04466 {
04467 fputs (reg_names [REGNO (x)], file);
04468 if (TARGET_64BIT && FP_REG_P (x) && GET_MODE_SIZE (GET_MODE (x)) <= 4)
04469 {
04470 fputs ("R", file);
04471 return;
04472 }
04473 if (FP_REG_P (x)
04474 && GET_MODE_SIZE (GET_MODE (x)) <= 4
04475 && (REGNO (x) & 1) == 0)
04476 fputs ("L", file);
04477 }
04478 else if (GET_CODE (x) == MEM)
04479 {
04480 int size = GET_MODE_SIZE (GET_MODE (x));
04481 rtx base = NULL_RTX;
04482 switch (GET_CODE (XEXP (x, 0)))
04483 {
04484 case PRE_DEC:
04485 case POST_DEC:
04486 base = XEXP (XEXP (x, 0), 0);
04487 fprintf (file, "-%d(%s)", size, reg_names [REGNO (base)]);
04488 break;
04489 case PRE_INC:
04490 case POST_INC:
04491 base = XEXP (XEXP (x, 0), 0);
04492 fprintf (file, "%d(%s)", size, reg_names [REGNO (base)]);
04493 break;
04494 default:
04495 if (GET_CODE (XEXP (x, 0)) == PLUS
04496 && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT)
04497 fprintf (file, "%s(%s)",
04498 reg_names [REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0))],
04499 reg_names [REGNO (XEXP (XEXP (x, 0), 1))]);
04500 else if (GET_CODE (XEXP (x, 0)) == PLUS
04501 && GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT)
04502 fprintf (file, "%s(%s)",
04503 reg_names [REGNO (XEXP (XEXP (XEXP (x, 0), 1), 0))],
04504 reg_names [REGNO (XEXP (XEXP (x, 0), 0))]);
04505 else
04506 output_address (XEXP (x, 0));
04507 break;
04508 }
04509 }
04510 else
04511 output_addr_const (file, x);
04512 }
04513
04514
04515
04516 void
04517 output_global_address (file, x, round_constant)
04518 FILE *file;
04519 rtx x;
04520 int round_constant;
04521 {
04522
04523
04524 if (GET_CODE (x) == HIGH)
04525 x = XEXP (x, 0);
04526
04527 if (GET_CODE (x) == SYMBOL_REF && read_only_operand (x, VOIDmode))
04528 assemble_name (file, XSTR (x, 0));
04529 else if (GET_CODE (x) == SYMBOL_REF && !flag_pic)
04530 {
04531 assemble_name (file, XSTR (x, 0));
04532 fputs ("-$global$", file);
04533 }
04534 else if (GET_CODE (x) == CONST)
04535 {
04536 const char *sep = "";
04537 int offset = 0;
04538 rtx base = NULL_RTX;
04539
04540 if (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
04541 {
04542 base = XEXP (XEXP (x, 0), 0);
04543 output_addr_const (file, base);
04544 }
04545 else if (GET_CODE (XEXP (XEXP (x, 0), 0)) == CONST_INT)
04546 offset = INTVAL (XEXP (XEXP (x, 0), 0));
04547 else abort ();
04548
04549 if (GET_CODE (XEXP (XEXP (x, 0), 1)) == SYMBOL_REF)
04550 {
04551 base = XEXP (XEXP (x, 0), 1);
04552 output_addr_const (file, base);
04553 }
04554 else if (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
04555 offset = INTVAL (XEXP (XEXP (x, 0), 1));
04556 else abort ();
04557
04558
04559
04560
04561
04562
04563
04564
04565
04566
04567 if (round_constant)
04568 offset = ((offset + 0x1000) & ~0x1fff);
04569
04570 if (GET_CODE (XEXP (x, 0)) == PLUS)
04571 {
04572 if (offset < 0)
04573 {
04574 offset = -offset;
04575 sep = "-";
04576 }
04577 else
04578 sep = "+";
04579 }
04580 else if (GET_CODE (XEXP (x, 0)) == MINUS
04581 && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))
04582 sep = "-";
04583 else abort ();
04584
04585 if (!read_only_operand (base, VOIDmode) && !flag_pic)
04586 fputs ("-$global$", file);
04587 if (offset)
04588 fprintf (file, "%s%d", sep, offset);
04589 }
04590 else
04591 output_addr_const (file, x);
04592 }
04593
04594 void
04595 output_deferred_plabels (file)
04596 FILE *file;
04597 {
04598 int i;
04599
04600
04601
04602 if (n_deferred_plabels)
04603 {
04604 data_section ();
04605 ASM_OUTPUT_ALIGN (file, 2);
04606 }
04607
04608
04609 for (i = 0; i < n_deferred_plabels; i++)
04610 {
04611 ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (deferred_plabels[i].internal_label));
04612 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, deferred_plabels[i].name),
04613 4, 32, 1);
04614 }
04615 }
04616
04617
04618
04619
04620 enum millicodes { remI, remU, divI, divU, mulI, mulU, end1000 };
04621 static void import_milli PARAMS ((enum millicodes));
04622 static char imported[(int) end1000];
04623 static const char * const milli_names[] = {"remI", "remU", "divI", "divU", "mulI", "mulU"};
04624 static const char import_string[] = ".IMPORT $$....,MILLICODE";
04625 #define MILLI_START 10
04626
04627 static void
04628 import_milli (code)
04629 enum millicodes code;
04630 {
04631 char str[sizeof (import_string)];
04632
04633 if (!imported[(int) code])
04634 {
04635 imported[(int) code] = 1;
04636 strcpy (str, import_string);
04637 strncpy (str + MILLI_START, milli_names[(int) code], 4);
04638 output_asm_insn (str, 0);
04639 }
04640 }
04641
04642
04643
04644
04645 const char *
04646 output_mul_insn (unsignedp, insn)
04647 int unsignedp ATTRIBUTE_UNUSED;
04648 rtx insn;
04649 {
04650 import_milli (mulI);
04651 return output_millicode_call (insn, gen_rtx_SYMBOL_REF (Pmode, "$$mulI"));
04652 }
04653
04654
04655
04656
04657 static const int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
04658 1, 1};
04659
04660
04661
04662
04663
04664 static int div_milli[16][2];
04665
04666 int
04667 div_operand (op, mode)
04668 rtx op;
04669 enum machine_mode mode;
04670 {
04671 return (mode == SImode
04672 && ((GET_CODE (op) == REG && REGNO (op) == 25)
04673 || (GET_CODE (op) == CONST_INT && INTVAL (op) > 0
04674 && INTVAL (op) < 16 && magic_milli[INTVAL (op)])));
04675 }
04676
04677 int
04678 emit_hpdiv_const (operands, unsignedp)
04679 rtx *operands;
04680 int unsignedp;
04681 {
04682 if (GET_CODE (operands[2]) == CONST_INT
04683 && INTVAL (operands[2]) > 0
04684 && INTVAL (operands[2]) < 16
04685 && magic_milli[INTVAL (operands[2])])
04686 {
04687 rtx ret = gen_rtx_REG (SImode, TARGET_64BIT ? 2 : 31);
04688
04689 emit_move_insn (gen_rtx_REG (SImode, 26), operands[1]);
04690 emit
04691 (gen_rtx
04692 (PARALLEL, VOIDmode,
04693 gen_rtvec (6, gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, 29),
04694 gen_rtx_fmt_ee (unsignedp ? UDIV : DIV,
04695 SImode,
04696 gen_rtx_REG (SImode, 26),
04697 operands[2])),
04698 gen_rtx_CLOBBER (VOIDmode, operands[4]),
04699 gen_rtx_CLOBBER (VOIDmode, operands[3]),
04700 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 26)),
04701 gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 25)),
04702 gen_rtx_CLOBBER (VOIDmode, ret))));
04703 emit_move_insn (operands[0], gen_rtx_REG (SImode, 29));
04704 return 1;
04705 }
04706 return 0;
04707 }
04708
04709 const char *
04710 output_div_insn (operands, unsignedp, insn)
04711 rtx *operands;
04712 int unsignedp;
04713 rtx insn;
04714 {
04715 int divisor;
04716
04717
04718
04719 if (GET_CODE (operands[0]) == CONST_INT)
04720 {
04721 static char buf[100];
04722 divisor = INTVAL (operands[0]);
04723 if (!div_milli[divisor][unsignedp])
04724 {
04725 div_milli[divisor][unsignedp] = 1;
04726 if (unsignedp)
04727 output_asm_insn (".IMPORT $$divU_%0,MILLICODE", operands);
04728 else
04729 output_asm_insn (".IMPORT $$divI_%0,MILLICODE", operands);
04730 }
04731 if (unsignedp)
04732 {
04733 sprintf (buf, "$$divU_");
04734 sprintf (buf + 7, HOST_WIDE_INT_PRINT_DEC, INTVAL (operands[0]));
04735 return output_millicode_call (insn,
04736 gen_rtx_SYMBOL_REF (SImode, buf));
04737 }
04738 else
04739 {
04740 sprintf (buf, "$$divI_");
04741 sprintf (buf + 7, HOST_WIDE_INT_PRINT_DEC, INTVAL (operands[0]));
04742 return output_millicode_call (insn,
04743 gen_rtx_SYMBOL_REF (SImode, buf));
04744 }
04745 }
04746
04747 else
04748 {
04749 if (unsignedp)
04750 {
04751 import_milli (divU);
04752 return output_millicode_call (insn,
04753 gen_rtx_SYMBOL_REF (SImode, "$$divU"));
04754 }
04755 else
04756 {
04757 import_milli (divI);
04758 return output_millicode_call (insn,
04759 gen_rtx_SYMBOL_REF (SImode, "$$divI"));
04760 }
04761 }
04762 }
04763
04764
04765
04766 const char *
04767 output_mod_insn (unsignedp, insn)
04768 int unsignedp;
04769 rtx insn;
04770 {
04771 if (unsignedp)
04772 {
04773 import_milli (remU);
04774 return output_millicode_call (insn,
04775 gen_rtx_SYMBOL_REF (SImode, "$$remU"));
04776 }
04777 else
04778 {
04779 import_milli (remI);
04780 return output_millicode_call (insn,
04781 gen_rtx_SYMBOL_REF (SImode, "$$remI"));
04782 }
04783 }
04784
04785 void
04786 output_arg_descriptor (call_insn)
04787 rtx call_insn;
04788 {
04789 const char *arg_regs[4];
04790 enum machine_mode arg_mode;
04791 rtx link;
04792 int i, output_flag = 0;
04793 int regno;
04794
04795
04796
04797 if (TARGET_64BIT || TARGET_ELF32)
04798 return;
04799
04800 for (i = 0; i < 4; i++)
04801 arg_regs[i] = 0;
04802
04803
04804
04805 if (TARGET_PORTABLE_RUNTIME)
04806 {
04807 fputs ("\t.CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO,RETVAL=NO\n",
04808 asm_out_file);
04809 return;
04810 }
04811
04812 if (GET_CODE (call_insn) != CALL_INSN)
04813 abort ();
04814 for (link = CALL_INSN_FUNCTION_USAGE (call_insn); link; link = XEXP (link, 1))
04815 {
04816 rtx use = XEXP (link, 0);
04817
04818 if (! (GET_CODE (use) == USE
04819 && GET_CODE (XEXP (use, 0)) == REG
04820 && FUNCTION_ARG_REGNO_P (REGNO (XEXP (use, 0)))))
04821 continue;
04822
04823 arg_mode = GET_MODE (XEXP (use, 0));
04824 regno = REGNO (XEXP (use, 0));
04825 if (regno >= 23 && regno <= 26)
04826 {
04827 arg_regs[26 - regno] = "GR";
04828 if (arg_mode == DImode)
04829 arg_regs[25 - regno] = "GR";
04830 }
04831 else if (regno >= 32 && regno <= 39)
04832 {
04833 if (arg_mode == SFmode)
04834 arg_regs[(regno - 32) / 2] = "FR";
04835 else
04836 {
04837 #ifndef HP_FP_ARG_DESCRIPTOR_REVERSED
04838 arg_regs[(regno - 34) / 2] = "FR";
04839 arg_regs[(regno - 34) / 2 + 1] = "FU";
04840 #else
04841 arg_regs[(regno - 34) / 2] = "FU";
04842 arg_regs[(regno - 34) / 2 + 1] = "FR";
04843 #endif
04844 }
04845 }
04846 }
04847 fputs ("\t.CALL ", asm_out_file);
04848 for (i = 0; i < 4; i++)
04849 {
04850 if (arg_regs[i])
04851 {
04852 if (output_flag++)
04853 fputc (',', asm_out_file);
04854 fprintf (asm_out_file, "ARGW%d=%s", i, arg_regs[i]);
04855 }
04856 }
04857 fputc ('\n', asm_out_file);
04858 }
04859
04860
04861
04862
04863
04864
04865
04866
04867
04868
04869
04870 enum reg_class
04871 secondary_reload_class (class, mode, in)
04872 enum reg_class class;
04873 enum machine_mode mode;
04874 rtx in;
04875 {
04876 int regno, is_symbolic;
04877
04878
04879
04880 if (flag_pic
04881 && GET_MODE_CLASS (mode) == MODE_INT
04882 && FP_REG_CLASS_P (class)
04883 && (GET_CODE (in) == CONST_INT || GET_CODE (in) == CONST_DOUBLE))
04884 return R1_REGS;
04885
04886
04887
04888
04889 if (GET_CODE (in) == REG)
04890 {
04891 regno = REGNO (in);
04892 if (regno >= FIRST_PSEUDO_REGISTER)
04893 regno = true_regnum (in);
04894 }
04895 else if (GET_CODE (in) == SUBREG)
04896 regno = true_regnum (in);
04897 else
04898 regno = -1;
04899
04900
04901
04902
04903 if (GET_CODE (in) == MEM
04904 && GET_CODE (XEXP (in, 0)) == MEM)
04905 return NO_REGS;
04906
04907
04908
04909 if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
04910 && GET_MODE_CLASS (mode) == MODE_INT
04911 && FP_REG_CLASS_P (class))
04912 || (class == SHIFT_REGS && (regno <= 0 || regno >= 32)))
04913 return GENERAL_REGS;
04914
04915
04916
04917 if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER
04918 && ((REGNO_REG_CLASS (regno) == SHIFT_REGS && FP_REG_CLASS_P (class))
04919 || (class == SHIFT_REGS && FP_REG_CLASS_P (REGNO_REG_CLASS (regno)))))
04920 return GENERAL_REGS;
04921
04922 if (GET_CODE (in) == HIGH)
04923 in = XEXP (in, 0);
04924
04925
04926
04927
04928
04929
04930 switch (GET_CODE (in))
04931 {
04932 rtx tmp;
04933
04934 case SYMBOL_REF:
04935 case LABEL_REF:
04936 is_symbolic = 1;
04937 break;
04938 case CONST:
04939 tmp = XEXP (in, 0);
04940 is_symbolic = ((GET_CODE (XEXP (tmp, 0)) == SYMBOL_REF
04941 || GET_CODE (XEXP (tmp, 0)) == LABEL_REF)
04942 && GET_CODE (XEXP (tmp, 1)) == CONST_INT);
04943 break;
04944
04945 default:
04946 is_symbolic = 0;
04947 break;
04948 }
04949
04950 if (!flag_pic
04951 && is_symbolic
04952 && read_only_operand (in, VOIDmode))
04953 return NO_REGS;
04954
04955 if (class != R1_REGS && is_symbolic)
04956 return R1_REGS;
04957
04958 return NO_REGS;
04959 }
04960
04961 enum direction
04962 function_arg_padding (mode, type)
04963 enum machine_mode mode;
04964 tree type;
04965 {
04966 int size;
04967
04968 if (mode == BLKmode)
04969 {
04970 if (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
04971 size = int_size_in_bytes (type) * BITS_PER_UNIT;
04972 else
04973 return upward;
04974
04975 }
04976 else
04977 size = GET_MODE_BITSIZE (mode);
04978 if (size < PARM_BOUNDARY)
04979 return downward;
04980 else if (size % PARM_BOUNDARY)
04981 return upward;
04982 else
04983 return none;
04984 }
04985
04986
04987
04988
04989
04990
04991 struct rtx_def *
04992 hppa_builtin_saveregs ()
04993 {
04994 rtx offset, dest;
04995 tree fntype = TREE_TYPE (current_function_decl);
04996 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
04997 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
04998 != void_type_node)))
04999 ? UNITS_PER_WORD : 0);
05000
05001 if (argadj)
05002 offset = plus_constant (current_function_arg_offset_rtx, argadj);
05003 else
05004 offset = current_function_arg_offset_rtx;
05005
05006 if (TARGET_64BIT)
05007 {
05008 int i, off;
05009
05010
05011 if (argadj)
05012 offset = plus_constant (current_function_arg_offset_rtx, -argadj);
05013 else
05014 offset = current_function_arg_offset_rtx;
05015
05016
05017
05018 for (i = 26, off = -64; i >= 19; i--, off += 8)
05019 emit_move_insn (gen_rtx_MEM (word_mode,
05020 plus_constant (arg_pointer_rtx, off)),
05021 gen_rtx_REG (word_mode, i));
05022
05023
05024
05025
05026
05027 emit_move_insn (virtual_incoming_args_rtx,
05028 plus_constant (arg_pointer_rtx, -64));
05029
05030
05031 return copy_to_reg (expand_binop (Pmode, add_optab,
05032 virtual_incoming_args_rtx,
05033 offset, 0, 0, OPTAB_LIB_WIDEN));
05034 }
05035
05036
05037 dest = gen_rtx_MEM (BLKmode,
05038 plus_constant (current_function_internal_arg_pointer,
05039 -16));
05040 set_mem_alias_set (dest, get_varargs_alias_set ());
05041 set_mem_align (dest, BITS_PER_WORD);
05042 move_block_from_reg (23, dest, 4, 4 * UNITS_PER_WORD);
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052
05053 emit_insn (gen_blockage ());
05054
05055 return copy_to_reg (expand_binop (Pmode, add_optab,
05056 current_function_internal_arg_pointer,
05057 offset, 0, 0, OPTAB_LIB_WIDEN));
05058 }
05059
05060 void
05061 hppa_va_start (stdarg_p, valist, nextarg)
05062 int stdarg_p ATTRIBUTE_UNUSED;
05063 tree valist;
05064 rtx nextarg;
05065 {
05066 nextarg = expand_builtin_saveregs ();
05067 std_expand_builtin_va_start (1, valist, nextarg);
05068 }
05069
05070 rtx
05071 hppa_va_arg (valist, type)
05072 tree valist, type;
05073 {
05074 HOST_WIDE_INT align, size, ofs;
05075 tree t, ptr, pptr;
05076
05077 if (TARGET_64BIT)
05078 {
05079
05080
05081
05082 size = int_size_in_bytes (type);
05083 if (size > UNITS_PER_WORD)
05084 {
05085 t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
05086 build_int_2 (2 * UNITS_PER_WORD - 1, 0));
05087 t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
05088 build_int_2 (-2 * UNITS_PER_WORD, -1));
05089 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
05090 TREE_SIDE_EFFECTS (t) = 1;
05091 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05092 }
05093 return std_expand_builtin_va_arg (valist, type);
05094 }
05095
05096
05097 align = PARM_BOUNDARY / BITS_PER_UNIT;
05098 size = int_size_in_bytes (type);
05099
05100 ptr = build_pointer_type (type);
05101
05102
05103 if (size > 8)
05104 {
05105 t = build (PREDECREMENT_EXPR, TREE_TYPE (valist), valist,
05106 build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0));
05107 TREE_SIDE_EFFECTS (t) = 1;
05108
05109 pptr = build_pointer_type (ptr);
05110 t = build1 (NOP_EXPR, pptr, t);
05111 TREE_SIDE_EFFECTS (t) = 1;
05112
05113 t = build1 (INDIRECT_REF, ptr, t);
05114 TREE_SIDE_EFFECTS (t) = 1;
05115 }
05116 else
05117 {
05118 t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
05119 build_int_2 (-size, -1));
05120
05121
05122
05123 t = build (BIT_AND_EXPR, TREE_TYPE (valist), t,
05124 build_int_2 ((size > 4 ? -8 : -4), -1));
05125
05126 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
05127 TREE_SIDE_EFFECTS (t) = 1;
05128
05129 ofs = (8 - size) % 4;
05130 if (ofs)
05131 {
05132 t = build (PLUS_EXPR, TREE_TYPE (valist), t, build_int_2 (ofs, 0));
05133 TREE_SIDE_EFFECTS (t) = 1;
05134 }
05135
05136 t = build1 (NOP_EXPR, ptr, t);
05137 TREE_SIDE_EFFECTS (t) = 1;
05138 }
05139
05140
05141 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
05142 }
05143
05144
05145
05146
05147
05148
05149
05150
05151
05152
05153 const char *
05154 output_cbranch (operands, nullify, length, negated, insn)
05155 rtx *operands;
05156 int nullify, length, negated;
05157 rtx insn;
05158 {
05159 static char buf[100];
05160 int useskip = 0;
05161
05162
05163
05164
05165
05166
05167 if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
05168 return "";
05169
05170
05171
05172 if (length == 8 && dbr_sequence_length () == 0)
05173 nullify = 1;
05174
05175
05176
05177 if (! nullify && length == 4 && dbr_sequence_length () == 0)
05178 nullify = forward_branch_p (insn);
05179
05180
05181
05182
05183 if (length == 4
05184 && next_real_insn (insn) != 0
05185 && get_attr_length (next_real_insn (insn)) == 4
05186 && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
05187 && nullify)
05188 useskip = 1;
05189
05190 switch (length)
05191 {
05192
05193
05194 case 4:
05195 if (useskip)
05196 strcpy (buf, "{com%I2clr,|cmp%I2clr,}");
05197 else
05198 strcpy (buf, "{com%I2b,|cmp%I2b,}");
05199 if (GET_MODE (operands[1]) == DImode)
05200 strcat (buf, "*");
05201 if (negated)
05202 strcat (buf, "%B3");
05203 else
05204 strcat (buf, "%S3");
05205 if (useskip)
05206 strcat (buf, " %2,%r1,%%r0");
05207 else if (nullify)
05208 strcat (buf, ",n %2,%r1,%0");
05209 else
05210 strcat (buf, " %2,%r1,%0");
05211 break;
05212
05213
05214
05215
05216 case 8:
05217
05218
05219 if (dbr_sequence_length () != 0
05220 && ! forward_branch_p (insn)
05221 && nullify)
05222 {
05223 strcpy (buf, "{com%I2b,|cmp%I2b,}");
05224 if (GET_MODE (operands[1]) == DImode)
05225 strcat (buf, "*");
05226 if (negated)
05227 strcat (buf, "%S3");
05228 else
05229 strcat (buf, "%B3");
05230 strcat (buf, ",n %2,%r1,.+12\n\tb %0");
05231 }
05232
05233
05234
05235 else if (dbr_sequence_length () == 0
05236 && ! forward_branch_p (insn)
05237 && INSN_ADDRESSES_SET_P ()
05238 && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
05239 - INSN_ADDRESSES (INSN_UID (insn)) - 8))
05240 {
05241 strcpy (buf, "{com%I2b,|cmp%I2b,}");
05242 if (GET_MODE (operands[1]) == DImode)
05243 strcat (buf, "*");
05244 if (negated)
05245 strcat (buf, "%B3 %2,%r1,%0%#");
05246 else
05247 strcat (buf, "%S3 %2,%r1,%0%#");
05248 }
05249 else
05250 {
05251 strcpy (buf, "{com%I2clr,|cmp%I2clr,}");
05252 if (GET_MODE (operands[1]) == DImode)
05253 strcat (buf, "*");
05254 if (negated)
05255 strcat (buf, "%S3");
05256 else
05257 strcat (buf, "%B3");
05258 if (nullify)
05259 strcat (buf, " %2,%r1,%%r0\n\tb,n %0");
05260 else
05261 strcat (buf, " %2,%r1,%%r0\n\tb %0");
05262 }
05263 break;
05264
05265 case 20:
05266
05267
05268 if (optimize)
05269 abort ();
05270
05271
05272
05273 if (negated)
05274 strcpy (buf, "{com%I2b,%S3,n %2,%r1,.+20|cmp%I2b,%S3,n %2,%r1,.+20}");
05275 else
05276 strcpy (buf, "{com%I2b,%B3,n %2,%r1,.+20|cmp%I2b,%B3,n %2,%r1,.+20}");
05277 if (GET_MODE (operands[1]) == DImode)
05278 {
05279 if (negated)
05280 strcpy (buf,
05281 "{com%I2b,*%S3,n %2,%r1,.+20|cmp%I2b,*%S3,n %2,%r1,.+20}");
05282 else
05283 strcpy (buf,
05284 "{com%I2b,*%B3,n %2,%r1,.+20|cmp%I2b,*%B3,n %2,%r1,.+20}");
05285 }
05286 output_asm_insn (buf, operands);
05287
05288
05289 output_asm_insn ("stw %%r1,-16(%%r30)", operands);
05290
05291
05292 output_asm_insn ("ldil L'%l0,%%r1\n\tbe R'%l0(%%sr4,%%r1)", operands);
05293
05294
05295
05296 return "ldw -16(%%r30),%%r1";
05297
05298 case 28:
05299
05300
05301
05302 if (optimize)
05303 abort ();
05304
05305
05306
05307 if (negated)
05308 strcpy (buf, "{com%I2b,%S3,n %2,%r1,.+28|cmp%I2b,%S3,n %2,%r1,.+28}");
05309 else
05310 strcpy (buf, "{com%I2b,%B3,n %2,%r1,.+28|cmp%I2b,%B3,n %2,%r1,.+28}");
05311 if (GET_MODE (operands[1]) == DImode)
05312 {
05313 if (negated)
05314 strcpy (buf, "{com%I2b,*%S3,n %2,%r1,.+28|cmp%I2b,*%S3,n %2,%r1,.+28}");
05315 else
05316 strcpy (buf, "{com%I2b,*%B3,n %2,%r1,.+28|cmp%I2b,*%B3,n %2,%r1,.+28}");
05317 }
05318 output_asm_insn (buf, operands);
05319
05320
05321 output_asm_insn ("stw %%r1,-16(%%r30)", operands);
05322
05323
05324 {
05325 rtx xoperands[5];
05326
05327 xoperands[0] = operands[0];
05328 xoperands[1] = operands[1];
05329 xoperands[2] = operands[2];
05330 xoperands[3] = operands[3];
05331 xoperands[4] = gen_label_rtx ();
05332
05333 output_asm_insn ("{bl|b,l} .+8,%%r1\n\taddil L'%l0-%l4,%%r1",
05334 xoperands);
05335 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
05336 CODE_LABEL_NUMBER (xoperands[4]));
05337 output_asm_insn ("ldo R'%l0-%l4(%%r1),%%r1\n\tbv %%r0(%%r1)",
05338 xoperands);
05339 }
05340
05341
05342
05343 return "ldw -16(%%r30),%%r1";
05344
05345 default:
05346 abort ();
05347 }
05348 return buf;
05349 }
05350
05351
05352
05353
05354
05355
05356 const char *
05357 output_bb (operands, nullify, length, negated, insn, which)
05358 rtx *operands ATTRIBUTE_UNUSED;
05359 int nullify, length, negated;
05360 rtx insn;
05361 int which;
05362 {
05363 static char buf[100];
05364 int useskip = 0;
05365
05366
05367
05368
05369
05370
05371 if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
05372 return "";
05373
05374
05375
05376 if (length == 8 && dbr_sequence_length () == 0)
05377 nullify = 1;
05378
05379
05380
05381 if (! nullify && length == 4 && dbr_sequence_length () == 0)
05382 nullify = forward_branch_p (insn);
05383
05384
05385
05386
05387
05388 if (length == 4
05389 && next_real_insn (insn) != 0
05390 && get_attr_length (next_real_insn (insn)) == 4
05391 && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
05392 && nullify)
05393 useskip = 1;
05394
05395 switch (length)
05396 {
05397
05398
05399
05400 case 4:
05401 if (useskip)
05402 strcpy (buf, "{extrs,|extrw,s,}");
05403 else
05404 strcpy (buf, "bb,");
05405 if (useskip && GET_MODE (operands[0]) == DImode)
05406 strcpy (buf, "extrd,s,*");
05407 else if (GET_MODE (operands[0]) == DImode)
05408 strcpy (buf, "bb,*");
05409 if ((which == 0 && negated)
05410 || (which == 1 && ! negated))
05411 strcat (buf, ">=");
05412 else
05413 strcat (buf, "<");
05414 if (useskip)
05415 strcat (buf, " %0,%1,1,%%r0");
05416 else if (nullify && negated)
05417 strcat (buf, ",n %0,%1,%3");
05418 else if (nullify && ! negated)
05419 strcat (buf, ",n %0,%1,%2");
05420 else if (! nullify && negated)
05421 strcat (buf, "%0,%1,%3");
05422 else if (! nullify && ! negated)
05423 strcat (buf, " %0,%1,%2");
05424 break;
05425
05426
05427
05428
05429 case 8:
05430
05431
05432 if (dbr_sequence_length () != 0
05433 && ! forward_branch_p (insn)
05434 && nullify)
05435 {
05436 strcpy (buf, "bb,");
05437 if (GET_MODE (operands[0]) == DImode)
05438 strcat (buf, "*");
05439 if ((which == 0 && negated)
05440 || (which == 1 && ! negated))
05441 strcat (buf, "<");
05442 else
05443 strcat (buf, ">=");
05444 if (negated)
05445 strcat (buf, ",n %0,%1,.+12\n\tb %3");
05446 else
05447 strcat (buf, ",n %0,%1,.+12\n\tb %2");
05448 }
05449
05450
05451
05452 else if (dbr_sequence_length () == 0
05453 && ! forward_branch_p (insn)
05454 && INSN_ADDRESSES_SET_P ()
05455 && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
05456 - INSN_ADDRESSES (INSN_UID (insn)) - 8))
05457 {
05458 strcpy (buf, "bb,");
05459 if (GET_MODE (operands[0]) == DImode)
05460 strcat (buf, "*");
05461 if ((which == 0 && negated)
05462 || (which == 1 && ! negated))
05463 strcat (buf, ">=");
05464 else
05465 strcat (buf, "<");
05466 if (negated)
05467 strcat (buf, " %0,%1,%3%#");
05468 else
05469 strcat (buf, " %0,%1,%2%#");
05470 }
05471 else
05472 {
05473 strcpy (buf, "{extrs,|extrw,s,}");
05474 if (GET_MODE (operands[0]) == DImode)
05475 strcpy (buf, "extrd,s,*");
05476 if ((which == 0 && negated)
05477 || (which == 1 && ! negated))
05478 strcat (buf, "<");
05479 else
05480 strcat (buf, ">=");
05481 if (nullify && negated)
05482 strcat (buf, " %0,%1,1,%%r0\n\tb,n %3");
05483 else if (nullify && ! negated)
05484 strcat (buf, " %0,%1,1,%%r0\n\tb,n %2");
05485 else if (negated)
05486 strcat (buf, " %0,%1,1,%%r0\n\tb %3");
05487 else
05488 strcat (buf, " %0,%1,1,%%r0\n\tb %2");
05489 }
05490 break;
05491
05492 default:
05493 abort ();
05494 }
05495 return buf;
05496 }
05497
05498
05499
05500
05501
05502
05503
05504 const char *
05505 output_bvb (operands, nullify, length, negated, insn, which)
05506 rtx *operands ATTRIBUTE_UNUSED;
05507 int nullify, length, negated;
05508 rtx insn;
05509 int which;
05510 {
05511 static char buf[100];
05512 int useskip = 0;
05513
05514
05515
05516
05517
05518
05519 if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
05520 return "";
05521
05522
05523
05524 if (length == 8 && dbr_sequence_length () == 0)
05525 nullify = 1;
05526
05527
05528
05529 if (! nullify && length == 4 && dbr_sequence_length () == 0)
05530 nullify = forward_branch_p (insn);
05531
05532
05533
05534
05535
05536 if (length == 4
05537 && next_real_insn (insn) != 0
05538 && get_attr_length (next_real_insn (insn)) == 4
05539 && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
05540 && nullify)
05541 useskip = 1;
05542
05543 switch (length)
05544 {
05545
05546
05547
05548 case 4:
05549 if (useskip)
05550 strcpy (buf, "{vextrs,|extrw,s,}");
05551 else
05552 strcpy (buf, "{bvb,|bb,}");
05553 if (useskip && GET_MODE (operands[0]) == DImode)
05554 strcpy (buf, "extrd,s,*}");
05555 else if (GET_MODE (operands[0]) == DImode)
05556 strcpy (buf, "bb,*");
05557 if ((which == 0 && negated)
05558 || (which == 1 && ! negated))
05559 strcat (buf, ">=");
05560 else
05561 strcat (buf, "<");
05562 if (useskip)
05563 strcat (buf, "{ %0,1,%%r0| %0,%%sar,1,%%r0}");
05564 else if (nullify && negated)
05565 strcat (buf, "{,n %0,%3|,n %0,%%sar,%3}");
05566 else if (nullify && ! negated)
05567 strcat (buf, "{,n %0,%2|,n %0,%%sar,%2}");
05568 else if (! nullify && negated)
05569 strcat (buf, "{%0,%3|%0,%%sar,%3}");
05570 else if (! nullify && ! negated)
05571 strcat (buf, "{ %0,%2| %0,%%sar,%2}");
05572 break;
05573
05574
05575
05576
05577 case 8:
05578
05579
05580 if (dbr_sequence_length () != 0
05581 && ! forward_branch_p (insn)
05582 && nullify)
05583 {
05584 strcpy (buf, "{bvb,|bb,}");
05585 if (GET_MODE (operands[0]) == DImode)
05586 strcat (buf, "*");
05587 if ((which == 0 && negated)
05588 || (which == 1 && ! negated))
05589 strcat (buf, "<");
05590 else
05591 strcat (buf, ">=");
05592 if (negated)
05593 strcat (buf, "{,n %0,.+12\n\tb %3|,n %0,%%sar,.+12\n\tb %3}");
05594 else
05595 strcat (buf, "{,n %0,.+12\n\tb %2|,n %0,%%sar,.+12\n\tb %2}");
05596 }
05597
05598
05599
05600 else if (dbr_sequence_length () == 0
05601 && ! forward_branch_p (insn)
05602 && INSN_ADDRESSES_SET_P ()
05603 && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
05604 - INSN_ADDRESSES (INSN_UID (insn)) - 8))
05605 {
05606 strcpy (buf, "{bvb,|bb,}");
05607 if (GET_MODE (operands[0]) == DImode)
05608 strcat (buf, "*");
05609 if ((which == 0 && negated)
05610 || (which == 1 && ! negated))
05611 strcat (buf, ">=");
05612 else
05613 strcat (buf, "<");
05614 if (negated)
05615 strcat (buf, "{ %0,%3%#| %0,%%sar,%3%#}");
05616 else
05617 strcat (buf, "{ %0,%2%#| %0,%%sar,%2%#}");
05618 }
05619 else
05620 {
05621 strcpy (buf, "{vextrs,|extrw,s,}");
05622 if (GET_MODE (operands[0]) == DImode)
05623 strcpy (buf, "extrd,s,*");
05624 if ((which == 0 && negated)
05625 || (which == 1 && ! negated))
05626 strcat (buf, "<");
05627 else
05628 strcat (buf, ">=");
05629 if (nullify && negated)
05630 strcat (buf, "{ %0,1,%%r0\n\tb,n %3| %0,%%sar,1,%%r0\n\tb,n %3}");
05631 else if (nullify && ! negated)
05632 strcat (buf, "{ %0,1,%%r0\n\tb,n %2| %0,%%sar,1,%%r0\n\tb,n %2}");
05633 else if (negated)
05634 strcat (buf, "{ %0,1,%%r0\n\tb %3| %0,%%sar,1,%%r0\n\tb %3}");
05635 else
05636 strcat (buf, "{ %0,1,%%r0\n\tb %2| %0,%%sar,1,%%r0\n\tb %2}");
05637 }
05638 break;
05639
05640 default:
05641 abort ();
05642 }
05643 return buf;
05644 }
05645
05646
05647
05648
05649
05650 const char *
05651 output_dbra (operands, insn, which_alternative)
05652 rtx *operands;
05653 rtx insn;
05654 int which_alternative;
05655 {
05656
05657
05658
05659
05660 if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
05661 {
05662 if (which_alternative == 0)
05663 return "ldo %1(%0),%0";
05664 else if (which_alternative == 1)
05665 {
05666 output_asm_insn ("{fstws|fstw} %0,-16(%%r30)", operands);
05667 output_asm_insn ("ldw -16(%%r30),%4", operands);
05668 output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(%%r30)", operands);
05669 return "{fldws|fldw} -16(%%r30),%0";
05670 }
05671 else
05672 {
05673 output_asm_insn ("ldw %0,%4", operands);
05674 return "ldo %1(%4),%4\n\tstw %4,%0";
05675 }
05676 }
05677
05678 if (which_alternative == 0)
05679 {
05680 int nullify = INSN_ANNULLED_BRANCH_P (insn);
05681 int length = get_attr_length (insn);
05682
05683
05684
05685 if (length == 8 && dbr_sequence_length () == 0)
05686 nullify = 1;
05687
05688
05689
05690 if (! nullify && length == 4 && dbr_sequence_length () == 0)
05691 nullify = forward_branch_p (insn);
05692
05693
05694 if (length == 4 && nullify)
05695 return "addib,%C2,n %1,%0,%3";
05696 else if (length == 4 && ! nullify)
05697 return "addib,%C2 %1,%0,%3";
05698 else if (length == 8)
05699 {
05700
05701
05702 if (dbr_sequence_length () != 0
05703 && ! forward_branch_p (insn)
05704 && nullify)
05705 return "addib,%N2,n %1,%0,.+12\n\tb %3";
05706
05707
05708
05709 else if (dbr_sequence_length () == 0
05710 && ! forward_branch_p (insn)
05711 && INSN_ADDRESSES_SET_P ()
05712 && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
05713 - INSN_ADDRESSES (INSN_UID (insn)) - 8))
05714 return "addib,%C2 %1,%0,%3%#";
05715
05716
05717 if (nullify)
05718 return "addi,%N2 %1,%0,%0\n\tb,n %3";
05719 else
05720 return "addi,%N2 %1,%0,%0\n\tb %3";
05721 }
05722 else
05723 abort ();
05724 }
05725
05726 else if (which_alternative == 1)
05727 {
05728
05729
05730
05731 output_asm_insn ("{fstws|fstw} %0,-16(%%r30)\n\tldw -16(%%r30),%4",
05732 operands);
05733 output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(%%r30)", operands);
05734 if (get_attr_length (insn) == 24)
05735 return "{comb|cmpb},%S2 %%r0,%4,%3\n\t{fldws|fldw} -16(%%r30),%0";
05736 else
05737 return "{comclr|cmpclr},%B2 %%r0,%4,%%r0\n\tb %3\n\t{fldws|fldw} -16(%%r30),%0";
05738 }
05739
05740 else
05741 {
05742
05743
05744 output_asm_insn ("ldw %0,%4", operands);
05745 if (get_attr_length (insn) == 12)
05746 return "addib,%C2 %1,%4,%3\n\tstw %4,%0";
05747 else
05748 return "addi,%N2 %1,%4,%4\n\tb %3\n\tstw %4,%0";
05749 }
05750 }
05751
05752
05753
05754
05755
05756 const char *
05757 output_movb (operands, insn, which_alternative, reverse_comparison)
05758 rtx *operands;
05759 rtx insn;
05760 int which_alternative;
05761 int reverse_comparison;
05762 {
05763
05764
05765
05766
05767 if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
05768 {
05769 if (which_alternative == 0)
05770 return "copy %1,%0";
05771 else if (which_alternative == 1)
05772 {
05773 output_asm_insn ("stw %1,-16(%%r30)", operands);
05774 return "{fldws|fldw} -16(%%r30),%0";
05775 }
05776 else if (which_alternative == 2)
05777 return "stw %1,%0";
05778 else
05779 return "mtsar %r1";
05780 }
05781
05782
05783 if (reverse_comparison)
05784 PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2])));
05785
05786 if (which_alternative == 0)
05787 {
05788 int nullify = INSN_ANNULLED_BRANCH_P (insn);
05789 int length = get_attr_length (insn);
05790
05791
05792
05793 if (length == 8 && dbr_sequence_length () == 0)
05794 nullify = 1;
05795
05796
05797
05798 if (! nullify && length == 4 && dbr_sequence_length () == 0)
05799 nullify = forward_branch_p (insn);
05800
05801
05802 if (length == 4 && nullify)
05803 return "movb,%C2,n %1,%0,%3";
05804 else if (length == 4 && ! nullify)
05805 return "movb,%C2 %1,%0,%3";
05806 else if (length == 8)
05807 {
05808
05809
05810 if (dbr_sequence_length () != 0
05811 && ! forward_branch_p (insn)
05812 && nullify)
05813 return "movb,%N2,n %1,%0,.+12\n\tb %3";
05814
05815
05816
05817
05818 else if (dbr_sequence_length () == 0
05819 && ! forward_branch_p (insn)
05820 && INSN_ADDRESSES_SET_P ()
05821 && VAL_14_BITS_P (INSN_ADDRESSES (INSN_UID (JUMP_LABEL (insn)))
05822 - INSN_ADDRESSES (INSN_UID (insn)) - 8))
05823 return "movb,%C2 %1,%0,%3%#";
05824
05825 if (nullify)
05826 return "or,%N2 %1,%%r0,%0\n\tb,n %3";
05827 else
05828 return "or,%N2 %1,%%r0,%0\n\tb %3";
05829 }
05830 else
05831 abort ();
05832 }
05833
05834 else if (which_alternative == 1)
05835 {
05836
05837
05838
05839 output_asm_insn ("stw %1,-16(%%r30)", operands);
05840 if (get_attr_length (insn) == 12)
05841 return "{comb|cmpb},%S2 %%r0,%1,%3\n\t{fldws|fldw} -16(%%r30),%0";
05842 else
05843 return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\t{fldws|fldw} -16(%%r30),%0";
05844 }
05845
05846 else if (which_alternative == 2)
05847 {
05848
05849
05850 if (get_attr_length (insn) == 8)
05851 return "{comb|cmpb},%S2 %%r0,%1,%3\n\tstw %1,%0";
05852 else
05853 return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\tstw %1,%0";
05854 }
05855
05856 else
05857 {
05858 if (get_attr_length (insn) == 8)
05859 return "{comb|cmpb},%S2 %%r0,%1,%3\n\tmtsar %r1";
05860 else
05861 return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tbl %3\n\tmtsar %r1";
05862 }
05863 }
05864
05865
05866
05867
05868
05869
05870
05871 const char *
05872 output_millicode_call (insn, call_dest)
05873 rtx insn;
05874 rtx call_dest;
05875 {
05876 int distance;
05877 rtx xoperands[4];
05878 rtx seq_insn;
05879
05880 xoperands[3] = gen_rtx_REG (Pmode, TARGET_64BIT ? 2 : 31);
05881
05882
05883
05884
05885
05886
05887 if ((dbr_sequence_length () == 0
05888 && (get_attr_length (insn) == 8
05889 || (get_attr_length (insn) == 28
05890 && get_attr_type (insn) == TYPE_MULTI)))
05891 || (dbr_sequence_length () != 0
05892 && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN
05893 && get_attr_length (insn) == 4))
05894 {
05895 xoperands[0] = call_dest;
05896 output_asm_insn ("{bl|b,l} %0,%3%#", xoperands);
05897 return "";
05898 }
05899
05900
05901 if (get_attr_length (insn) > 8)
05902 {
05903 int delay_insn_deleted = 0;
05904
05905
05906 if (dbr_sequence_length () != 0
05907 && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN)
05908 {
05909
05910
05911 final_scan_insn (NEXT_INSN (insn), asm_out_file, optimize, 0, 0);
05912
05913
05914 PUT_CODE (NEXT_INSN (insn), NOTE);
05915 NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
05916 NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
05917 delay_insn_deleted = 1;
05918 }
05919
05920
05921 if (flag_pic)
05922 {
05923 xoperands[0] = call_dest;
05924 xoperands[1] = gen_label_rtx ();
05925
05926 output_asm_insn ("{bl|b,l} .+8,%%r1", xoperands);
05927
05928
05929 output_asm_insn ("addil L%%%0-%1,%%r1", xoperands);
05930 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
05931 CODE_LABEL_NUMBER (xoperands[1]));
05932 output_asm_insn ("ldo R%%%0-%1(%%r1),%%r1", xoperands);
05933
05934
05935 output_asm_insn ("blr 0,%3", xoperands);
05936
05937
05938 output_asm_insn ("bv,n %%r0(%%r1)", xoperands);
05939
05940
05941
05942 output_asm_insn ("nop", xoperands);
05943 }
05944
05945
05946 else if (TARGET_PORTABLE_RUNTIME)
05947 {
05948 xoperands[0] = call_dest;
05949
05950 output_asm_insn ("ldil L%%%0,%%r29", xoperands);
05951 output_asm_insn ("ldo R%%%0(%%r29),%%r29", xoperands);
05952
05953
05954 output_asm_insn ("blr %%r0,%3", xoperands);
05955
05956
05957 output_asm_insn ("bv,n %%r0(%%r29)", xoperands);
05958
05959
05960
05961 output_asm_insn ("nop", xoperands);
05962 }
05963
05964
05965 else
05966 {
05967 xoperands[0] = call_dest;
05968 output_asm_insn ("ldil L%%%0,%3", xoperands);
05969 if (TARGET_PA_20)
05970 output_asm_insn ("be,l R%%%0(%%sr4,%3),%%sr0,%%r31", xoperands);
05971 else
05972 output_asm_insn ("ble R%%%0(%%sr4,%3)", xoperands);
05973 output_asm_insn ("nop", xoperands);
05974 }
05975
05976
05977 if (dbr_sequence_length () != 0
05978 && !delay_insn_deleted)
05979 {
05980 xoperands[0] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
05981 output_asm_insn ("b,n %0", xoperands);
05982
05983
05984 PUT_CODE (NEXT_INSN (insn), NOTE);
05985 NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
05986 NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
05987 }
05988 return "";
05989 }
05990
05991
05992
05993
05994
05995
05996 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
05997
05998 distance = INSN_ADDRESSES (INSN_UID (JUMP_LABEL (NEXT_INSN (insn))))
05999 - INSN_ADDRESSES (INSN_UID (seq_insn)) - 8;
06000
06001
06002
06003
06004
06005
06006
06007 xoperands[0] = call_dest;
06008 xoperands[1] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
06009 if (! VAL_14_BITS_P (distance))
06010 output_asm_insn ("{bl|b,l} %0,%3\n\tnop\n\tb,n %1", xoperands);
06011 else
06012 {
06013 xoperands[2] = gen_label_rtx ();
06014 output_asm_insn ("\n\t{bl|b,l} %0,%3\n\tldo %1-%2(%3),%3",
06015 xoperands);
06016 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
06017 CODE_LABEL_NUMBER (xoperands[2]));
06018 }
06019
06020
06021 PUT_CODE (NEXT_INSN (insn), NOTE);
06022 NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
06023 NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
06024 return "";
06025 }
06026
06027 extern struct obstack permanent_obstack;
06028
06029
06030
06031
06032
06033
06034 const char *
06035 output_call (insn, call_dest, sibcall)
06036 rtx insn;
06037 rtx call_dest;
06038 int sibcall;
06039 {
06040 int distance;
06041 rtx xoperands[4];
06042 rtx seq_insn;
06043
06044
06045
06046
06047 if ((dbr_sequence_length () == 0
06048 && get_attr_length (insn) == 8)
06049 || (dbr_sequence_length () != 0
06050 && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN
06051 && get_attr_length (insn) == 4))
06052 {
06053 xoperands[0] = call_dest;
06054 xoperands[1] = gen_rtx_REG (word_mode, sibcall ? 0 : 2);
06055 output_asm_insn ("{bl|b,l} %0,%1%#", xoperands);
06056 return "";
06057 }
06058
06059
06060 if (get_attr_length (insn) > 8)
06061 {
06062 int delay_insn_deleted = 0;
06063 rtx xoperands[2];
06064 rtx link;
06065
06066
06067
06068
06069
06070
06071
06072
06073 if (dbr_sequence_length () != 0
06074 && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN)
06075 {
06076
06077
06078
06079 final_scan_insn (NEXT_INSN (insn), asm_out_file, optimize, 0, 0);
06080
06081
06082 PUT_CODE (NEXT_INSN (insn), NOTE);
06083 NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
06084 NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
06085 delay_insn_deleted = 1;
06086 }
06087
06088
06089 for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
06090 {
06091 int arg_mode, regno;
06092 rtx use = XEXP (link, 0);
06093 if (! (GET_CODE (use) == USE
06094 && GET_CODE (XEXP (use, 0)) == REG
06095 && FUNCTION_ARG_REGNO_P (REGNO (XEXP (use, 0)))))
06096 continue;
06097
06098 arg_mode = GET_MODE (XEXP (use, 0));
06099 regno = REGNO (XEXP (use, 0));
06100
06101 if (regno >= 32 && regno <= 39)
06102 {
06103
06104
06105 if (arg_mode == SFmode)
06106 {
06107 xoperands[0] = XEXP (use, 0);
06108 xoperands[1] = gen_rtx_REG (SImode, 26 - (regno - 32) / 2);
06109 output_asm_insn ("{fstws|fstw} %0,-16(%%sr0,%%r30)",
06110 xoperands);
06111 output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands);
06112 }
06113 else
06114 {
06115 xoperands[0] = XEXP (use, 0);
06116 xoperands[1] = gen_rtx_REG (DImode, 25 - (regno - 34) / 2);
06117 output_asm_insn ("{fstds|fstd} %0,-16(%%sr0,%%r30)",
06118 xoperands);
06119 output_asm_insn ("ldw -12(%%sr0,%%r30),%R1", xoperands);
06120 output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands);
06121 }
06122 }
06123 }
06124
06125
06126
06127 {
06128 int i;
06129 const char *name = XSTR (call_dest, 0);
06130
06131
06132
06133
06134
06135 for (i = 0; i < n_deferred_plabels; i++)
06136 if (strcmp (name, deferred_plabels[i].name) == 0)
06137 break;
06138
06139
06140
06141 if (deferred_plabels == NULL || i == n_deferred_plabels)
06142 {
06143 const char *real_name;
06144
06145 if (deferred_plabels == 0)
06146 deferred_plabels = (struct deferred_plabel *)
06147 xmalloc (1 * sizeof (struct deferred_plabel));
06148 else
06149 deferred_plabels = (struct deferred_plabel *)
06150 xrealloc (deferred_plabels,
06151 ((n_deferred_plabels + 1)
06152 * sizeof (struct deferred_plabel)));
06153
06154 i = n_deferred_plabels++;
06155 deferred_plabels[i].internal_label = gen_label_rtx ();
06156 deferred_plabels[i].name = obstack_alloc (&permanent_obstack,
06157 strlen (name) + 1);
06158 strcpy (deferred_plabels[i].name, name);
06159
06160
06161
06162 STRIP_NAME_ENCODING (real_name, name);
06163 TREE_SYMBOL_REFERENCED (get_identifier (real_name)) = 1;
06164 }
06165
06166
06167
06168
06169
06170 if (flag_pic)
06171 {
06172 xoperands[0] = deferred_plabels[i].internal_label;
06173 xoperands[1] = gen_label_rtx ();
06174
06175 output_asm_insn ("addil LT%%%0,%%r19", xoperands);
06176 output_asm_insn ("ldw RT%%%0(%%r1),%%r22", xoperands);
06177 output_asm_insn ("ldw 0(%%r22),%%r22", xoperands);
06178
06179
06180 output_asm_insn ("{bl|b,l} .+8,%%r1", xoperands);
06181
06182
06183 if (TARGET_SOM || !TARGET_GAS)
06184 {
06185 output_asm_insn ("addil L%%$$dyncall-%1,%%r1", xoperands);
06186 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
06187 CODE_LABEL_NUMBER (xoperands[1]));
06188 output_asm_insn ("ldo R%%$$dyncall-%1(%%r1),%%r1", xoperands);
06189 }
06190 else
06191 {
06192 output_asm_insn ("addil L%%$$dyncall-$PIC_pcrel$0+4,%%r1",
06193 xoperands);
06194 output_asm_insn ("ldo R%%$$dyncall-$PIC_pcrel$0+8(%%r1),%%r1",
06195 xoperands);
06196 }
06197
06198
06199 output_asm_insn ("blr %%r0,%%r31", xoperands);
06200
06201
06202 output_asm_insn ("bv %%r0(%%r1)", xoperands);
06203
06204 if (sibcall)
06205 {
06206
06207
06208 output_asm_insn ("nop", xoperands);
06209 }
06210 else
06211 {
06212
06213 output_asm_insn ("copy %%r31,%%r2", xoperands);
06214 }
06215 }
06216 else
06217 {
06218 xoperands[0] = deferred_plabels[i].internal_label;
06219
06220
06221 output_asm_insn ("addil LR%%%0-$global$,%%r27", xoperands);
06222 output_asm_insn ("ldw RR%%%0-$global$(%%r1),%%r22", xoperands);
06223
06224
06225
06226 output_asm_insn ("ldil L%%$$dyncall,%%r2", xoperands);
06227 if (TARGET_PA_20)
06228 output_asm_insn ("be,l R%%$$dyncall(%%sr4,%%r2),%%sr0,%%r31",
06229 xoperands);
06230 else
06231 output_asm_insn ("ble R%%$$dyncall(%%sr4,%%r2)", xoperands);
06232
06233 if (sibcall)
06234 {
06235
06236
06237 output_asm_insn ("nop", xoperands);
06238 }
06239 else
06240 {
06241
06242 output_asm_insn ("copy %%r31,%%r2", xoperands);
06243 }
06244 }
06245 }
06246
06247
06248 if (dbr_sequence_length () != 0
06249 && !delay_insn_deleted)
06250 {
06251 xoperands[0] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
06252 output_asm_insn ("b,n %0", xoperands);
06253
06254
06255 PUT_CODE (NEXT_INSN (insn), NOTE);
06256 NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
06257 NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
06258 }
06259 return "";
06260 }
06261
06262
06263
06264
06265
06266
06267 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
06268
06269 distance = INSN_ADDRESSES (INSN_UID (JUMP_LABEL (NEXT_INSN (insn))))
06270 - INSN_ADDRESSES (INSN_UID (seq_insn)) - 8;
06271
06272
06273
06274
06275
06276
06277
06278 xoperands[0] = call_dest;
06279 xoperands[1] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
06280 if (! VAL_14_BITS_P (distance))
06281 output_asm_insn ("{bl|b,l} %0,%%r2\n\tnop\n\tb,n %1", xoperands);
06282 else
06283 {
06284 xoperands[3] = gen_label_rtx ();
06285 output_asm_insn ("\n\t{bl|b,l} %0,%%r2\n\tldo %1-%3(%%r2),%%r2",
06286 xoperands);
06287 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
06288 CODE_LABEL_NUMBER (xoperands[3]));
06289 }
06290
06291
06292 PUT_CODE (NEXT_INSN (insn), NOTE);
06293 NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
06294 NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
06295 return "";
06296 }
06297
06298
06299
06300
06301
06302
06303 void
06304 hppa_encode_label (sym)
06305 rtx sym;
06306 {
06307 const char *str = XSTR (sym, 0);
06308 int len = strlen (str) + 1;
06309 char *newstr, *p;
06310
06311 p = newstr = alloca (len + 1);
06312 if (str[0] == '*')
06313 {
06314 str++;
06315 len--;
06316 }
06317 *p++ = '@';
06318 strcpy (p, str);
06319
06320 XSTR (sym, 0) = ggc_alloc_string (newstr, len);
06321 }
06322
06323 int
06324 function_label_operand (op, mode)
06325 rtx op;
06326 enum machine_mode mode ATTRIBUTE_UNUSED;
06327 {
06328 return GET_CODE (op) == SYMBOL_REF && FUNCTION_NAME_P (XSTR (op, 0));
06329 }
06330
06331
06332
06333
06334 int
06335 is_function_label_plus_const (op)
06336 rtx op;
06337 {
06338
06339 if (GET_CODE (op) == CONST)
06340 op = XEXP (op, 0);
06341
06342 return (GET_CODE (op) == PLUS
06343 && function_label_operand (XEXP (op, 0), Pmode)
06344 && GET_CODE (XEXP (op, 1)) == CONST_INT);
06345 }
06346
06347
06348
06349 int
06350 fmpyaddoperands (operands)
06351 rtx *operands;
06352 {
06353 enum machine_mode mode = GET_MODE (operands[0]);
06354
06355
06356 if (mode != SFmode && mode != DFmode)
06357 return 0;
06358
06359
06360 if (! (mode == GET_MODE (operands[1])
06361 && mode == GET_MODE (operands[2])
06362 && mode == GET_MODE (operands[3])
06363 && mode == GET_MODE (operands[4])
06364 && mode == GET_MODE (operands[5])))
06365 return 0;
06366
06367
06368 if (! (GET_CODE (operands[1]) == REG
06369 && GET_CODE (operands[2]) == REG
06370 && GET_CODE (operands[3]) == REG
06371 && GET_CODE (operands[4]) == REG
06372 && GET_CODE (operands[5]) == REG))
06373 return 0;
06374
06375
06376
06377 if (! rtx_equal_p (operands[3], operands[4])
06378 && ! rtx_equal_p (operands[3], operands[5]))
06379 return 0;
06380
06381
06382 if (rtx_equal_p (operands[3], operands[0])
06383 || rtx_equal_p (operands[3], operands[1])
06384 || rtx_equal_p (operands[3], operands[2]))
06385 return 0;
06386
06387
06388 if (rtx_equal_p (operands[4], operands[0])
06389 || rtx_equal_p (operands[5], operands[0]))
06390 return 0;
06391
06392
06393 if (mode == SFmode
06394 && (REGNO_REG_CLASS (REGNO (operands[0])) != FPUPPER_REGS
06395 || REGNO_REG_CLASS (REGNO (operands[1])) != FPUPPER_REGS
06396 || REGNO_REG_CLASS (REGNO (operands[2])) != FPUPPER_REGS
06397 || REGNO_REG_CLASS (REGNO (operands[3])) != FPUPPER_REGS
06398 || REGNO_REG_CLASS (REGNO (operands[4])) != FPUPPER_REGS
06399 || REGNO_REG_CLASS (REGNO (operands[5])) != FPUPPER_REGS))
06400 return 0;
06401
06402
06403 return 1;
06404 }
06405
06406
06407
06408 int
06409 fmpysuboperands (operands)
06410 rtx *operands;
06411 {
06412 enum machine_mode mode = GET_MODE (operands[0]);
06413
06414
06415 if (mode != SFmode && mode != DFmode)
06416 return 0;
06417
06418
06419 if (! (mode == GET_MODE (operands[1])
06420 && mode == GET_MODE (operands[2])
06421 && mode == GET_MODE (operands[3])
06422 && mode == GET_MODE (operands[4])
06423 && mode == GET_MODE (operands[5])))
06424 return 0;
06425
06426
06427 if (! (GET_CODE (operands[1]) == REG
06428 && GET_CODE (operands[2]) == REG
06429 && GET_CODE (operands[3]) == REG
06430 && GET_CODE (operands[4]) == REG
06431 && GET_CODE (operands[5]) == REG))
06432 return 0;
06433
06434
06435
06436 if (! rtx_equal_p (operands[3], operands[4]))
06437 return 0;
06438
06439
06440 if (rtx_equal_p (operands[5], operands[0]))
06441 return 0;
06442
06443
06444 if (rtx_equal_p (operands[3], operands[0])
06445 || rtx_equal_p (operands[3], operands[1])
06446 || rtx_equal_p (operands[3], operands[2]))
06447 return 0;
06448
06449
06450 if (mode == SFmode
06451 && (REGNO_REG_CLASS (REGNO (operands[0])) != FPUPPER_REGS
06452 || REGNO_REG_CLASS (REGNO (operands[1])) != FPUPPER_REGS
06453 || REGNO_REG_CLASS (REGNO (operands[2])) != FPUPPER_REGS
06454 || REGNO_REG_CLASS (REGNO (operands[3])) != FPUPPER_REGS
06455 || REGNO_REG_CLASS (REGNO (operands[4])) != FPUPPER_REGS
06456 || REGNO_REG_CLASS (REGNO (operands[5])) != FPUPPER_REGS))
06457 return 0;
06458
06459
06460 return 1;
06461 }
06462
06463 int
06464 plus_xor_ior_operator (op, mode)
06465 rtx op;
06466 enum machine_mode mode ATTRIBUTE_UNUSED;
06467 {
06468 return (GET_CODE (op) == PLUS || GET_CODE (op) == XOR
06469 || GET_CODE (op) == IOR);
06470 }
06471
06472
06473
06474 static int
06475 shadd_constant_p (val)
06476 int val;
06477 {
06478 if (val == 2 || val == 4 || val == 8)
06479 return 1;
06480 else
06481 return 0;
06482 }
06483
06484
06485
06486 int
06487 shadd_operand (op, mode)
06488 rtx op;
06489 enum machine_mode mode ATTRIBUTE_UNUSED;
06490 {
06491 return (GET_CODE (op) == CONST_INT && shadd_constant_p (INTVAL (op)));
06492 }
06493
06494
06495
06496 int
06497 basereg_operand (op, mode)
06498 rtx op;
06499 enum machine_mode mode;
06500 {
06501
06502
06503
06504 if (!cse_not_expected)
06505 return 0;
06506
06507
06508
06509
06510 if (TARGET_NO_SPACE_REGS)
06511 return (GET_CODE (op) == REG);
06512
06513
06514
06515
06516 if (! flag_omit_frame_pointer && op == frame_pointer_rtx)
06517 return 1;
06518
06519 return (GET_CODE (op) == REG
06520 && REG_POINTER (op)
06521 && register_operand (op, mode));
06522 }
06523
06524
06525
06526 int
06527 non_hard_reg_operand (op, mode)
06528 rtx op;
06529 enum machine_mode mode ATTRIBUTE_UNUSED;
06530 {
06531 return ! (GET_CODE (op) == REG && REGNO (op) < FIRST_PSEUDO_REGISTER);
06532 }
06533
06534
06535
06536 static int
06537 forward_branch_p (insn)
06538 rtx insn;
06539 {
06540 rtx label = JUMP_LABEL (insn);
06541
06542 while (insn)
06543 {
06544 if (insn == label)
06545 break;
06546 else
06547 insn = NEXT_INSN (insn);
06548 }
06549
06550 return (insn == label);
06551 }
06552
06553
06554 int
06555 eq_neq_comparison_operator (op, mode)
06556 rtx op;
06557 enum machine_mode mode ATTRIBUTE_UNUSED;
06558 {
06559 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
06560 }
06561
06562
06563 int
06564 movb_comparison_operator (op, mode)
06565 rtx op;
06566 enum machine_mode mode ATTRIBUTE_UNUSED;
06567 {
06568 return (GET_CODE (op) == EQ || GET_CODE (op) == NE
06569 || GET_CODE (op) == LT || GET_CODE (op) == GE);
06570 }
06571
06572
06573 int
06574 jump_in_call_delay (insn)
06575 rtx insn;
06576 {
06577
06578 if (GET_CODE (insn) != JUMP_INSN)
06579 return 0;
06580
06581 if (PREV_INSN (insn)
06582 && PREV_INSN (PREV_INSN (insn))
06583 && GET_CODE (next_active_insn (PREV_INSN (PREV_INSN (insn)))) == INSN)
06584 {
06585 rtx test_insn = next_active_insn (PREV_INSN (PREV_INSN (insn)));
06586
06587 return (GET_CODE (PATTERN (test_insn)) == SEQUENCE
06588 && XVECEXP (PATTERN (test_insn), 0, 1) == insn);
06589
06590 }
06591 else
06592 return 0;
06593 }
06594
06595
06596
06597 const char *
06598 output_parallel_movb (operands, length)
06599 rtx *operands;
06600 int length;
06601 {
06602
06603 if (length == 4)
06604 return "mov%I1b,tr %1,%0,%2";
06605
06606
06607 if (dbr_sequence_length () == 0)
06608 {
06609
06610
06611 if (GET_CODE (operands[1]) == CONST_INT)
06612 return "b %2\n\tldi %1,%0";
06613 else
06614 return "b %2\n\tcopy %1,%0";
06615 }
06616 else
06617 {
06618
06619 if (GET_CODE (operands[1]) == CONST_INT)
06620 return "ldi %1,%0\n\tb %2";
06621 else
06622 return "copy %1,%0\n\tb %2";
06623 }
06624 }
06625
06626
06627
06628 const char *
06629 output_parallel_addb (operands, length)
06630 rtx *operands;
06631 int length;
06632 {
06633
06634
06635 if (operands[0] == operands[1])
06636 operands[1] = operands[2];
06637
06638
06639 if (length == 4)
06640 return "add%I1b,tr %1,%0,%3";
06641
06642
06643 if (dbr_sequence_length () == 0)
06644 {
06645
06646
06647 return "b %3\n\tadd%I1 %1,%0,%0";
06648 }
06649 else
06650 {
06651
06652 return "add%I1 %1,%0,%0\n\tb %3";
06653 }
06654 }
06655
06656
06657
06658
06659
06660
06661
06662
06663
06664
06665 int
06666 following_call (insn)
06667 rtx insn;
06668 {
06669
06670
06671 if (pa_cpu != PROCESSOR_8000)
06672 return 0;
06673
06674
06675 insn = PREV_INSN (insn);
06676 while (insn && GET_CODE (insn) == NOTE)
06677 insn = PREV_INSN (insn);
06678
06679
06680 if (insn
06681 && ((GET_CODE (insn) == CALL_INSN
06682 && get_attr_type (insn) != TYPE_DYNCALL)
06683 || (GET_CODE (insn) == INSN
06684 && GET_CODE (PATTERN (insn)) != SEQUENCE
06685 && GET_CODE (PATTERN (insn)) != USE
06686 && GET_CODE (PATTERN (insn)) != CLOBBER
06687 && get_attr_type (insn) == TYPE_MILLI)))
06688 return 1;
06689
06690 return 0;
06691 }
06692
06693
06694
06695
06696
06697
06698
06699
06700
06701
06702
06703
06704
06705
06706
06707
06708
06709
06710
06711
06712
06713
06714
06715
06716
06717
06718
06719
06720
06721
06722
06723
06724
06725
06726 void
06727 pa_reorg (insns)
06728 rtx insns;
06729 {
06730 rtx insn;
06731
06732 remove_useless_addtr_insns (insns, 1);
06733
06734 if (pa_cpu < PROCESSOR_8000)
06735 pa_combine_instructions (get_insns ());
06736
06737
06738
06739 if (optimize > 0 && !TARGET_BIG_SWITCH)
06740 {
06741
06742 insns = get_insns ();
06743 for (insn = insns; insn; insn = NEXT_INSN (insn))
06744 {
06745 rtx pattern, tmp, location;
06746 unsigned int length, i;
06747
06748
06749 if (GET_CODE (insn) != JUMP_INSN
06750 || (GET_CODE (PATTERN (insn)) != ADDR_VEC
06751 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC))
06752 continue;
06753
06754
06755 emit_insn_before (gen_begin_brtab (), insn);
06756
06757 pattern = PATTERN (insn);
06758 location = PREV_INSN (insn);
06759 length = XVECLEN (pattern, GET_CODE (pattern) == ADDR_DIFF_VEC);
06760
06761 for (i = 0; i < length; i++)
06762 {
06763
06764
06765 tmp = gen_label_rtx ();
06766 LABEL_NUSES (tmp) = 1;
06767 emit_label_after (tmp, location);
06768 location = NEXT_INSN (location);
06769
06770 if (GET_CODE (pattern) == ADDR_VEC)
06771 {
06772
06773 tmp = gen_jump (XEXP (XVECEXP (pattern, 0, i), 0));
06774 tmp = emit_jump_insn_after (tmp, location);
06775 JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 0, i), 0);
06776
06777
06778
06779
06780
06781
06782
06783
06784
06785
06786
06787
06788
06789
06790
06791
06792 PUT_MODE (tmp, SImode);
06793 LABEL_NUSES (JUMP_LABEL (tmp))++;
06794 location = NEXT_INSN (location);
06795 }
06796 else
06797 {
06798
06799 tmp = gen_jump (XEXP (XVECEXP (pattern, 1, i), 0));
06800 tmp = emit_jump_insn_after (tmp, location);
06801 JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 1, i), 0);
06802
06803
06804
06805
06806
06807
06808
06809
06810
06811
06812
06813
06814
06815
06816
06817
06818 PUT_MODE (tmp, SImode);
06819 LABEL_NUSES (JUMP_LABEL (tmp))++;
06820 location = NEXT_INSN (location);
06821 }
06822
06823
06824 emit_barrier_after (location);
06825 location = NEXT_INSN (location);
06826 }
06827
06828
06829 emit_insn_before (gen_end_brtab (), location);
06830 location = NEXT_INSN (location);
06831 emit_barrier_after (location);
06832
06833
06834 delete_insn (insn);
06835 }
06836 }
06837 else
06838 {
06839
06840 insns = get_insns ();
06841 for (insn = insns; insn; insn = NEXT_INSN (insn))
06842 {
06843
06844 if (GET_CODE (insn) != JUMP_INSN
06845 || (GET_CODE (PATTERN (insn)) != ADDR_VEC
06846 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC))
06847 continue;
06848
06849
06850
06851 emit_insn_before (gen_begin_brtab (), insn);
06852 emit_insn_after (gen_end_brtab (), insn);
06853 }
06854 }
06855 }
06856
06857
06858
06859
06860
06861
06862
06863
06864
06865
06866
06867
06868
06869
06870
06871
06872
06873
06874
06875
06876
06877
06878
06879
06880
06881
06882
06883
06884
06885
06886
06887
06888
06889
06890
06891
06892
06893
06894
06895
06896
06897
06898
06899
06900 static void
06901 pa_combine_instructions (insns)
06902 rtx insns ATTRIBUTE_UNUSED;
06903 {
06904 rtx anchor, new;
06905
06906
06907
06908
06909 if (optimize < 2)
06910 return;
06911
06912
06913
06914
06915
06916 new = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, NULL_RTX, NULL_RTX));
06917 new = make_insn_raw (new);
06918
06919 for (anchor = get_insns (); anchor; anchor = NEXT_INSN (anchor))
06920 {
06921 enum attr_pa_combine_type anchor_attr;
06922 enum attr_pa_combine_type floater_attr;
06923
06924
06925
06926 if ((GET_CODE (anchor) != INSN
06927 && GET_CODE (anchor) != JUMP_INSN
06928 && GET_CODE (anchor) != CALL_INSN)
06929 || GET_CODE (PATTERN (anchor)) == USE
06930 || GET_CODE (PATTERN (anchor)) == CLOBBER
06931 || GET_CODE (PATTERN (anchor)) == ADDR_VEC
06932 || GET_CODE (PATTERN (anchor)) == ADDR_DIFF_VEC)
06933 continue;
06934
06935 anchor_attr = get_attr_pa_combine_type (anchor);
06936
06937 if (anchor_attr == PA_COMBINE_TYPE_FMPY
06938 || anchor_attr == PA_COMBINE_TYPE_FADDSUB
06939 || (anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH
06940 && ! forward_branch_p (anchor)))
06941 {
06942 rtx floater;
06943
06944 for (floater = PREV_INSN (anchor);
06945 floater;
06946 floater = PREV_INSN (floater))
06947 {
06948 if (GET_CODE (floater) == NOTE
06949 || (GET_CODE (floater) == INSN
06950 && (GET_CODE (PATTERN (floater)) == USE
06951 || GET_CODE (PATTERN (floater)) == CLOBBER)))
06952 continue;
06953
06954
06955 if (GET_CODE (floater) != INSN
06956 || GET_CODE (PATTERN (floater)) == ADDR_VEC
06957 || GET_CODE (PATTERN (floater)) == ADDR_DIFF_VEC)
06958 {
06959 floater = NULL_RTX;
06960 break;
06961 }
06962
06963
06964
06965 floater_attr = get_attr_pa_combine_type (floater);
06966 if ((anchor_attr == PA_COMBINE_TYPE_FMPY
06967 && floater_attr == PA_COMBINE_TYPE_FADDSUB)
06968 || (anchor_attr == PA_COMBINE_TYPE_FADDSUB
06969 && floater_attr == PA_COMBINE_TYPE_FMPY))
06970 {
06971
06972
06973 if (pa_can_combine_p (new, anchor, floater, 0,
06974 SET_DEST (PATTERN (floater)),
06975 XEXP (SET_SRC (PATTERN (floater)), 0),
06976 XEXP (SET_SRC (PATTERN (floater)), 1)))
06977 break;
06978 }
06979
06980 else if (anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH
06981 && floater_attr == PA_COMBINE_TYPE_ADDMOVE)
06982 {
06983 if (GET_CODE (SET_SRC (PATTERN (floater))) == PLUS)
06984 {
06985 if (pa_can_combine_p (new, anchor, floater, 0,
06986 SET_DEST (PATTERN (floater)),
06987 XEXP (SET_SRC (PATTERN (floater)), 0),
06988 XEXP (SET_SRC (PATTERN (floater)), 1)))
06989 break;
06990 }
06991 else
06992 {
06993 if (pa_can_combine_p (new, anchor, floater, 0,
06994 SET_DEST (PATTERN (floater)),
06995 SET_SRC (PATTERN (floater)),
06996 SET_SRC (PATTERN (floater))))
06997 break;
06998 }
06999 }
07000 }
07001
07002
07003 if (!floater
07004 && (anchor_attr == PA_COMBINE_TYPE_FMPY
07005 || anchor_attr == PA_COMBINE_TYPE_FADDSUB))
07006 {
07007 for (floater = anchor; floater; floater = NEXT_INSN (floater))
07008 {
07009 if (GET_CODE (floater) == NOTE
07010 || (GET_CODE (floater) == INSN
07011 && (GET_CODE (PATTERN (floater)) == USE
07012 || GET_CODE (PATTERN (floater)) == CLOBBER)))
07013
07014 continue;
07015
07016
07017 if (GET_CODE (floater) != INSN
07018 || GET_CODE (PATTERN (floater)) == ADDR_VEC
07019 || GET_CODE (PATTERN (floater)) == ADDR_DIFF_VEC)
07020 {
07021 floater = NULL_RTX;
07022 break;
07023 }
07024
07025
07026
07027 floater_attr = get_attr_pa_combine_type (floater);
07028 if ((anchor_attr == PA_COMBINE_TYPE_FMPY
07029 && floater_attr == PA_COMBINE_TYPE_FADDSUB)
07030 || (anchor_attr == PA_COMBINE_TYPE_FADDSUB
07031 && floater_attr == PA_COMBINE_TYPE_FMPY))
07032 {
07033
07034
07035 if (pa_can_combine_p (new, anchor, floater, 1,
07036 SET_DEST (PATTERN (floater)),
07037 XEXP (SET_SRC (PATTERN (floater)),
07038 0),
07039 XEXP (SET_SRC (PATTERN (floater)),
07040 1)))
07041 break;
07042 }
07043 }
07044 }
07045
07046
07047
07048 if (floater
07049 && (anchor_attr == PA_COMBINE_TYPE_FADDSUB
07050 || anchor_attr == PA_COMBINE_TYPE_FMPY))
07051 {
07052
07053 emit_insn_before (gen_rtx_PARALLEL
07054 (VOIDmode,
07055 gen_rtvec (2, PATTERN (anchor),
07056 PATTERN (floater))),
07057 anchor);
07058
07059 PUT_CODE (anchor, NOTE);
07060 NOTE_LINE_NUMBER (anchor) = NOTE_INSN_DELETED;
07061 NOTE_SOURCE_FILE (anchor) = 0;
07062
07063
07064
07065 emit_insn_before (gen_rtx_USE (VOIDmode, floater), floater);
07066 delete_insn (floater);
07067
07068 continue;
07069 }
07070 else if (floater
07071 && anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH)
07072 {
07073 rtx temp;
07074
07075 temp
07076 = emit_jump_insn_before (gen_rtx_PARALLEL
07077 (VOIDmode,
07078 gen_rtvec (2, PATTERN (anchor),
07079 PATTERN (floater))),
07080 anchor);
07081
07082 JUMP_LABEL (temp) = JUMP_LABEL (anchor);
07083 PUT_CODE (anchor, NOTE);
07084 NOTE_LINE_NUMBER (anchor) = NOTE_INSN_DELETED;
07085 NOTE_SOURCE_FILE (anchor) = 0;
07086
07087
07088
07089 emit_insn_before (gen_rtx_USE (VOIDmode, floater), floater);
07090 delete_insn (floater);
07091 continue;
07092 }
07093 }
07094 }
07095 }
07096
07097 static int
07098 pa_can_combine_p (new, anchor, floater, reversed, dest, src1, src2)
07099 rtx new, anchor, floater;
07100 int reversed;
07101 rtx dest, src1, src2;
07102 {
07103 int insn_code_number;
07104 rtx start, end;
07105
07106
07107
07108
07109
07110
07111
07112
07113 XVECEXP (PATTERN (new), 0, 0) = PATTERN (anchor);
07114 XVECEXP (PATTERN (new), 0, 1) = PATTERN (floater);
07115 INSN_CODE (new) = -1;
07116 insn_code_number = recog_memoized (new);
07117 if (insn_code_number < 0
07118 || (extract_insn (new), ! constrain_operands (1)))
07119 return 0;
07120
07121 if (reversed)
07122 {
07123 start = anchor;
07124 end = floater;
07125 }
07126 else
07127 {
07128 start = floater;
07129 end = anchor;
07130 }
07131
07132
07133
07134
07135
07136
07137
07138
07139 if (reg_used_between_p (dest, start, end))
07140 return 0;
07141
07142 if (reg_set_between_p (src1, start, end))
07143 return 0;
07144
07145 if (reg_set_between_p (src2, start, end))
07146 return 0;
07147
07148
07149 return 1;
07150 }
07151
07152
07153
07154
07155
07156
07157
07158
07159
07160
07161
07162
07163
07164
07165
07166
07167
07168
07169
07170
07171
07172
07173
07174
07175 int
07176 insn_refs_are_delayed (insn)
07177 rtx insn;
07178 {
07179 return ((GET_CODE (insn) == INSN
07180 && GET_CODE (PATTERN (insn)) != SEQUENCE
07181 && GET_CODE (PATTERN (insn)) != USE
07182 && GET_CODE (PATTERN (insn)) != CLOBBER
07183 && get_attr_type (insn) == TYPE_MILLI));
07184 }
07185
07186
07187
07188
07189
07190
07191
07192
07193
07194 rtx
07195 function_arg (cum, mode, type, named, incoming)
07196 CUMULATIVE_ARGS *cum;
07197 enum machine_mode mode;
07198 tree type;
07199 int named ATTRIBUTE_UNUSED;
07200 int incoming;
07201 {
07202 int max_arg_words = (TARGET_64BIT ? 8 : 4);
07203 int fpr_reg_base;
07204 int gpr_reg_base;
07205 rtx retval;
07206
07207 if (! TARGET_64BIT)
07208 {
07209
07210
07211
07212
07213 if (cum->words + FUNCTION_ARG_SIZE (mode, type) > max_arg_words
07214 || mode == VOIDmode)
07215 return NULL_RTX;
07216 }
07217 else
07218 {
07219 int offset = 0;
07220 if (FUNCTION_ARG_SIZE (mode, type) > 1 && (cum->words & 1))
07221 offset = 1;
07222 if (cum->words + offset >= max_arg_words
07223 || mode == VOIDmode)
07224 return NULL_RTX;
07225 }
07226
07227
07228
07229
07230
07231
07232
07233
07234 if (TARGET_64BIT)
07235 {
07236
07237
07238
07239
07240
07241
07242 gpr_reg_base = 26 - cum->words;
07243 fpr_reg_base = 32 + cum->words;
07244
07245
07246
07247 if (FUNCTION_ARG_SIZE (mode, type) > 1)
07248 {
07249 if (mode != BLKmode)
07250 {
07251
07252 gpr_reg_base -= (cum->words & 1);
07253
07254
07255
07256