00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #include "config.h"
00052 #include "system.h"
00053 #include "coretypes.h"
00054 #include "tm.h"
00055
00056 #include "tree.h"
00057 #include "rtl.h"
00058 #include "tm_p.h"
00059 #include "regs.h"
00060 #include "insn-config.h"
00061 #include "insn-attr.h"
00062 #include "recog.h"
00063 #include "conditions.h"
00064 #include "flags.h"
00065 #include "real.h"
00066 #include "hard-reg-set.h"
00067 #include "output.h"
00068 #include "except.h"
00069 #include "function.h"
00070 #include "toplev.h"
00071 #include "reload.h"
00072 #include "intl.h"
00073 #include "basic-block.h"
00074 #include "target.h"
00075 #include "debug.h"
00076 #include "expr.h"
00077 #include "cfglayout.h"
00078 #include "tree-pass.h"
00079 #include "timevar.h"
00080 #include "cgraph.h"
00081 #include "coverage.h"
00082
00083 #ifdef XCOFF_DEBUGGING_INFO
00084 #include "xcoffout.h"
00085
00086 #endif
00087
00088 #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
00089 #include "dwarf2out.h"
00090 #endif
00091
00092 #ifdef DBX_DEBUGGING_INFO
00093 #include "dbxout.h"
00094 #endif
00095
00096 #ifdef SDB_DEBUGGING_INFO
00097 #include "sdbout.h"
00098 #endif
00099
00100
00101
00102 #ifndef CC_STATUS_INIT
00103 #define CC_STATUS_INIT
00104 #endif
00105
00106
00107 #ifndef ASM_COMMENT_START
00108 #define ASM_COMMENT_START ";#"
00109 #endif
00110
00111
00112 #ifndef IS_ASM_LOGICAL_LINE_SEPARATOR
00113 #define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == ';')
00114 #endif
00115
00116 #ifndef JUMP_TABLES_IN_TEXT_SECTION
00117 #define JUMP_TABLES_IN_TEXT_SECTION 0
00118 #endif
00119
00120
00121 #define SEEN_BB 1
00122 #define SEEN_NOTE 2
00123 #define SEEN_EMITTED 4
00124
00125
00126 static rtx debug_insn;
00127 rtx current_output_insn;
00128
00129
00130 static int last_linenum;
00131
00132
00133 static int high_block_linenum;
00134
00135
00136 static int high_function_linenum;
00137
00138
00139 static const char *last_filename;
00140
00141
00142 static bool force_source_line = false;
00143
00144 extern const int length_unit_log;
00145
00146
00147
00148
00149 rtx this_is_asm_operands;
00150
00151
00152 static unsigned int insn_noperands;
00153
00154
00155
00156 static rtx last_ignored_compare = 0;
00157
00158
00159
00160
00161 static int insn_counter = 0;
00162
00163 #ifdef HAVE_cc0
00164
00165
00166
00167
00168 CC_STATUS cc_status;
00169
00170
00171
00172
00173 CC_STATUS cc_prev_status;
00174 #endif
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 char regs_ever_live[FIRST_PSEUDO_REGISTER];
00186
00187
00188
00189
00190
00191 char regs_asm_clobbered[FIRST_PSEUDO_REGISTER];
00192
00193
00194
00195
00196
00197 int frame_pointer_needed;
00198
00199
00200
00201 static int block_depth;
00202
00203
00204
00205 static int app_on;
00206
00207
00208
00209
00210 rtx final_sequence;
00211
00212 #ifdef ASSEMBLER_DIALECT
00213
00214
00215 static int dialect_number;
00216 #endif
00217
00218 #ifdef HAVE_conditional_execution
00219
00220 rtx current_insn_predicate;
00221 #endif
00222
00223 #ifdef HAVE_ATTR_length
00224 static int asm_insn_count (rtx);
00225 #endif
00226 static void profile_function (FILE *);
00227 static void profile_after_prologue (FILE *);
00228 static bool notice_source_line (rtx);
00229 static rtx walk_alter_subreg (rtx *);
00230 static void output_asm_name (void);
00231 static void output_alternate_entry_point (FILE *, rtx);
00232 static tree get_mem_expr_from_op (rtx, int *);
00233 static void output_asm_operand_names (rtx *, int *, int);
00234 static void output_operand (rtx, int);
00235 #ifdef LEAF_REGISTERS
00236 static void leaf_renumber_regs (rtx);
00237 #endif
00238 #ifdef HAVE_cc0
00239 static int alter_cond (rtx);
00240 #endif
00241 #ifndef ADDR_VEC_ALIGN
00242 static int final_addr_vec_align (rtx);
00243 #endif
00244 #ifdef HAVE_ATTR_length
00245 static int align_fuzz (rtx, rtx, int, unsigned);
00246 #endif
00247
00248
00249
00250 void
00251 init_final (const char *filename ATTRIBUTE_UNUSED)
00252 {
00253 app_on = 0;
00254 final_sequence = 0;
00255
00256 #ifdef ASSEMBLER_DIALECT
00257 dialect_number = ASSEMBLER_DIALECT;
00258 #endif
00259 }
00260
00261
00262
00263
00264
00265 void
00266 default_function_pro_epilogue (FILE *file ATTRIBUTE_UNUSED,
00267 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
00268 {
00269 }
00270
00271
00272 void
00273 no_asm_to_stream (FILE *file ATTRIBUTE_UNUSED)
00274 {
00275 }
00276
00277
00278
00279
00280 void
00281 app_enable (void)
00282 {
00283 if (! app_on)
00284 {
00285 fputs (ASM_APP_ON, asm_out_file);
00286 app_on = 1;
00287 }
00288 }
00289
00290
00291
00292
00293 void
00294 app_disable (void)
00295 {
00296 if (app_on)
00297 {
00298 fputs (ASM_APP_OFF, asm_out_file);
00299 app_on = 0;
00300 }
00301 }
00302
00303
00304
00305
00306
00307 #ifdef DELAY_SLOTS
00308 int
00309 dbr_sequence_length (void)
00310 {
00311 if (final_sequence != 0)
00312 return XVECLEN (final_sequence, 0) - 1;
00313 else
00314 return 0;
00315 }
00316 #endif
00317
00318
00319
00320
00321
00322
00323
00324 static int *insn_lengths;
00325
00326 varray_type insn_addresses_;
00327
00328
00329 static int insn_lengths_max_uid;
00330
00331
00332 int insn_current_address;
00333
00334
00335 int insn_last_address;
00336
00337
00338 int insn_current_align;
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 struct label_alignment
00350 {
00351 short alignment;
00352 short max_skip;
00353 };
00354
00355 static rtx *uid_align;
00356 static int *uid_shuid;
00357 static struct label_alignment *label_align;
00358
00359
00360
00361 void
00362 init_insn_lengths (void)
00363 {
00364 if (uid_shuid)
00365 {
00366 free (uid_shuid);
00367 uid_shuid = 0;
00368 }
00369 if (insn_lengths)
00370 {
00371 free (insn_lengths);
00372 insn_lengths = 0;
00373 insn_lengths_max_uid = 0;
00374 }
00375 #ifdef HAVE_ATTR_length
00376 INSN_ADDRESSES_FREE ();
00377 #endif
00378 if (uid_align)
00379 {
00380 free (uid_align);
00381 uid_align = 0;
00382 }
00383 }
00384
00385
00386
00387
00388 static inline int
00389 get_attr_length_1 (rtx insn ATTRIBUTE_UNUSED,
00390 int (*fallback_fn) (rtx) ATTRIBUTE_UNUSED)
00391 {
00392 #ifdef HAVE_ATTR_length
00393 rtx body;
00394 int i;
00395 int length = 0;
00396
00397 if (insn_lengths_max_uid > INSN_UID (insn))
00398 return insn_lengths[INSN_UID (insn)];
00399 else
00400 switch (GET_CODE (insn))
00401 {
00402 case NOTE:
00403 case BARRIER:
00404 case CODE_LABEL:
00405 return 0;
00406
00407 case CALL_INSN:
00408 length = fallback_fn (insn);
00409 break;
00410
00411 case JUMP_INSN:
00412 body = PATTERN (insn);
00413 if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
00414 {
00415
00416
00417 }
00418 else
00419 length = fallback_fn (insn);
00420 break;
00421
00422 case INSN:
00423 body = PATTERN (insn);
00424 if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER)
00425 return 0;
00426
00427 else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
00428 length = asm_insn_count (body) * fallback_fn (insn);
00429 else if (GET_CODE (body) == SEQUENCE)
00430 for (i = 0; i < XVECLEN (body, 0); i++)
00431 length += get_attr_length (XVECEXP (body, 0, i));
00432 else
00433 length = fallback_fn (insn);
00434 break;
00435
00436 default:
00437 break;
00438 }
00439
00440 #ifdef ADJUST_INSN_LENGTH
00441 ADJUST_INSN_LENGTH (insn, length);
00442 #endif
00443 return length;
00444 #else
00445 return 0;
00446 #define insn_default_length 0
00447 #define insn_min_length 0
00448 #endif
00449 }
00450
00451
00452
00453 int
00454 get_attr_length (rtx insn)
00455 {
00456 return get_attr_length_1 (insn, insn_default_length);
00457 }
00458
00459
00460
00461 int
00462 get_attr_min_length (rtx insn)
00463 {
00464 return get_attr_length_1 (insn, insn_min_length);
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 #ifndef LABEL_ALIGN
00509 #define LABEL_ALIGN(LABEL) align_labels_log
00510 #endif
00511
00512 #ifndef LABEL_ALIGN_MAX_SKIP
00513 #define LABEL_ALIGN_MAX_SKIP align_labels_max_skip
00514 #endif
00515
00516 #ifndef LOOP_ALIGN
00517 #define LOOP_ALIGN(LABEL) align_loops_log
00518 #endif
00519
00520 #ifndef LOOP_ALIGN_MAX_SKIP
00521 #define LOOP_ALIGN_MAX_SKIP align_loops_max_skip
00522 #endif
00523
00524 #ifndef LABEL_ALIGN_AFTER_BARRIER
00525 #define LABEL_ALIGN_AFTER_BARRIER(LABEL) 0
00526 #endif
00527
00528 #ifndef LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
00529 #define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP 0
00530 #endif
00531
00532 #ifndef JUMP_ALIGN
00533 #define JUMP_ALIGN(LABEL) align_jumps_log
00534 #endif
00535
00536 #ifndef JUMP_ALIGN_MAX_SKIP
00537 #define JUMP_ALIGN_MAX_SKIP align_jumps_max_skip
00538 #endif
00539
00540 #ifndef ADDR_VEC_ALIGN
00541 static int
00542 final_addr_vec_align (rtx addr_vec)
00543 {
00544 int align = GET_MODE_SIZE (GET_MODE (PATTERN (addr_vec)));
00545
00546 if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
00547 align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
00548 return exact_log2 (align);
00549
00550 }
00551
00552 #define ADDR_VEC_ALIGN(ADDR_VEC) final_addr_vec_align (ADDR_VEC)
00553 #endif
00554
00555 #ifndef INSN_LENGTH_ALIGNMENT
00556 #define INSN_LENGTH_ALIGNMENT(INSN) length_unit_log
00557 #endif
00558
00559 #define INSN_SHUID(INSN) (uid_shuid[INSN_UID (INSN)])
00560
00561 static int min_labelno, max_labelno;
00562
00563 #define LABEL_TO_ALIGNMENT(LABEL) \
00564 (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].alignment)
00565
00566 #define LABEL_TO_MAX_SKIP(LABEL) \
00567 (label_align[CODE_LABEL_NUMBER (LABEL) - min_labelno].max_skip)
00568
00569
00570
00571 int
00572 label_to_alignment (rtx label)
00573 {
00574 return LABEL_TO_ALIGNMENT (label);
00575 }
00576
00577 #ifdef HAVE_ATTR_length
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606 static int
00607 align_fuzz (rtx start, rtx end, int known_align_log, unsigned int growth)
00608 {
00609 int uid = INSN_UID (start);
00610 rtx align_label;
00611 int known_align = 1 << known_align_log;
00612 int end_shuid = INSN_SHUID (end);
00613 int fuzz = 0;
00614
00615 for (align_label = uid_align[uid]; align_label; align_label = uid_align[uid])
00616 {
00617 int align_addr, new_align;
00618
00619 uid = INSN_UID (align_label);
00620 align_addr = INSN_ADDRESSES (uid) - insn_lengths[uid];
00621 if (uid_shuid[uid] > end_shuid)
00622 break;
00623 known_align_log = LABEL_TO_ALIGNMENT (align_label);
00624 new_align = 1 << known_align_log;
00625 if (new_align < known_align)
00626 continue;
00627 fuzz += (-align_addr ^ growth) & (new_align - known_align);
00628 known_align = new_align;
00629 }
00630 return fuzz;
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 int
00646 insn_current_reference_address (rtx branch)
00647 {
00648 rtx dest, seq;
00649 int seq_uid;
00650
00651 if (! INSN_ADDRESSES_SET_P ())
00652 return 0;
00653
00654 seq = NEXT_INSN (PREV_INSN (branch));
00655 seq_uid = INSN_UID (seq);
00656 if (!JUMP_P (branch))
00657
00658
00659
00660
00661
00662 return insn_current_address;
00663 dest = JUMP_LABEL (branch);
00664
00665
00666
00667 if (INSN_SHUID (seq) < INSN_SHUID (dest))
00668 {
00669
00670 return (insn_last_address + insn_lengths[seq_uid]
00671 - align_fuzz (seq, dest, length_unit_log, ~0));
00672 }
00673 else
00674 {
00675
00676 return (insn_current_address
00677 + align_fuzz (dest, seq, length_unit_log, ~0));
00678 }
00679 }
00680 #endif
00681
00682
00683
00684
00685 static unsigned int
00686 compute_alignments (void)
00687 {
00688 int log, max_skip, max_log;
00689 basic_block bb;
00690
00691 if (label_align)
00692 {
00693 free (label_align);
00694 label_align = 0;
00695 }
00696
00697 max_labelno = max_label_num ();
00698 min_labelno = get_first_label_num ();
00699 label_align = XCNEWVEC (struct label_alignment, max_labelno - min_labelno + 1);
00700
00701
00702 if (! optimize || optimize_size)
00703 return 0;
00704
00705 FOR_EACH_BB (bb)
00706 {
00707 rtx label = BB_HEAD (bb);
00708 int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0;
00709 edge e;
00710 edge_iterator ei;
00711
00712 if (!LABEL_P (label)
00713 || probably_never_executed_bb_p (bb))
00714 continue;
00715 max_log = LABEL_ALIGN (label);
00716 max_skip = LABEL_ALIGN_MAX_SKIP;
00717
00718 FOR_EACH_EDGE (e, ei, bb->preds)
00719 {
00720 if (e->flags & EDGE_FALLTHRU)
00721 has_fallthru = 1, fallthru_frequency += EDGE_FREQUENCY (e);
00722 else
00723 branch_frequency += EDGE_FREQUENCY (e);
00724 }
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 if (!has_fallthru
00737 && (branch_frequency > BB_FREQ_MAX / 10
00738 || (bb->frequency > bb->prev_bb->frequency * 10
00739 && (bb->prev_bb->frequency
00740 <= ENTRY_BLOCK_PTR->frequency / 2))))
00741 {
00742 log = JUMP_ALIGN (label);
00743 if (max_log < log)
00744 {
00745 max_log = log;
00746 max_skip = JUMP_ALIGN_MAX_SKIP;
00747 }
00748 }
00749
00750
00751 if (has_fallthru
00752 && maybe_hot_bb_p (bb)
00753 && branch_frequency + fallthru_frequency > BB_FREQ_MAX / 10
00754 && branch_frequency > fallthru_frequency * 2)
00755 {
00756 log = LOOP_ALIGN (label);
00757 if (max_log < log)
00758 {
00759 max_log = log;
00760 max_skip = LOOP_ALIGN_MAX_SKIP;
00761 }
00762 }
00763 LABEL_TO_ALIGNMENT (label) = max_log;
00764 LABEL_TO_MAX_SKIP (label) = max_skip;
00765 }
00766 return 0;
00767 }
00768
00769 struct tree_opt_pass pass_compute_alignments =
00770 {
00771 NULL,
00772 NULL,
00773 compute_alignments,
00774 NULL,
00775 NULL,
00776 0,
00777 0,
00778 0,
00779 0,
00780 0,
00781 0,
00782 0,
00783 0
00784 };
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 void
00799 shorten_branches (rtx first ATTRIBUTE_UNUSED)
00800 {
00801 rtx insn;
00802 int max_uid;
00803 int i;
00804 int max_log;
00805 int max_skip;
00806 #ifdef HAVE_ATTR_length
00807 #define MAX_CODE_ALIGN 16
00808 rtx seq;
00809 int something_changed = 1;
00810 char *varying_length;
00811 rtx body;
00812 int uid;
00813 rtx align_tab[MAX_CODE_ALIGN];
00814
00815 #endif
00816
00817
00818 max_uid = get_max_uid ();
00819
00820
00821 free (uid_shuid);
00822
00823 uid_shuid = XNEWVEC (int, max_uid);
00824
00825 if (max_labelno != max_label_num ())
00826 {
00827 int old = max_labelno;
00828 int n_labels;
00829 int n_old_labels;
00830
00831 max_labelno = max_label_num ();
00832
00833 n_labels = max_labelno - min_labelno + 1;
00834 n_old_labels = old - min_labelno + 1;
00835
00836 label_align = xrealloc (label_align,
00837 n_labels * sizeof (struct label_alignment));
00838
00839
00840
00841 gcc_assert (n_old_labels <= n_labels);
00842
00843 memset (label_align + n_old_labels, 0,
00844 (n_labels - n_old_labels) * sizeof (struct label_alignment));
00845 }
00846
00847
00848
00849
00850
00851
00852
00853 max_log = 0;
00854 max_skip = 0;
00855
00856 for (insn = get_insns (), i = 1; insn; insn = NEXT_INSN (insn))
00857 {
00858 int log;
00859
00860 INSN_SHUID (insn) = i++;
00861 if (INSN_P (insn))
00862 continue;
00863
00864 if (LABEL_P (insn))
00865 {
00866 rtx next;
00867
00868
00869 log = LABEL_TO_ALIGNMENT (insn);
00870 if (max_log < log)
00871 {
00872 max_log = log;
00873 max_skip = LABEL_TO_MAX_SKIP (insn);
00874 }
00875
00876 log = LABEL_ALIGN (insn);
00877 if (max_log < log)
00878 {
00879 max_log = log;
00880 max_skip = LABEL_ALIGN_MAX_SKIP;
00881 }
00882 next = next_nonnote_insn (insn);
00883
00884
00885 if (JUMP_TABLES_IN_TEXT_SECTION
00886 || readonly_data_section == text_section)
00887 if (next && JUMP_P (next))
00888 {
00889 rtx nextbody = PATTERN (next);
00890 if (GET_CODE (nextbody) == ADDR_VEC
00891 || GET_CODE (nextbody) == ADDR_DIFF_VEC)
00892 {
00893 log = ADDR_VEC_ALIGN (next);
00894 if (max_log < log)
00895 {
00896 max_log = log;
00897 max_skip = LABEL_ALIGN_MAX_SKIP;
00898 }
00899 }
00900 }
00901 LABEL_TO_ALIGNMENT (insn) = max_log;
00902 LABEL_TO_MAX_SKIP (insn) = max_skip;
00903 max_log = 0;
00904 max_skip = 0;
00905 }
00906 else if (BARRIER_P (insn))
00907 {
00908 rtx label;
00909
00910 for (label = insn; label && ! INSN_P (label);
00911 label = NEXT_INSN (label))
00912 if (LABEL_P (label))
00913 {
00914 log = LABEL_ALIGN_AFTER_BARRIER (insn);
00915 if (max_log < log)
00916 {
00917 max_log = log;
00918 max_skip = LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP;
00919 }
00920 break;
00921 }
00922 }
00923 }
00924 #ifdef HAVE_ATTR_length
00925
00926
00927 insn_lengths = XNEWVEC (int, max_uid);
00928 insn_lengths_max_uid = max_uid;
00929
00930
00931 INSN_ADDRESSES_ALLOC (max_uid);
00932
00933 varying_length = XCNEWVEC (char, max_uid);
00934
00935
00936
00937
00938
00939
00940 uid_align = XCNEWVEC (rtx, max_uid);
00941
00942 for (i = MAX_CODE_ALIGN; --i >= 0;)
00943 align_tab[i] = NULL_RTX;
00944 seq = get_last_insn ();
00945 for (; seq; seq = PREV_INSN (seq))
00946 {
00947 int uid = INSN_UID (seq);
00948 int log;
00949 log = (LABEL_P (seq) ? LABEL_TO_ALIGNMENT (seq) : 0);
00950 uid_align[uid] = align_tab[0];
00951 if (log)
00952 {
00953
00954 uid_align[uid] = align_tab[log];
00955 for (i = log - 1; i >= 0; i--)
00956 align_tab[i] = seq;
00957 }
00958 }
00959 #ifdef CASE_VECTOR_SHORTEN_MODE
00960 if (optimize)
00961 {
00962
00963
00964
00965 int min_shuid = INSN_SHUID (get_insns ()) - 1;
00966 int max_shuid = INSN_SHUID (get_last_insn ()) + 1;
00967 int rel;
00968
00969 for (insn = first; insn != 0; insn = NEXT_INSN (insn))
00970 {
00971 rtx min_lab = NULL_RTX, max_lab = NULL_RTX, pat;
00972 int len, i, min, max, insn_shuid;
00973 int min_align;
00974 addr_diff_vec_flags flags;
00975
00976 if (!JUMP_P (insn)
00977 || GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
00978 continue;
00979 pat = PATTERN (insn);
00980 len = XVECLEN (pat, 1);
00981 gcc_assert (len > 0);
00982 min_align = MAX_CODE_ALIGN;
00983 for (min = max_shuid, max = min_shuid, i = len - 1; i >= 0; i--)
00984 {
00985 rtx lab = XEXP (XVECEXP (pat, 1, i), 0);
00986 int shuid = INSN_SHUID (lab);
00987 if (shuid < min)
00988 {
00989 min = shuid;
00990 min_lab = lab;
00991 }
00992 if (shuid > max)
00993 {
00994 max = shuid;
00995 max_lab = lab;
00996 }
00997 if (min_align > LABEL_TO_ALIGNMENT (lab))
00998 min_align = LABEL_TO_ALIGNMENT (lab);
00999 }
01000 XEXP (pat, 2) = gen_rtx_LABEL_REF (Pmode, min_lab);
01001 XEXP (pat, 3) = gen_rtx_LABEL_REF (Pmode, max_lab);
01002 insn_shuid = INSN_SHUID (insn);
01003 rel = INSN_SHUID (XEXP (XEXP (pat, 0), 0));
01004 memset (&flags, 0, sizeof (flags));
01005 flags.min_align = min_align;
01006 flags.base_after_vec = rel > insn_shuid;
01007 flags.min_after_vec = min > insn_shuid;
01008 flags.max_after_vec = max > insn_shuid;
01009 flags.min_after_base = min > rel;
01010 flags.max_after_base = max > rel;
01011 ADDR_DIFF_VEC_FLAGS (pat) = flags;
01012 }
01013 }
01014 #endif
01015
01016
01017 for (insn_current_address = 0, insn = first;
01018 insn != 0;
01019 insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))
01020 {
01021 uid = INSN_UID (insn);
01022
01023 insn_lengths[uid] = 0;
01024
01025 if (LABEL_P (insn))
01026 {
01027 int log = LABEL_TO_ALIGNMENT (insn);
01028 if (log)
01029 {
01030 int align = 1 << log;
01031 int new_address = (insn_current_address + align - 1) & -align;
01032 insn_lengths[uid] = new_address - insn_current_address;
01033 }
01034 }
01035
01036 INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid];
01037
01038 if (NOTE_P (insn) || BARRIER_P (insn)
01039 || LABEL_P (insn))
01040 continue;
01041 if (INSN_DELETED_P (insn))
01042 continue;
01043
01044 body = PATTERN (insn);
01045 if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
01046 {
01047
01048
01049 if (JUMP_TABLES_IN_TEXT_SECTION
01050 || readonly_data_section == text_section)
01051 insn_lengths[uid] = (XVECLEN (body,
01052 GET_CODE (body) == ADDR_DIFF_VEC)
01053 * GET_MODE_SIZE (GET_MODE (body)));
01054
01055 }
01056 else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
01057 insn_lengths[uid] = asm_insn_count (body) * insn_default_length (insn);
01058 else if (GET_CODE (body) == SEQUENCE)
01059 {
01060 int i;
01061 int const_delay_slots;
01062 #ifdef DELAY_SLOTS
01063 const_delay_slots = const_num_delay_slots (XVECEXP (body, 0, 0));
01064 #else
01065 const_delay_slots = 0;
01066 #endif
01067
01068
01069
01070 for (i = 0; i < XVECLEN (body, 0); i++)
01071 {
01072 rtx inner_insn = XVECEXP (body, 0, i);
01073 int inner_uid = INSN_UID (inner_insn);
01074 int inner_length;
01075
01076 if (GET_CODE (body) == ASM_INPUT
01077 || asm_noperands (PATTERN (XVECEXP (body, 0, i))) >= 0)
01078 inner_length = (asm_insn_count (PATTERN (inner_insn))
01079 * insn_default_length (inner_insn));
01080 else
01081 inner_length = insn_default_length (inner_insn);
01082
01083 insn_lengths[inner_uid] = inner_length;
01084 if (const_delay_slots)
01085 {
01086 if ((varying_length[inner_uid]
01087 = insn_variable_length_p (inner_insn)) != 0)
01088 varying_length[uid] = 1;
01089 INSN_ADDRESSES (inner_uid) = (insn_current_address
01090 + insn_lengths[uid]);
01091 }
01092 else
01093 varying_length[inner_uid] = 0;
01094 insn_lengths[uid] += inner_length;
01095 }
01096 }
01097 else if (GET_CODE (body) != USE && GET_CODE (body) != CLOBBER)
01098 {
01099 insn_lengths[uid] = insn_default_length (insn);
01100 varying_length[uid] = insn_variable_length_p (insn);
01101 }
01102
01103
01104 #ifdef ADJUST_INSN_LENGTH
01105 ADJUST_INSN_LENGTH (insn, insn_lengths[uid]);
01106 if (insn_lengths[uid] < 0)
01107 fatal_insn ("negative insn length", insn);
01108 #endif
01109 }
01110
01111
01112
01113
01114
01115 while (something_changed)
01116 {
01117 something_changed = 0;
01118 insn_current_align = MAX_CODE_ALIGN - 1;
01119 for (insn_current_address = 0, insn = first;
01120 insn != 0;
01121 insn = NEXT_INSN (insn))
01122 {
01123 int new_length;
01124 #ifdef ADJUST_INSN_LENGTH
01125 int tmp_length;
01126 #endif
01127 int length_align;
01128
01129 uid = INSN_UID (insn);
01130
01131 if (LABEL_P (insn))
01132 {
01133 int log = LABEL_TO_ALIGNMENT (insn);
01134 if (log > insn_current_align)
01135 {
01136 int align = 1 << log;
01137 int new_address= (insn_current_address + align - 1) & -align;
01138 insn_lengths[uid] = new_address - insn_current_address;
01139 insn_current_align = log;
01140 insn_current_address = new_address;
01141 }
01142 else
01143 insn_lengths[uid] = 0;
01144 INSN_ADDRESSES (uid) = insn_current_address;
01145 continue;
01146 }
01147
01148 length_align = INSN_LENGTH_ALIGNMENT (insn);
01149 if (length_align < insn_current_align)
01150 insn_current_align = length_align;
01151
01152 insn_last_address = INSN_ADDRESSES (uid);
01153 INSN_ADDRESSES (uid) = insn_current_address;
01154
01155 #ifdef CASE_VECTOR_SHORTEN_MODE
01156 if (optimize && JUMP_P (insn)
01157 && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
01158 {
01159 rtx body = PATTERN (insn);
01160 int old_length = insn_lengths[uid];
01161 rtx rel_lab = XEXP (XEXP (body, 0), 0);
01162 rtx min_lab = XEXP (XEXP (body, 2), 0);
01163 rtx max_lab = XEXP (XEXP (body, 3), 0);
01164 int rel_addr = INSN_ADDRESSES (INSN_UID (rel_lab));
01165 int min_addr = INSN_ADDRESSES (INSN_UID (min_lab));
01166 int max_addr = INSN_ADDRESSES (INSN_UID (max_lab));
01167 rtx prev;
01168 int rel_align = 0;
01169 addr_diff_vec_flags flags;
01170
01171
01172 flags = ADDR_DIFF_VEC_FLAGS (body);
01173
01174
01175 for (prev = rel_lab;
01176 prev
01177 && ! insn_lengths[INSN_UID (prev)]
01178 && ! (varying_length[INSN_UID (prev)] & 1);
01179 prev = PREV_INSN (prev))
01180 if (varying_length[INSN_UID (prev)] & 2)
01181 {
01182 rel_align = LABEL_TO_ALIGNMENT (prev);
01183 break;
01184 }
01185
01186
01187
01188
01189
01190
01191 if (flags.base_after_vec)
01192 rel_addr += insn_current_address - insn_last_address;
01193 if (flags.min_after_vec)
01194 min_addr += insn_current_address - insn_last_address;
01195 if (flags.max_after_vec)
01196 max_addr += insn_current_address - insn_last_address;
01197
01198
01199
01200
01201
01202 if (flags.min_after_base)
01203 {
01204
01205
01206
01207
01208 if (! flags.base_after_vec && flags.min_after_vec)
01209 {
01210 min_addr -= align_fuzz (rel_lab, insn, rel_align, 0);
01211 min_addr -= align_fuzz (insn, min_lab, 0, 0);
01212 }
01213 else
01214 min_addr -= align_fuzz (rel_lab, min_lab, rel_align, 0);
01215 }
01216 else
01217 {
01218 if (flags.base_after_vec && ! flags.min_after_vec)
01219 {
01220 min_addr -= align_fuzz (min_lab, insn, 0, ~0);
01221 min_addr -= align_fuzz (insn, rel_lab, 0, ~0);
01222 }
01223 else
01224 min_addr -= align_fuzz (min_lab, rel_lab, 0, ~0);
01225 }
01226
01227
01228 if (flags.max_after_base)
01229 {
01230 if (! flags.base_after_vec && flags.max_after_vec)
01231 {
01232 max_addr += align_fuzz (rel_lab, insn, rel_align, ~0);
01233 max_addr += align_fuzz (insn, max_lab, 0, ~0);
01234 }
01235 else
01236 max_addr += align_fuzz (rel_lab, max_lab, rel_align, ~0);
01237 }
01238 else
01239 {
01240 if (flags.base_after_vec && ! flags.max_after_vec)
01241 {
01242 max_addr += align_fuzz (max_lab, insn, 0, 0);
01243 max_addr += align_fuzz (insn, rel_lab, 0, 0);
01244 }
01245 else
01246 max_addr += align_fuzz (max_lab, rel_lab, 0, 0);
01247 }
01248 PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
01249 max_addr - rel_addr,
01250 body));
01251 if (JUMP_TABLES_IN_TEXT_SECTION
01252 || readonly_data_section == text_section)
01253 {
01254 insn_lengths[uid]
01255 = (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body)));
01256 insn_current_address += insn_lengths[uid];
01257 if (insn_lengths[uid] != old_length)
01258 something_changed = 1;
01259 }
01260
01261 continue;
01262 }
01263 #endif
01264
01265 if (! (varying_length[uid]))
01266 {
01267 if (NONJUMP_INSN_P (insn)
01268 && GET_CODE (PATTERN (insn)) == SEQUENCE)
01269 {
01270 int i;
01271
01272 body = PATTERN (insn);
01273 for (i = 0; i < XVECLEN (body, 0); i++)
01274 {
01275 rtx inner_insn = XVECEXP (body, 0, i);
01276 int inner_uid = INSN_UID (inner_insn);
01277
01278 INSN_ADDRESSES (inner_uid) = insn_current_address;
01279
01280 insn_current_address += insn_lengths[inner_uid];
01281 }
01282 }
01283 else
01284 insn_current_address += insn_lengths[uid];
01285
01286 continue;
01287 }
01288
01289 if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
01290 {
01291 int i;
01292
01293 body = PATTERN (insn);
01294 new_length = 0;
01295 for (i = 0; i < XVECLEN (body, 0); i++)
01296 {
01297 rtx inner_insn = XVECEXP (body, 0, i);
01298 int inner_uid = INSN_UID (inner_insn);
01299 int inner_length;
01300
01301 INSN_ADDRESSES (inner_uid) = insn_current_address;
01302
01303
01304
01305 if (! varying_length[inner_uid])
01306 inner_length = insn_lengths[inner_uid];
01307 else
01308 inner_length = insn_current_length (inner_insn);
01309
01310 if (inner_length != insn_lengths[inner_uid])
01311 {
01312 insn_lengths[inner_uid] = inner_length;
01313 something_changed = 1;
01314 }
01315 insn_current_address += insn_lengths[inner_uid];
01316 new_length += inner_length;
01317 }
01318 }
01319 else
01320 {
01321 new_length = insn_current_length (insn);
01322 insn_current_address += new_length;
01323 }
01324
01325 #ifdef ADJUST_INSN_LENGTH
01326
01327 tmp_length = new_length;
01328 ADJUST_INSN_LENGTH (insn, new_length);
01329 insn_current_address += (new_length - tmp_length);
01330 #endif
01331
01332 if (new_length != insn_lengths[uid])
01333 {
01334 insn_lengths[uid] = new_length;
01335 something_changed = 1;
01336 }
01337 }
01338
01339 if (!optimize)
01340 break;
01341 }
01342
01343 free (varying_length);
01344
01345 #endif
01346 }
01347
01348 #ifdef HAVE_ATTR_length
01349
01350
01351
01352
01353 static int
01354 asm_insn_count (rtx body)
01355 {
01356 const char *template;
01357 int count = 1;
01358
01359 if (GET_CODE (body) == ASM_INPUT)
01360 template = XSTR (body, 0);
01361 else
01362 template = decode_asm_operands (body, NULL, NULL, NULL, NULL);
01363
01364 for (; *template; template++)
01365 if (IS_ASM_LOGICAL_LINE_SEPARATOR (*template) || *template == '\n')
01366 count++;
01367
01368 return count;
01369 }
01370 #endif
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382 void
01383 final_start_function (rtx first ATTRIBUTE_UNUSED, FILE *file,
01384 int optimize ATTRIBUTE_UNUSED)
01385 {
01386 block_depth = 0;
01387
01388 this_is_asm_operands = 0;
01389
01390 last_filename = locator_file (prologue_locator);
01391 last_linenum = locator_line (prologue_locator);
01392
01393 high_block_linenum = high_function_linenum = last_linenum;
01394
01395 (*debug_hooks->begin_prologue) (last_linenum, last_filename);
01396
01397 #if defined (DWARF2_UNWIND_INFO) || defined (TARGET_UNWIND_INFO)
01398 if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG)
01399 dwarf2out_begin_prologue (0, NULL);
01400 #endif
01401
01402 #ifdef LEAF_REG_REMAP
01403 if (current_function_uses_only_leaf_regs)
01404 leaf_renumber_regs (first);
01405 #endif
01406
01407
01408
01409 #ifdef PROFILE_BEFORE_PROLOGUE
01410 if (current_function_profile)
01411 profile_function (file);
01412 #endif
01413
01414 #if defined (DWARF2_UNWIND_INFO) && defined (HAVE_prologue)
01415 if (dwarf2out_do_frame ())
01416 dwarf2out_frame_debug (NULL_RTX, false);
01417 #endif
01418
01419
01420
01421 if (write_symbols)
01422 {
01423 reemit_insn_block_notes ();
01424 number_blocks (current_function_decl);
01425
01426
01427
01428 TREE_ASM_WRITTEN (DECL_INITIAL (current_function_decl)) = 1;
01429 }
01430
01431
01432 targetm.asm_out.function_prologue (file, get_frame_size ());
01433
01434
01435
01436 #ifdef HAVE_prologue
01437 if (! HAVE_prologue)
01438 #endif
01439 profile_after_prologue (file);
01440 }
01441
01442 static void
01443 profile_after_prologue (FILE *file ATTRIBUTE_UNUSED)
01444 {
01445 #ifndef PROFILE_BEFORE_PROLOGUE
01446 if (current_function_profile)
01447 profile_function (file);
01448 #endif
01449 }
01450
01451 static void
01452 profile_function (FILE *file ATTRIBUTE_UNUSED)
01453 {
01454 #ifndef NO_PROFILE_COUNTERS
01455 # define NO_PROFILE_COUNTERS 0
01456 #endif
01457 #if defined(ASM_OUTPUT_REG_PUSH)
01458 int sval = current_function_returns_struct;
01459 rtx svrtx = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl), 1);
01460 #if defined(STATIC_CHAIN_INCOMING_REGNUM) || defined(STATIC_CHAIN_REGNUM)
01461 int cxt = cfun->static_chain_decl != NULL;
01462 #endif
01463 #endif
01464
01465 if (! NO_PROFILE_COUNTERS)
01466 {
01467 int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
01468 switch_to_section (data_section);
01469 ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
01470 targetm.asm_out.internal_label (file, "LP", current_function_funcdef_no);
01471 assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
01472 }
01473
01474 switch_to_section (current_function_section ());
01475
01476 #if defined(ASM_OUTPUT_REG_PUSH)
01477 if (sval && svrtx != NULL_RTX && REG_P (svrtx))
01478 ASM_OUTPUT_REG_PUSH (file, REGNO (svrtx));
01479 #endif
01480
01481 #if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
01482 if (cxt)
01483 ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM);
01484 #else
01485 #if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
01486 if (cxt)
01487 {
01488 ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM);
01489 }
01490 #endif
01491 #endif
01492
01493 FUNCTION_PROFILER (file, current_function_funcdef_no);
01494
01495 #if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
01496 if (cxt)
01497 ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM);
01498 #else
01499 #if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
01500 if (cxt)
01501 {
01502 ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM);
01503 }
01504 #endif
01505 #endif
01506
01507 #if defined(ASM_OUTPUT_REG_PUSH)
01508 if (sval && svrtx != NULL_RTX && REG_P (svrtx))
01509 ASM_OUTPUT_REG_POP (file, REGNO (svrtx));
01510 #endif
01511 }
01512
01513
01514
01515
01516
01517 void
01518 final_end_function (void)
01519 {
01520 app_disable ();
01521
01522 (*debug_hooks->end_function) (high_function_linenum);
01523
01524
01525
01526 targetm.asm_out.function_epilogue (asm_out_file, get_frame_size ());
01527
01528
01529 (*debug_hooks->end_epilogue) (last_linenum, last_filename);
01530
01531 #if defined (DWARF2_UNWIND_INFO)
01532 if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG
01533 && dwarf2out_do_frame ())
01534 dwarf2out_end_epilogue (last_linenum, last_filename);
01535 #endif
01536 }
01537
01538
01539
01540
01541 void
01542 final (rtx first, FILE *file, int optimize)
01543 {
01544 rtx insn;
01545 int max_uid = 0;
01546 int seen = 0;
01547
01548 last_ignored_compare = 0;
01549
01550 #ifdef SDB_DEBUGGING_INFO
01551
01552
01553
01554 if (write_symbols == SDB_DEBUG)
01555 {
01556 rtx last = 0;
01557 for (insn = first; insn; insn = NEXT_INSN (insn))
01558 if (NOTE_P (insn) && NOTE_LINE_NUMBER (insn) > 0)
01559 {
01560 if (last != 0
01561 #ifdef USE_MAPPED_LOCATION
01562 && NOTE_SOURCE_LOCATION (insn) == NOTE_SOURCE_LOCATION (last)
01563 #else
01564 && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last)
01565 && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last)
01566 #endif
01567 )
01568 {
01569 delete_insn (insn);
01570 continue;
01571 }
01572 last = insn;
01573 }
01574 }
01575 #endif
01576
01577 for (insn = first; insn; insn = NEXT_INSN (insn))
01578 {
01579 if (INSN_UID (insn) > max_uid)
01580 max_uid = INSN_UID (insn);
01581 #ifdef HAVE_cc0
01582
01583
01584 if (optimize && JUMP_P (insn))
01585 {
01586 rtx lab = JUMP_LABEL (insn);
01587 if (lab && LABEL_NUSES (lab) == 1)
01588 {
01589 LABEL_REFS (lab) = insn;
01590 }
01591 }
01592 #endif
01593 }
01594
01595 init_recog ();
01596
01597 CC_STATUS_INIT;
01598
01599
01600 for (insn = NEXT_INSN (first); insn;)
01601 {
01602 #ifdef HAVE_ATTR_length
01603 if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ())
01604 {
01605
01606
01607 gcc_assert (NOTE_P (insn));
01608 insn_current_address = -1;
01609 }
01610 else
01611 insn_current_address = INSN_ADDRESSES (INSN_UID (insn));
01612 #endif
01613
01614 insn = final_scan_insn (insn, file, optimize, 0, &seen);
01615 }
01616 }
01617
01618 const char *
01619 get_insn_template (int code, rtx insn)
01620 {
01621 switch (insn_data[code].output_format)
01622 {
01623 case INSN_OUTPUT_FORMAT_SINGLE:
01624 return insn_data[code].output.single;
01625 case INSN_OUTPUT_FORMAT_MULTI:
01626 return insn_data[code].output.multi[which_alternative];
01627 case INSN_OUTPUT_FORMAT_FUNCTION:
01628 gcc_assert (insn);
01629 return (*insn_data[code].output.function) (recog_data.operand, insn);
01630
01631 default:
01632 gcc_unreachable ();
01633 }
01634 }
01635
01636
01637
01638
01639
01640
01641 static void
01642 output_alternate_entry_point (FILE *file, rtx insn)
01643 {
01644 const char *name = LABEL_NAME (insn);
01645
01646 switch (LABEL_KIND (insn))
01647 {
01648 case LABEL_WEAK_ENTRY:
01649 #ifdef ASM_WEAKEN_LABEL
01650 ASM_WEAKEN_LABEL (file, name);
01651 #endif
01652 case LABEL_GLOBAL_ENTRY:
01653 targetm.asm_out.globalize_label (file, name);
01654 case LABEL_STATIC_ENTRY:
01655 #ifdef ASM_OUTPUT_TYPE_DIRECTIVE
01656 ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
01657 #endif
01658 ASM_OUTPUT_LABEL (file, name);
01659 break;
01660
01661 case LABEL_NORMAL:
01662 default:
01663 gcc_unreachable ();
01664 }
01665 }
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681 rtx
01682 final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
01683 int nopeepholes ATTRIBUTE_UNUSED, int *seen)
01684 {
01685 #ifdef HAVE_cc0
01686 rtx set;
01687 #endif
01688 rtx next;
01689
01690 insn_counter++;
01691
01692
01693
01694 if (INSN_DELETED_P (insn))
01695 return NEXT_INSN (insn);
01696
01697 switch (GET_CODE (insn))
01698 {
01699 case NOTE:
01700 switch (NOTE_LINE_NUMBER (insn))
01701 {
01702 case NOTE_INSN_DELETED:
01703 case NOTE_INSN_FUNCTION_END:
01704 case NOTE_INSN_REPEATED_LINE_NUMBER:
01705 case NOTE_INSN_EXPECTED_VALUE:
01706 break;
01707
01708 case NOTE_INSN_SWITCH_TEXT_SECTIONS:
01709 in_cold_section_p = !in_cold_section_p;
01710 (*debug_hooks->switch_text_section) ();
01711 switch_to_section (current_function_section ());
01712 break;
01713
01714 case NOTE_INSN_BASIC_BLOCK:
01715 #ifdef TARGET_UNWIND_INFO
01716 targetm.asm_out.unwind_emit (asm_out_file, insn);
01717 #endif
01718
01719 if (flag_debug_asm)
01720 fprintf (asm_out_file, "\t%s basic block %d\n",
01721 ASM_COMMENT_START, NOTE_BASIC_BLOCK (insn)->index);
01722
01723 if ((*seen & (SEEN_EMITTED | SEEN_BB)) == SEEN_BB)
01724 {
01725 *seen |= SEEN_EMITTED;
01726 force_source_line = true;
01727 }
01728 else
01729 *seen |= SEEN_BB;
01730
01731 break;
01732
01733 case NOTE_INSN_EH_REGION_BEG:
01734 ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHB",
01735 NOTE_EH_HANDLER (insn));
01736 break;
01737
01738 case NOTE_INSN_EH_REGION_END:
01739 ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHE",
01740 NOTE_EH_HANDLER (insn));
01741 break;
01742
01743 case NOTE_INSN_PROLOGUE_END:
01744 targetm.asm_out.function_end_prologue (file);
01745 profile_after_prologue (file);
01746
01747 if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
01748 {
01749 *seen |= SEEN_EMITTED;
01750 force_source_line = true;
01751 }
01752 else
01753 *seen |= SEEN_NOTE;
01754
01755 break;
01756
01757 case NOTE_INSN_EPILOGUE_BEG:
01758 targetm.asm_out.function_begin_epilogue (file);
01759 break;
01760
01761 case NOTE_INSN_FUNCTION_BEG:
01762 app_disable ();
01763 (*debug_hooks->end_prologue) (last_linenum, last_filename);
01764
01765 if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
01766 {
01767 *seen |= SEEN_EMITTED;
01768 force_source_line = true;
01769 }
01770 else
01771 *seen |= SEEN_NOTE;
01772
01773 break;
01774
01775 case NOTE_INSN_BLOCK_BEG:
01776 if (debug_info_level == DINFO_LEVEL_NORMAL
01777 || debug_info_level == DINFO_LEVEL_VERBOSE
01778 || write_symbols == DWARF2_DEBUG
01779 || write_symbols == VMS_AND_DWARF2_DEBUG
01780 || write_symbols == VMS_DEBUG)
01781 {
01782 int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
01783
01784 app_disable ();
01785 ++block_depth;
01786 high_block_linenum = last_linenum;
01787
01788
01789 (*debug_hooks->begin_block) (last_linenum, n);
01790
01791
01792 TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1;
01793 }
01794 break;
01795
01796 case NOTE_INSN_BLOCK_END:
01797 if (debug_info_level == DINFO_LEVEL_NORMAL
01798 || debug_info_level == DINFO_LEVEL_VERBOSE
01799 || write_symbols == DWARF2_DEBUG
01800 || write_symbols == VMS_AND_DWARF2_DEBUG
01801 || write_symbols == VMS_DEBUG)
01802 {
01803 int n = BLOCK_NUMBER (NOTE_BLOCK (insn));
01804
01805 app_disable ();
01806
01807
01808 --block_depth;
01809 gcc_assert (block_depth >= 0);
01810
01811 (*debug_hooks->end_block) (high_block_linenum, n);
01812 }
01813 break;
01814
01815 case NOTE_INSN_DELETED_LABEL:
01816
01817
01818
01819 ASM_OUTPUT_DEBUG_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
01820 break;
01821
01822 case NOTE_INSN_VAR_LOCATION:
01823 (*debug_hooks->var_location) (insn);
01824 break;
01825
01826 case 0:
01827 break;
01828
01829 default:
01830 gcc_assert (NOTE_LINE_NUMBER (insn) > 0);
01831 break;
01832 }
01833 break;
01834
01835 case BARRIER:
01836 #if defined (DWARF2_UNWIND_INFO)
01837 if (dwarf2out_do_frame ())
01838 dwarf2out_frame_debug (insn, false);
01839 #endif
01840 break;
01841
01842 case CODE_LABEL:
01843
01844
01845 if (CODE_LABEL_NUMBER (insn) <= max_labelno)
01846 {
01847 int align = LABEL_TO_ALIGNMENT (insn);
01848 #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
01849 int max_skip = LABEL_TO_MAX_SKIP (insn);
01850 #endif
01851
01852 if (align && NEXT_INSN (insn))
01853 {
01854 #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
01855 ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip);
01856 #else
01857 #ifdef ASM_OUTPUT_ALIGN_WITH_NOP
01858 ASM_OUTPUT_ALIGN_WITH_NOP (file, align);
01859 #else
01860 ASM_OUTPUT_ALIGN (file, align);
01861 #endif
01862 #endif
01863 }
01864 }
01865 #ifdef HAVE_cc0
01866 CC_STATUS_INIT;
01867
01868
01869
01870
01871
01872 if (0 )
01873 {
01874 rtx jump = LABEL_REFS (insn);
01875 rtx barrier = prev_nonnote_insn (insn);
01876 rtx prev;
01877
01878
01879
01880
01881
01882 if (barrier && BARRIER_P (barrier)
01883 && jump && JUMP_P (jump)
01884 && (prev = prev_nonnote_insn (jump))
01885 && NONJUMP_INSN_P (prev))
01886 {
01887 NOTICE_UPDATE_CC (PATTERN (prev), prev);
01888 NOTICE_UPDATE_CC (PATTERN (jump), jump);
01889 }
01890 }
01891 #endif
01892
01893 if (LABEL_NAME (insn))
01894 (*debug_hooks->label) (insn);
01895
01896 if (app_on)
01897 {
01898 fputs (ASM_APP_OFF, file);
01899 app_on = 0;
01900 }
01901
01902 next = next_nonnote_insn (insn);
01903 if (next != 0 && JUMP_P (next))
01904 {
01905 rtx nextbody = PATTERN (next);
01906
01907
01908
01909
01910
01911 if (GET_CODE (nextbody) == ADDR_VEC
01912 || GET_CODE (nextbody) == ADDR_DIFF_VEC)
01913 {
01914 #if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
01915
01916
01917
01918 #else
01919 if (! JUMP_TABLES_IN_TEXT_SECTION)
01920 {
01921 int log_align;
01922
01923 switch_to_section (targetm.asm_out.function_rodata_section
01924 (current_function_decl));
01925
01926 #ifdef ADDR_VEC_ALIGN
01927 log_align = ADDR_VEC_ALIGN (next);
01928 #else
01929 log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
01930 #endif
01931 ASM_OUTPUT_ALIGN (file, log_align);
01932 }
01933 else
01934 switch_to_section (current_function_section ());
01935
01936 #ifdef ASM_OUTPUT_CASE_LABEL
01937 ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
01938 next);
01939 #else
01940 targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
01941 #endif
01942 #endif
01943 break;
01944 }
01945 }
01946 if (LABEL_ALT_ENTRY_P (insn))
01947 output_alternate_entry_point (file, insn);
01948 else
01949 targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
01950 break;
01951
01952 default:
01953 {
01954 rtx body = PATTERN (insn);
01955 int insn_code_number;
01956 const char *template;
01957
01958 #ifdef HAVE_conditional_execution
01959
01960 current_insn_predicate = NULL_RTX;
01961 #endif
01962
01963
01964
01965 if (GET_CODE (body) == USE
01966 || GET_CODE (body) == CLOBBER)
01967 break;
01968
01969 #ifdef HAVE_cc0
01970 {
01971
01972
01973
01974
01975
01976 rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
01977 if (note)
01978 {
01979 NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0));
01980 cc_prev_status = cc_status;
01981 }
01982 }
01983 #endif
01984
01985
01986
01987
01988 if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
01989 {
01990 #if !(defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC))
01991 int vlen, idx;
01992 #endif
01993
01994 if (! JUMP_TABLES_IN_TEXT_SECTION)
01995 switch_to_section (targetm.asm_out.function_rodata_section
01996 (current_function_decl));
01997 else
01998 switch_to_section (current_function_section ());
01999
02000 if (app_on)
02001 {
02002 fputs (ASM_APP_OFF, file);
02003 app_on = 0;
02004 }
02005
02006 #if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
02007 if (GET_CODE (body) == ADDR_VEC)
02008 {
02009 #ifdef ASM_OUTPUT_ADDR_VEC
02010 ASM_OUTPUT_ADDR_VEC (PREV_INSN (insn), body);
02011 #else
02012 gcc_unreachable ();
02013 #endif
02014 }
02015 else
02016 {
02017 #ifdef ASM_OUTPUT_ADDR_DIFF_VEC
02018 ASM_OUTPUT_ADDR_DIFF_VEC (PREV_INSN (insn), body);
02019 #else
02020 gcc_unreachable ();
02021 #endif
02022 }
02023 #else
02024 vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC);
02025 for (idx = 0; idx < vlen; idx++)
02026 {
02027 if (GET_CODE (body) == ADDR_VEC)
02028 {
02029 #ifdef ASM_OUTPUT_ADDR_VEC_ELT
02030 ASM_OUTPUT_ADDR_VEC_ELT
02031 (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
02032 #else
02033 gcc_unreachable ();
02034 #endif
02035 }
02036 else
02037 {
02038 #ifdef ASM_OUTPUT_ADDR_DIFF_ELT
02039 ASM_OUTPUT_ADDR_DIFF_ELT
02040 (file,
02041 body,
02042 CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
02043 CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0)));
02044 #else
02045 gcc_unreachable ();
02046 #endif
02047 }
02048 }
02049 #ifdef ASM_OUTPUT_CASE_END
02050 ASM_OUTPUT_CASE_END (file,
02051 CODE_LABEL_NUMBER (PREV_INSN (insn)),
02052 insn);
02053 #endif
02054 #endif
02055
02056 switch_to_section (current_function_section ());
02057
02058 break;
02059 }
02060
02061
02062 if (notice_source_line (insn))
02063 {
02064 (*debug_hooks->source_line) (last_linenum, last_filename);
02065 }
02066
02067 if (GET_CODE (body) == ASM_INPUT)
02068 {
02069 const char *string = XSTR (body, 0);
02070
02071
02072 CC_STATUS_INIT;
02073
02074 if (string[0])
02075 {
02076 if (! app_on)
02077 {
02078 fputs (ASM_APP_ON, file);
02079 app_on = 1;
02080 }
02081 fprintf (asm_out_file, "\t%s\n", string);
02082 }
02083 break;
02084 }
02085
02086
02087 if (asm_noperands (body) >= 0)
02088 {
02089 unsigned int noperands = asm_noperands (body);
02090 rtx *ops = alloca (noperands * sizeof (rtx));
02091 const char *string;
02092
02093
02094 CC_STATUS_INIT;
02095
02096
02097 string = decode_asm_operands (body, ops, NULL, NULL, NULL);
02098
02099 insn_noperands = noperands;
02100 this_is_asm_operands = insn;
02101
02102 #ifdef FINAL_PRESCAN_INSN
02103 FINAL_PRESCAN_INSN (insn, ops, insn_noperands);
02104 #endif
02105
02106
02107 if (string[0])
02108 {
02109 if (! app_on)
02110 {
02111 fputs (ASM_APP_ON, file);
02112 app_on = 1;
02113 }
02114 output_asm_insn (string, ops);
02115 }
02116
02117 this_is_asm_operands = 0;
02118 break;
02119 }
02120
02121 if (app_on)
02122 {
02123 fputs (ASM_APP_OFF, file);
02124 app_on = 0;
02125 }
02126
02127 if (GET_CODE (body) == SEQUENCE)
02128 {
02129
02130 int i;
02131
02132 final_sequence = body;
02133
02134
02135
02136 #if defined (DWARF2_UNWIND_INFO)
02137 if (dwarf2out_do_frame ())
02138 for (i = 1; i < XVECLEN (body, 0); i++)
02139 dwarf2out_frame_debug (XVECEXP (body, 0, i), false);
02140 #endif
02141
02142
02143
02144
02145
02146
02147 next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, 1, seen);
02148 if (next != XVECEXP (body, 0, 1))
02149 {
02150 final_sequence = 0;
02151 return next;
02152 }
02153
02154 for (i = 1; i < XVECLEN (body, 0); i++)
02155 {
02156 rtx insn = XVECEXP (body, 0, i);
02157 rtx next = NEXT_INSN (insn);
02158
02159
02160 do
02161 insn = final_scan_insn (insn, file, 0, 1, seen);
02162 while (insn != next);
02163 }
02164 #ifdef DBR_OUTPUT_SEQEND
02165 DBR_OUTPUT_SEQEND (file);
02166 #endif
02167 final_sequence = 0;
02168
02169
02170
02171
02172
02173
02174 if (CALL_P (XVECEXP (body, 0, 0)))
02175 {
02176 CC_STATUS_INIT;
02177 }
02178 break;
02179 }
02180
02181
02182
02183 body = PATTERN (insn);
02184
02185 #ifdef HAVE_cc0
02186 set = single_set (insn);
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196 if (optimize)
02197 {
02198 if (set
02199 && GET_CODE (SET_DEST (set)) == CC0
02200 && insn != last_ignored_compare)
02201 {
02202 if (GET_CODE (SET_SRC (set)) == SUBREG)
02203 SET_SRC (set) = alter_subreg (&SET_SRC (set));
02204 else if (GET_CODE (SET_SRC (set)) == COMPARE)
02205 {
02206 if (GET_CODE (XEXP (SET_SRC (set), 0)) == SUBREG)
02207 XEXP (SET_SRC (set), 0)
02208 = alter_subreg (&XEXP (SET_SRC (set), 0));
02209 if (GET_CODE (XEXP (SET_SRC (set), 1)) == SUBREG)
02210 XEXP (SET_SRC (set), 1)
02211 = alter_subreg (&XEXP (SET_SRC (set), 1));
02212 }
02213 if ((cc_status.value1 != 0
02214 && rtx_equal_p (SET_SRC (set), cc_status.value1))
02215 || (cc_status.value2 != 0
02216 && rtx_equal_p (SET_SRC (set), cc_status.value2)))
02217 {
02218
02219 if (! FIND_REG_INC_NOTE (insn, NULL_RTX)
02220
02221 && ! volatile_refs_p (PATTERN (insn)))
02222 {
02223
02224 last_ignored_compare = insn;
02225 break;
02226 }
02227 }
02228 }
02229 }
02230 #endif
02231
02232 #ifdef HAVE_cc0
02233
02234
02235
02236
02237
02238 if (cc_status.flags != 0
02239 && JUMP_P (insn)
02240 && GET_CODE (body) == SET
02241 && SET_DEST (body) == pc_rtx
02242 && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE
02243 && COMPARISON_P (XEXP (SET_SRC (body), 0))
02244 && XEXP (XEXP (SET_SRC (body), 0), 0) == cc0_rtx)
02245 {
02246
02247
02248
02249
02250
02251 int result = alter_cond (XEXP (SET_SRC (body), 0));
02252
02253
02254 if (result == 1)
02255 SET_SRC (body) = XEXP (SET_SRC (body), 1);
02256 if (result == -1)
02257 SET_SRC (body) = XEXP (SET_SRC (body), 2);
02258
02259
02260
02261
02262 if (SET_SRC (body) == pc_rtx)
02263 {
02264 delete_insn (insn);
02265 break;
02266 }
02267 else if (GET_CODE (SET_SRC (body)) == RETURN)
02268
02269 PATTERN (insn) = body = SET_SRC (body);
02270
02271
02272 if (result != 0)
02273 INSN_CODE (insn) = -1;
02274 }
02275
02276
02277
02278
02279
02280 if (cc_status.flags != 0
02281 && set != 0)
02282 {
02283 rtx cond_rtx, then_rtx, else_rtx;
02284
02285 if (!JUMP_P (insn)
02286 && GET_CODE (SET_SRC (set)) == IF_THEN_ELSE)
02287 {
02288 cond_rtx = XEXP (SET_SRC (set), 0);
02289 then_rtx = XEXP (SET_SRC (set), 1);
02290 else_rtx = XEXP (SET_SRC (set), 2);
02291 }
02292 else
02293 {
02294 cond_rtx = SET_SRC (set);
02295 then_rtx = const_true_rtx;
02296 else_rtx = const0_rtx;
02297 }
02298
02299 switch (GET_CODE (cond_rtx))
02300 {
02301 case GTU:
02302 case GT:
02303 case LTU:
02304 case LT:
02305 case GEU:
02306 case GE:
02307 case LEU:
02308 case LE:
02309 case EQ:
02310 case NE:
02311 {
02312 int result;
02313 if (XEXP (cond_rtx, 0) != cc0_rtx)
02314 break;
02315 result = alter_cond (cond_rtx);
02316 if (result == 1)
02317 validate_change (insn, &SET_SRC (set), then_rtx, 0);
02318 else if (result == -1)
02319 validate_change (insn, &SET_SRC (set), else_rtx, 0);
02320 else if (result == 2)
02321 INSN_CODE (insn) = -1;
02322 if (SET_DEST (set) == SET_SRC (set))
02323 delete_insn (insn);
02324 }
02325 break;
02326
02327 default:
02328 break;
02329 }
02330 }
02331
02332 #endif
02333
02334 #ifdef HAVE_peephole
02335
02336
02337 if (optimize && !flag_no_peephole && !nopeepholes)
02338 {
02339 rtx next = peephole (insn);
02340
02341
02342 if (next != 0 && next != NEXT_INSN (insn))
02343 {
02344 rtx note, prev = PREV_INSN (insn);
02345
02346 for (note = NEXT_INSN (insn); note != next;
02347 note = NEXT_INSN (note))
02348 final_scan_insn (note, file, optimize, nopeepholes, seen);
02349
02350
02351
02352
02353
02354 note = NEXT_INSN (insn);
02355 PREV_INSN (note) = prev;
02356 NEXT_INSN (prev) = note;
02357 NEXT_INSN (PREV_INSN (next)) = insn;
02358 PREV_INSN (insn) = PREV_INSN (next);
02359 NEXT_INSN (insn) = next;
02360 PREV_INSN (next) = insn;
02361 }
02362
02363
02364 body = PATTERN (insn);
02365 }
02366 #endif
02367
02368
02369
02370
02371
02372
02373 insn_code_number = recog_memoized (insn);
02374 cleanup_subreg_operands (insn);
02375
02376
02377 if (flag_dump_rtl_in_asm)
02378 {
02379 print_rtx_head = ASM_COMMENT_START;
02380 print_rtl_single (asm_out_file, insn);
02381 print_rtx_head = "";
02382 }
02383
02384 if (! constrain_operands_cached (1))
02385 fatal_insn_not_found (insn);
02386
02387
02388
02389
02390 #ifdef FINAL_PRESCAN_INSN
02391 FINAL_PRESCAN_INSN (insn, recog_data.operand, recog_data.n_operands);
02392 #endif
02393
02394 #ifdef HAVE_conditional_execution
02395 if (GET_CODE (PATTERN (insn)) == COND_EXEC)
02396 current_insn_predicate = COND_EXEC_TEST (PATTERN (insn));
02397 #endif
02398
02399 #ifdef HAVE_cc0
02400 cc_prev_status = cc_status;
02401
02402
02403
02404
02405
02406
02407 NOTICE_UPDATE_CC (body, insn);
02408 #endif
02409
02410 current_output_insn = debug_insn = insn;
02411
02412 #if defined (DWARF2_UNWIND_INFO)
02413 if (CALL_P (insn) && dwarf2out_do_frame ())
02414 dwarf2out_frame_debug (insn, false);
02415 #endif
02416
02417
02418 template = get_insn_template (insn_code_number, insn);
02419
02420
02421
02422
02423 if (template == 0)
02424 {
02425 rtx prev;
02426
02427 gcc_assert (prev_nonnote_insn (insn) == last_ignored_compare);
02428
02429
02430
02431
02432
02433 for (prev = insn;
02434 prev != last_ignored_compare;
02435 prev = PREV_INSN (prev))
02436 {
02437 if (NOTE_P (prev))
02438 delete_insn (prev);
02439 }
02440
02441 return prev;
02442 }
02443
02444
02445
02446 if (template[0] == '#' && template[1] == '\0')
02447 {
02448 rtx new = try_split (body, insn, 0);
02449
02450
02451 if (new == insn && PATTERN (new) == body)
02452 fatal_insn ("could not split insn", insn);
02453
02454 #ifdef HAVE_ATTR_length
02455
02456
02457
02458 gcc_unreachable ();
02459 #endif
02460
02461 return new;
02462 }
02463
02464 #ifdef TARGET_UNWIND_INFO
02465
02466
02467
02468 targetm.asm_out.unwind_emit (asm_out_file, insn);
02469 #endif
02470
02471
02472 output_asm_insn (template, recog_data.operand);
02473
02474
02475
02476
02477 #if defined (DWARF2_UNWIND_INFO)
02478 if (final_sequence == 0
02479 #if !defined (HAVE_prologue)
02480 && !ACCUMULATE_OUTGOING_ARGS
02481 #endif
02482 && dwarf2out_do_frame ())
02483 dwarf2out_frame_debug (insn, true);
02484 #endif
02485
02486 current_output_insn = debug_insn = 0;
02487 }
02488 }
02489 return NEXT_INSN (insn);
02490 }
02491
02492
02493
02494 static bool
02495 notice_source_line (rtx insn)
02496 {
02497 const char *filename = insn_file (insn);
02498 int linenum = insn_line (insn);
02499
02500 if (filename
02501 && (force_source_line
02502 || filename != last_filename
02503 || last_linenum != linenum))
02504 {
02505 force_source_line = false;
02506 last_filename = filename;
02507 last_linenum = linenum;
02508 high_block_linenum = MAX (last_linenum, high_block_linenum);
02509 high_function_linenum = MAX (last_linenum, high_function_linenum);
02510 return true;
02511 }
02512 return false;
02513 }
02514
02515
02516
02517
02518 void
02519 cleanup_subreg_operands (rtx insn)
02520 {
02521 int i;
02522 extract_insn_cached (insn);
02523 for (i = 0; i < recog_data.n_operands; i++)
02524 {
02525
02526
02527
02528
02529
02530 if (GET_CODE (*recog_data.operand_loc[i]) == SUBREG)
02531 recog_data.operand[i] = alter_subreg (recog_data.operand_loc[i]);
02532 else if (GET_CODE (recog_data.operand[i]) == PLUS
02533 || GET_CODE (recog_data.operand[i]) == MULT
02534 || MEM_P (recog_data.operand[i]))
02535 recog_data.operand[i] = walk_alter_subreg (recog_data.operand_loc[i]);
02536 }
02537
02538 for (i = 0; i < recog_data.n_dups; i++)
02539 {
02540 if (GET_CODE (*recog_data.dup_loc[i]) == SUBREG)
02541 *recog_data.dup_loc[i] = alter_subreg (recog_data.dup_loc[i]);
02542 else if (GET_CODE (*recog_data.dup_loc[i]) == PLUS
02543 || GET_CODE (*recog_data.dup_loc[i]) == MULT
02544 || MEM_P (*recog_data.dup_loc[i]))
02545 *recog_data.dup_loc[i] = walk_alter_subreg (recog_data.dup_loc[i]);
02546 }
02547 }
02548
02549
02550
02551
02552 rtx
02553 alter_subreg (rtx *xp)
02554 {
02555 rtx x = *xp;
02556 rtx y = SUBREG_REG (x);
02557
02558
02559
02560 if (MEM_P (y))
02561 {
02562 int offset = SUBREG_BYTE (x);
02563
02564
02565
02566 if (offset == 0
02567 && GET_MODE_SIZE (GET_MODE (y)) < GET_MODE_SIZE (GET_MODE (x)))
02568 {
02569 int difference = GET_MODE_SIZE (GET_MODE (y))
02570 - GET_MODE_SIZE (GET_MODE (x));
02571 if (WORDS_BIG_ENDIAN)
02572 offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
02573 if (BYTES_BIG_ENDIAN)
02574 offset += difference % UNITS_PER_WORD;
02575 }
02576
02577 *xp = adjust_address (y, GET_MODE (x), offset);
02578 }
02579 else
02580 {
02581 rtx new = simplify_subreg (GET_MODE (x), y, GET_MODE (y),
02582 SUBREG_BYTE (x));
02583
02584 if (new != 0)
02585 *xp = new;
02586 else if (REG_P (y))
02587 {
02588
02589 unsigned int regno = subreg_regno (x);
02590 *xp = gen_rtx_REG_offset (y, GET_MODE (x), regno, SUBREG_BYTE (x));
02591 }
02592 }
02593
02594 return *xp;
02595 }
02596
02597
02598
02599 static rtx
02600 walk_alter_subreg (rtx *xp)
02601 {
02602 rtx x = *xp;
02603 switch (GET_CODE (x))
02604 {
02605 case PLUS:
02606 case MULT:
02607 case AND:
02608 XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0));
02609 XEXP (x, 1) = walk_alter_subreg (&XEXP (x, 1));
02610 break;
02611
02612 case MEM:
02613 case ZERO_EXTEND:
02614 XEXP (x, 0) = walk_alter_subreg (&XEXP (x, 0));
02615 break;
02616
02617 case SUBREG:
02618 return alter_subreg (xp);
02619
02620 default:
02621 break;
02622 }
02623
02624 return *xp;
02625 }
02626
02627 #ifdef HAVE_cc0
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638 static int
02639 alter_cond (rtx cond)
02640 {
02641 int value = 0;
02642
02643 if (cc_status.flags & CC_REVERSED)
02644 {
02645 value = 2;
02646 PUT_CODE (cond, swap_condition (GET_CODE (cond)));
02647 }
02648
02649 if (cc_status.flags & CC_INVERTED)
02650 {
02651 value = 2;
02652 PUT_CODE (cond, reverse_condition (GET_CODE (cond)));
02653 }
02654
02655 if (cc_status.flags & CC_NOT_POSITIVE)
02656 switch (GET_CODE (cond))
02657 {
02658 case LE:
02659 case LEU:
02660 case GEU:
02661
02662 return 1;
02663
02664 case GT:
02665 case GTU:
02666 case LTU:
02667
02668 return -1;
02669
02670 case GE:
02671 PUT_CODE (cond, EQ);
02672 value = 2;
02673 break;
02674
02675 case LT:
02676 PUT_CODE (cond, NE);
02677 value = 2;
02678 break;
02679
02680 default:
02681 break;
02682 }
02683
02684 if (cc_status.flags & CC_NOT_NEGATIVE)
02685 switch (GET_CODE (cond))
02686 {
02687 case GE:
02688 case GEU:
02689
02690 return 1;
02691
02692 case LT:
02693 case LTU:
02694
02695 return -1;
02696
02697 case LE:
02698 case LEU:
02699 PUT_CODE (cond, EQ);
02700 value = 2;
02701 break;
02702
02703 case GT:
02704 case GTU:
02705 PUT_CODE (cond, NE);
02706 value = 2;
02707 break;
02708
02709 default:
02710 break;
02711 }
02712
02713 if (cc_status.flags & CC_NO_OVERFLOW)
02714 switch (GET_CODE (cond))
02715 {
02716 case GEU:
02717
02718 return 1;
02719
02720 case LEU:
02721 PUT_CODE (cond, EQ);
02722 value = 2;
02723 break;
02724
02725 case GTU:
02726 PUT_CODE (cond, NE);
02727 value = 2;
02728 break;
02729
02730 case LTU:
02731
02732 return -1;
02733
02734 default:
02735 break;
02736 }
02737
02738 if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N))
02739 switch (GET_CODE (cond))
02740 {
02741 default:
02742 gcc_unreachable ();
02743
02744 case NE:
02745 PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? GE : LT);
02746 value = 2;
02747 break;
02748
02749 case EQ:
02750 PUT_CODE (cond, cc_status.flags & CC_Z_IN_N ? LT : GE);
02751 value = 2;
02752 break;
02753 }
02754
02755 if (cc_status.flags & CC_NOT_SIGNED)
02756
02757
02758 switch (GET_CODE (cond))
02759 {
02760 case LE:
02761 PUT_CODE (cond, LEU);
02762 value = 2;
02763 break;
02764
02765 case LT:
02766 PUT_CODE (cond, LTU);
02767 value = 2;
02768 break;
02769
02770 case GT:
02771 PUT_CODE (cond, GTU);
02772 value = 2;
02773 break;
02774
02775 case GE:
02776 PUT_CODE (cond, GEU);
02777 value = 2;
02778 break;
02779
02780 default:
02781 break;
02782 }
02783
02784 return value;
02785 }
02786 #endif
02787
02788
02789
02790
02791 void
02792 output_operand_lossage (const char *cmsgid, ...)
02793 {
02794 char *fmt_string;
02795 char *new_message;
02796 const char *pfx_str;
02797 va_list ap;
02798
02799 va_start (ap, cmsgid);
02800
02801 pfx_str = this_is_asm_operands ? _("invalid 'asm': ") : "output_operand: ";
02802 asprintf (&fmt_string, "%s%s", pfx_str, _(cmsgid));
02803 vasprintf (&new_message, fmt_string, ap);
02804
02805 if (this_is_asm_operands)
02806 error_for_asm (this_is_asm_operands, "%s", new_message);
02807 else
02808 internal_error ("%s", new_message);
02809
02810 free (fmt_string);
02811 free (new_message);
02812 va_end (ap);
02813 }
02814
02815
02816
02817
02818
02819
02820 static void
02821 output_asm_name (void)
02822 {
02823 if (debug_insn)
02824 {
02825 int num = INSN_CODE (debug_insn);
02826 fprintf (asm_out_file, "\t%s %d\t%s",
02827 ASM_COMMENT_START, INSN_UID (debug_insn),
02828 insn_data[num].name);
02829 if (insn_data[num].n_alternatives > 1)
02830 fprintf (asm_out_file, "/%d", which_alternative + 1);
02831 #ifdef HAVE_ATTR_length
02832 fprintf (asm_out_file, "\t[length = %d]",
02833 get_attr_length (debug_insn));
02834 #endif
02835
02836
02837 debug_insn = 0;
02838 }
02839 }
02840
02841
02842
02843
02844
02845 static tree
02846 get_mem_expr_from_op (rtx op, int *paddressp)
02847 {
02848 tree expr;
02849 int inner_addressp;
02850
02851 *paddressp = 0;
02852
02853 if (REG_P (op))
02854 return REG_EXPR (op);
02855 else if (!MEM_P (op))
02856 return 0;
02857
02858 if (MEM_EXPR (op) != 0)
02859 return MEM_EXPR (op);
02860
02861
02862 *paddressp = 1;
02863 op = XEXP (op, 0);
02864
02865
02866
02867
02868 if ((expr = get_mem_expr_from_op (op, &inner_addressp)) && ! inner_addressp)
02869 return expr;
02870 else if (GET_CODE (op) == PLUS
02871 && (expr = get_mem_expr_from_op (XEXP (op, 1), &inner_addressp)))
02872 return expr;
02873
02874 while (GET_RTX_CLASS (GET_CODE (op)) == RTX_UNARY
02875 || GET_RTX_CLASS (GET_CODE (op)) == RTX_BIN_ARITH)
02876 op = XEXP (op, 0);
02877
02878 expr = get_mem_expr_from_op (op, &inner_addressp);
02879 return inner_addressp ? 0 : expr;
02880 }
02881
02882
02883
02884
02885
02886 static void
02887 output_asm_operand_names (rtx *operands, int *oporder, int nops)
02888 {
02889 int wrote = 0;
02890 int i;
02891
02892 for (i = 0; i < nops; i++)
02893 {
02894 int addressp;
02895 rtx op = operands[oporder[i]];
02896 tree expr = get_mem_expr_from_op (op, &addressp);
02897
02898 fprintf (asm_out_file, "%c%s",
02899 wrote ? ',' : '\t', wrote ? "" : ASM_COMMENT_START);
02900 wrote = 1;
02901 if (expr)
02902 {
02903 fprintf (asm_out_file, "%s",
02904 addressp ? "*" : "");
02905 print_mem_expr (asm_out_file, expr);
02906 wrote = 1;
02907 }
02908 else if (REG_P (op) && ORIGINAL_REGNO (op)
02909 && ORIGINAL_REGNO (op) != REGNO (op))
02910 fprintf (asm_out_file, " tmp%i", ORIGINAL_REGNO (op));
02911 }
02912 }
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930 void
02931 output_asm_insn (const char *template, rtx *operands)
02932 {
02933 const char *p;
02934 int c;
02935 #ifdef ASSEMBLER_DIALECT
02936 int dialect = 0;
02937 #endif
02938 int oporder[MAX_RECOG_OPERANDS];
02939 char opoutput[MAX_RECOG_OPERANDS];
02940 int ops = 0;
02941
02942
02943
02944 if (*template == 0)
02945 return;
02946
02947 memset (opoutput, 0, sizeof opoutput);
02948 p = template;
02949 putc ('\t', asm_out_file);
02950
02951 #ifdef ASM_OUTPUT_OPCODE
02952 ASM_OUTPUT_OPCODE (asm_out_file, p);
02953 #endif
02954
02955 while ((c = *p++))
02956 switch (c)
02957 {
02958 case '\n':
02959 if (flag_verbose_asm)
02960 output_asm_operand_names (operands, oporder, ops);
02961 if (flag_print_asm_name)
02962 output_asm_name ();
02963
02964 ops = 0;
02965 memset (opoutput, 0, sizeof opoutput);
02966
02967 putc (c, asm_out_file);
02968 #ifdef ASM_OUTPUT_OPCODE
02969 while ((c = *p) == '\t')
02970 {
02971 putc (c, asm_out_file);
02972 p++;
02973 }
02974 ASM_OUTPUT_OPCODE (asm_out_file, p);
02975 #endif
02976 break;
02977
02978 #ifdef ASSEMBLER_DIALECT
02979 case '{':
02980 {
02981 int i;
02982
02983 if (dialect)
02984 output_operand_lossage ("nested assembly dialect alternatives");
02985 else
02986 dialect = 1;
02987
02988
02989
02990 for (i = 0; i < dialect_number; i++)
02991 {
02992 while (*p && *p != '}' && *p++ != '|')
02993 ;
02994 if (*p == '}')
02995 break;
02996 if (*p == '|')
02997 p++;
02998 }
02999
03000 if (*p == '\0')
03001 output_operand_lossage ("unterminated assembly dialect alternative");
03002 }
03003 break;
03004
03005 case '|':
03006 if (dialect)
03007 {
03008
03009 do
03010 {
03011 if (*p == '\0')
03012 {
03013 output_operand_lossage ("unterminated assembly dialect alternative");
03014 break;
03015 }
03016 }
03017 while (*p++ != '}');
03018 dialect = 0;
03019 }
03020 else
03021 putc (c, asm_out_file);
03022 break;
03023
03024 case '}':
03025 if (! dialect)
03026 putc (c, asm_out_file);
03027 dialect = 0;
03028 break;
03029 #endif
03030
03031 case '%':
03032
03033 if (*p == '%')
03034 {
03035 p++;
03036 putc (c, asm_out_file);
03037 }
03038
03039
03040
03041 else if (*p == '=')
03042 {
03043 p++;
03044 fprintf (asm_out_file, "%d", insn_counter);
03045 }
03046
03047
03048
03049
03050
03051 else if (ISALPHA (*p))
03052 {
03053 int letter = *p++;
03054 unsigned long opnum;
03055 char *endptr;
03056
03057 opnum = strtoul (p, &endptr, 10);
03058
03059 if (endptr == p)
03060 output_operand_lossage ("operand number missing "
03061 "after %%-letter");
03062 else if (this_is_asm_operands && opnum >= insn_noperands)
03063 output_operand_lossage ("operand number out of range");
03064 else if (letter == 'l')
03065 output_asm_label (operands[opnum]);
03066 else if (letter == 'a')
03067 output_address (operands[opnum]);
03068 else if (letter == 'c')
03069 {
03070 if (CONSTANT_ADDRESS_P (operands[opnum]))
03071 output_addr_const (asm_out_file, operands[opnum]);
03072 else
03073 output_operand (operands[opnum], 'c');
03074 }
03075 else if (letter == 'n')
03076 {
03077 if (GET_CODE (operands[opnum]) == CONST_INT)
03078 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC,
03079 - INTVAL (operands[opnum]));
03080 else
03081 {
03082 putc ('-', asm_out_file);
03083 output_addr_const (asm_out_file, operands[opnum]);
03084 }
03085 }
03086 else
03087 output_operand (operands[opnum], letter);
03088
03089 if (!opoutput[opnum])
03090 oporder[ops++] = opnum;
03091 opoutput[opnum] = 1;
03092
03093 p = endptr;
03094 c = *p;
03095 }
03096
03097 else if (ISDIGIT (*p))
03098 {
03099 unsigned long opnum;
03100 char *endptr;
03101
03102 opnum = strtoul (p, &endptr, 10);
03103 if (this_is_asm_operands && opnum >= insn_noperands)
03104 output_operand_lossage ("operand number out of range");
03105 else
03106 output_operand (operands[opnum], 0);
03107
03108 if (!opoutput[opnum])
03109 oporder[ops++] = opnum;
03110 opoutput[opnum] = 1;
03111
03112 p = endptr;
03113 c = *p;
03114 }
03115
03116
03117
03118 #ifdef PRINT_OPERAND_PUNCT_VALID_P
03119 else if (PRINT_OPERAND_PUNCT_VALID_P ((unsigned char) *p))
03120 output_operand (NULL_RTX, *p++);
03121 #endif
03122 else
03123 output_operand_lossage ("invalid %%-code");
03124 break;
03125
03126 default:
03127 putc (c, asm_out_file);
03128 }
03129
03130
03131 if (flag_verbose_asm)
03132 output_asm_operand_names (operands, oporder, ops);
03133 if (flag_print_asm_name)
03134 output_asm_name ();
03135
03136 putc ('\n', asm_out_file);
03137 }
03138
03139
03140
03141 void
03142 output_asm_label (rtx x)
03143 {
03144 char buf[256];
03145
03146 if (GET_CODE (x) == LABEL_REF)
03147 x = XEXP (x, 0);
03148 if (LABEL_P (x)
03149 || (NOTE_P (x)
03150 && NOTE_LINE_NUMBER (x) == NOTE_INSN_DELETED_LABEL))
03151 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
03152 else
03153 output_operand_lossage ("'%%l' operand isn't a label");
03154
03155 assemble_name (asm_out_file, buf);
03156 }
03157
03158
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168 static void
03169 output_operand (rtx x, int code ATTRIBUTE_UNUSED)
03170 {
03171 if (x && GET_CODE (x) == SUBREG)
03172 x = alter_subreg (&x);
03173
03174
03175 gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER);
03176
03177 PRINT_OPERAND (asm_out_file, x, code);
03178 }
03179
03180
03181
03182
03183
03184 void
03185 output_address (rtx x)
03186 {
03187 walk_alter_subreg (&x);
03188 PRINT_OPERAND_ADDRESS (asm_out_file, x);
03189 }
03190
03191
03192
03193
03194
03195 void
03196 output_addr_const (FILE *file, rtx x)
03197 {
03198 char buf[256];
03199
03200 restart:
03201 switch (GET_CODE (x))
03202 {
03203 case PC:
03204 putc ('.', file);
03205 break;
03206
03207 case SYMBOL_REF:
03208 if (SYMBOL_REF_DECL (x))
03209 mark_decl_referenced (SYMBOL_REF_DECL (x));
03210 #ifdef ASM_OUTPUT_SYMBOL_REF
03211 ASM_OUTPUT_SYMBOL_REF (file, x);
03212 #else
03213 assemble_name (file, XSTR (x, 0));
03214 #endif
03215 break;
03216
03217 case LABEL_REF:
03218 x = XEXP (x, 0);
03219
03220 case CODE_LABEL:
03221 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
03222 #ifdef ASM_OUTPUT_LABEL_REF
03223 ASM_OUTPUT_LABEL_REF (file, buf);
03224 #else
03225 assemble_name (file, buf);
03226 #endif
03227 break;
03228
03229 case CONST_INT:
03230 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
03231 break;
03232
03233 case CONST:
03234
03235
03236 output_addr_const (file, XEXP (x, 0));
03237 break;
03238
03239 case CONST_DOUBLE:
03240 if (GET_MODE (x) == VOIDmode)
03241 {
03242
03243 if (CONST_DOUBLE_HIGH (x))
03244 fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
03245 CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
03246 else if (CONST_DOUBLE_LOW (x) < 0)
03247 fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
03248 else
03249 fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
03250 }
03251 else
03252
03253
03254 output_operand_lossage ("floating constant misused");
03255 break;
03256
03257 case PLUS:
03258
03259 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
03260 {
03261 output_addr_const (file, XEXP (x, 1));
03262 if (INTVAL (XEXP (x, 0)) >= 0)
03263 fprintf (file, "+");
03264 output_addr_const (file, XEXP (x, 0));
03265 }
03266 else
03267 {
03268 output_addr_const (file, XEXP (x, 0));
03269 if (GET_CODE (XEXP (x, 1)) != CONST_INT
03270 || INTVAL (XEXP (x, 1)) >= 0)
03271 fprintf (file, "+");
03272 output_addr_const (file, XEXP (x, 1));
03273 }
03274 break;
03275
03276 case MINUS:
03277
03278
03279 x = simplify_subtraction (x);
03280 if (GET_CODE (x) != MINUS)
03281 goto restart;
03282
03283 output_addr_const (file, XEXP (x, 0));
03284 fprintf (file, "-");
03285 if ((GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) >= 0)
03286 || GET_CODE (XEXP (x, 1)) == PC
03287 || GET_CODE (XEXP (x, 1)) == SYMBOL_REF)
03288 output_addr_const (file, XEXP (x, 1));
03289 else
03290 {
03291 fputs (targetm.asm_out.open_paren, file);
03292 output_addr_const (file, XEXP (x, 1));
03293 fputs (targetm.asm_out.close_paren, file);
03294 }
03295 break;
03296
03297 case ZERO_EXTEND:
03298 case SIGN_EXTEND:
03299 case SUBREG:
03300 output_addr_const (file, XEXP (x, 0));
03301 break;
03302
03303 default:
03304 #ifdef OUTPUT_ADDR_CONST_EXTRA
03305 OUTPUT_ADDR_CONST_EXTRA (file, x, fail);
03306 break;
03307
03308 fail:
03309 #endif
03310 output_operand_lossage ("invalid expression as operand");
03311 }
03312 }
03313
03314
03315
03316
03317
03318
03319
03320
03321
03322
03323
03324 void
03325 asm_fprintf (FILE *file, const char *p, ...)
03326 {
03327 char buf[10];
03328 char *q, c;
03329 va_list argptr;
03330
03331 va_start (argptr, p);
03332
03333 buf[0] = '%';
03334
03335 while ((c = *p++))
03336 switch (c)
03337 {
03338 #ifdef ASSEMBLER_DIALECT
03339 case '{':
03340 {
03341 int i;
03342
03343
03344
03345 for (i = 0; i < dialect_number; i++)
03346 {
03347 while (*p && *p++ != '|')
03348 ;
03349
03350 if (*p == '|')
03351 p++;
03352 }
03353 }
03354 break;
03355
03356 case '|':
03357
03358 while (*p && *p++ != '}')
03359 ;
03360 break;
03361
03362 case '}':
03363 break;
03364 #endif
03365
03366 case '%':
03367 c = *p++;
03368 q = &buf[1];
03369 while (strchr ("-+ #0", c))
03370 {
03371 *q++ = c;
03372 c = *p++;
03373 }
03374 while (ISDIGIT (c) || c == '.')
03375 {
03376 *q++ = c;
03377 c = *p++;
03378 }
03379 switch (c)
03380 {
03381 case '%':
03382 putc ('%', file);
03383 break;
03384
03385 case 'd': case 'i': case 'u':
03386 case 'x': case 'X': case 'o':
03387 case 'c':
03388 *q++ = c;
03389 *q = 0;
03390 fprintf (file, buf, va_arg (argptr, int));
03391 break;
03392
03393 case 'w':
03394
03395
03396
03397
03398 memcpy (q, HOST_WIDE_INT_PRINT, strlen (HOST_WIDE_INT_PRINT));
03399 q += strlen (HOST_WIDE_INT_PRINT);
03400 *q++ = *p++;
03401 *q = 0;
03402 fprintf (file, buf, va_arg (argptr, HOST_WIDE_INT));
03403 break;
03404
03405 case 'l':
03406 *q++ = c;
03407 #ifdef HAVE_LONG_LONG
03408 if (*p == 'l')
03409 {
03410 *q++ = *p++;
03411 *q++ = *p++;
03412 *q = 0;
03413 fprintf (file, buf, va_arg (argptr, long long));
03414 }
03415 else
03416 #endif
03417 {
03418 *q++ = *p++;
03419 *q = 0;
03420 fprintf (file, buf, va_arg (argptr, long));
03421 }
03422
03423 break;
03424
03425 case 's':
03426 *q++ = c;
03427 *q = 0;
03428 fprintf (file, buf, va_arg (argptr, char *));
03429 break;
03430
03431 case 'O':
03432 #ifdef ASM_OUTPUT_OPCODE
03433 ASM_OUTPUT_OPCODE (asm_out_file, p);
03434 #endif
03435 break;
03436
03437 case 'R':
03438 #ifdef REGISTER_PREFIX
03439 fprintf (file, "%s", REGISTER_PREFIX);
03440 #endif
03441 break;
03442
03443 case 'I':
03444 #ifdef IMMEDIATE_PREFIX
03445 fprintf (file, "%s", IMMEDIATE_PREFIX);
03446 #endif
03447 break;
03448
03449 case 'L':
03450 #ifdef LOCAL_LABEL_PREFIX
03451 fprintf (file, "%s", LOCAL_LABEL_PREFIX);
03452 #endif
03453 break;
03454
03455 case 'U':
03456 fputs (user_label_prefix, file);
03457 break;
03458
03459 #ifdef ASM_FPRINTF_EXTENSIONS
03460
03461
03462
03463
03464
03465 case 'A': case 'B': case 'C': case 'D': case 'E':
03466 case 'F': case 'G': case 'H': case 'J': case 'K':
03467 case 'M': case 'N': case 'P': case 'Q': case 'S':
03468 case 'T': case 'V': case 'W': case 'Y': case 'Z':
03469 break;
03470
03471 ASM_FPRINTF_EXTENSIONS (file, argptr, p)
03472 #endif
03473 default:
03474 gcc_unreachable ();
03475 }
03476 break;
03477
03478 default:
03479 putc (c, file);
03480 }
03481 va_end (argptr);
03482 }
03483
03484
03485
03486
03487
03488
03489 void
03490 split_double (rtx value, rtx *first, rtx *second)
03491 {
03492 if (GET_CODE (value) == CONST_INT)
03493 {
03494 if (HOST_BITS_PER_WIDE_INT >= (2 * BITS_PER_WORD))
03495 {
03496
03497
03498
03499 unsigned HOST_WIDE_INT low, high;
03500 unsigned HOST_WIDE_INT mask, sign_bit, sign_extend;
03501
03502
03503 sign_bit = 1;
03504 sign_bit <<= BITS_PER_WORD - 1;
03505
03506
03507
03508
03509
03510
03511
03512 mask = sign_bit << 1;
03513 mask--;
03514
03515
03516 sign_extend = ~mask;
03517
03518
03519 low = INTVAL (value);
03520 low &= mask;
03521 if (low & sign_bit)
03522 low |= sign_extend;
03523
03524
03525
03526 high = INTVAL (value);
03527 high >>= BITS_PER_WORD - 1;
03528 high >>= 1;
03529 high &= mask;
03530 if (high & sign_bit)
03531 high |= sign_extend;
03532
03533
03534 if (WORDS_BIG_ENDIAN)
03535 {
03536 *first = GEN_INT (high);
03537 *second = GEN_INT (low);
03538 }
03539 else
03540 {
03541 *first = GEN_INT (low);
03542 *second = GEN_INT (high);
03543 }
03544 }
03545 else
03546 {
03547
03548
03549
03550 rtx high = (INTVAL (value) < 0 ? constm1_rtx : const0_rtx);
03551 if (WORDS_BIG_ENDIAN)
03552 {
03553 *first = high;
03554 *second = value;
03555 }
03556 else
03557 {
03558 *first = value;
03559 *second = high;
03560 }
03561 }
03562 }
03563 else if (GET_CODE (value) != CONST_DOUBLE)
03564 {
03565 if (WORDS_BIG_ENDIAN)
03566 {
03567 *first = const0_rtx;
03568 *second = value;
03569 }
03570 else
03571 {
03572 *first = value;
03573 *second = const0_rtx;
03574 }
03575 }
03576 else if (GET_MODE (value) == VOIDmode
03577
03578 || GET_MODE_CLASS (GET_MODE (value)) == MODE_INT)
03579 {
03580
03581
03582 if (WORDS_BIG_ENDIAN)
03583 {
03584 *first = GEN_INT (CONST_DOUBLE_HIGH (value));
03585 *second = GEN_INT (CONST_DOUBLE_LOW (value));
03586 }
03587 else
03588 {
03589 *first = GEN_INT (CONST_DOUBLE_LOW (value));
03590 *second = GEN_INT (CONST_DOUBLE_HIGH (value));
03591 }
03592 }
03593 else
03594 {
03595 REAL_VALUE_TYPE r;
03596 long l[2];
03597 REAL_VALUE_FROM_CONST_DOUBLE (r, value);
03598
03599
03600
03601
03602
03603 REAL_VALUE_TO_TARGET_DOUBLE (r, l);
03604
03605
03606
03607
03608
03609
03610
03611 #if HOST_BITS_PER_LONG > 32
03612 if (BITS_PER_WORD < HOST_BITS_PER_LONG && BITS_PER_WORD == 32)
03613 {
03614 if (l[0] & ((long) 1 << 31))
03615 l[0] |= ((long) (-1) << 32);
03616 if (l[1] & ((long) 1 << 31))
03617 l[1] |= ((long) (-1) << 32);
03618 }
03619 #endif
03620
03621 *first = GEN_INT (l[0]);
03622 *second = GEN_INT (l[1]);
03623 }
03624 }
03625
03626
03627
03628 int
03629 leaf_function_p (void)
03630 {
03631 rtx insn;
03632 rtx link;
03633
03634 if (current_function_profile || profile_arc_flag)
03635 return 0;
03636
03637 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
03638 {
03639 if (CALL_P (insn)
03640 && ! SIBLING_CALL_P (insn))
03641 return 0;
03642 if (NONJUMP_INSN_P (insn)
03643 && GET_CODE (PATTERN (insn)) == SEQUENCE
03644 && CALL_P (XVECEXP (PATTERN (insn), 0, 0))
03645 && ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0)))
03646 return 0;
03647 }
03648 for (link = current_function_epilogue_delay_list;
03649 link;
03650 link = XEXP (link, 1))
03651 {
03652 insn = XEXP (link, 0);
03653
03654 if (CALL_P (insn)
03655 && ! SIBLING_CALL_P (insn))
03656 return 0;
03657 if (NONJUMP_INSN_P (insn)
03658 && GET_CODE (PATTERN (insn)) == SEQUENCE
03659 && CALL_P (XVECEXP (PATTERN (insn), 0, 0))
03660 && ! SIBLING_CALL_P (XVECEXP (PATTERN (insn), 0, 0)))
03661 return 0;
03662 }
03663
03664 return 1;
03665 }
03666
03667
03668
03669
03670
03671 int
03672 final_forward_branch_p (rtx insn)
03673 {
03674 int insn_id, label_id;
03675
03676 gcc_assert (uid_shuid);
03677 insn_id = INSN_SHUID (insn);
03678 label_id = INSN_SHUID (JUMP_LABEL (insn));
03679
03680 gcc_assert (insn_id && label_id);
03681 return insn_id < label_id;
03682 }
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693 #ifdef LEAF_REGISTERS
03694
03695
03696
03697
03698 int
03699 only_leaf_regs_used (void)
03700 {
03701 int i;
03702 const char *const permitted_reg_in_leaf_functions = LEAF_REGISTERS;
03703
03704 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
03705 if ((regs_ever_live[i] || global_regs[i])
03706 && ! permitted_reg_in_leaf_functions[i])
03707 return 0;
03708
03709 if (current_function_uses_pic_offset_table
03710 && pic_offset_table_rtx != 0
03711 && REG_P (pic_offset_table_rtx)
03712 && ! permitted_reg_in_leaf_functions[REGNO (pic_offset_table_rtx)])
03713 return 0;
03714
03715 return 1;
03716 }
03717
03718
03719
03720
03721 static void
03722 leaf_renumber_regs (rtx first)
03723 {
03724 rtx insn;
03725
03726
03727
03728
03729 for (insn = first; insn; insn = NEXT_INSN (insn))
03730 if (INSN_P (insn))
03731 leaf_renumber_regs_insn (PATTERN (insn));
03732 for (insn = current_function_epilogue_delay_list;
03733 insn;
03734 insn = XEXP (insn, 1))
03735 if (INSN_P (XEXP (insn, 0)))
03736 leaf_renumber_regs_insn (PATTERN (XEXP (insn, 0)));
03737 }
03738
03739
03740
03741
03742 void
03743 leaf_renumber_regs_insn (rtx in_rtx)
03744 {
03745 int i, j;
03746 const char *format_ptr;
03747
03748 if (in_rtx == 0)
03749 return;
03750
03751
03752
03753
03754
03755 if (REG_P (in_rtx))
03756 {
03757 int newreg;
03758
03759
03760 if (in_rtx->used)
03761 return;
03762
03763 newreg = REGNO (in_rtx);
03764
03765
03766 if (newreg >= FIRST_PSEUDO_REGISTER)
03767 {
03768 in_rtx->used = 1;
03769 return;
03770 }
03771 newreg = LEAF_REG_REMAP (newreg);
03772 gcc_assert (newreg >= 0);
03773 regs_ever_live[REGNO (in_rtx)] = 0;
03774 regs_ever_live[newreg] = 1;
03775 REGNO (in_rtx) = newreg;
03776 in_rtx->used = 1;
03777 }
03778
03779 if (INSN_P (in_rtx))
03780 {
03781
03782
03783
03784 leaf_renumber_regs_insn (PATTERN (in_rtx));
03785 return;
03786 }
03787
03788 format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
03789
03790 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
03791 switch (*format_ptr++)
03792 {
03793 case 'e':
03794 leaf_renumber_regs_insn (XEXP (in_rtx, i));
03795 break;
03796
03797 case 'E':
03798 if (NULL != XVEC (in_rtx, i))
03799 {
03800 for (j = 0; j < XVECLEN (in_rtx, i); j++)
03801 leaf_renumber_regs_insn (XVECEXP (in_rtx, i, j));
03802 }
03803 break;
03804
03805 case 'S':
03806 case 's':
03807 case '0':
03808 case 'i':
03809 case 'w':
03810 case 'n':
03811 case 'u':
03812 break;
03813
03814 default:
03815 gcc_unreachable ();
03816 }
03817 }
03818 #endif
03819
03820
03821
03822
03823
03824
03825
03826
03827
03828 int debug_nesting = 0;
03829
03830 static tree *symbol_queue;
03831 int symbol_queue_index = 0;
03832 static int symbol_queue_size = 0;
03833
03834
03835
03836
03837
03838
03839 void
03840 debug_flush_symbol_queue (void)
03841 {
03842 int i;
03843
03844
03845
03846
03847 ++debug_nesting;
03848
03849 for (i = 0; i < symbol_queue_index; ++i)
03850 {
03851
03852
03853
03854
03855
03856 int saved_tree_used = TREE_USED (symbol_queue[i]);
03857 int saved_suppress_debug = TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]);
03858 TREE_USED (symbol_queue[i]) = 1;
03859 TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = 0;
03860
03861 #ifdef DBX_DEBUGGING_INFO
03862 dbxout_symbol (symbol_queue[i], 0);
03863 #endif
03864
03865 TREE_USED (symbol_queue[i]) = saved_tree_used;
03866 TYPE_DECL_SUPPRESS_DEBUG (symbol_queue[i]) = saved_suppress_debug;
03867 }
03868
03869 symbol_queue_index = 0;
03870 --debug_nesting;
03871 }
03872
03873
03874
03875
03876
03877 void
03878 debug_queue_symbol (tree decl)
03879 {
03880 if (symbol_queue_index >= symbol_queue_size)
03881 {
03882 symbol_queue_size += 10;
03883 symbol_queue = xrealloc (symbol_queue,
03884 symbol_queue_size * sizeof (tree));
03885 }
03886
03887 symbol_queue[symbol_queue_index++] = decl;
03888 }
03889
03890
03891 void
03892 debug_free_queue (void)
03893 {
03894 if (symbol_queue)
03895 {
03896 free (symbol_queue);
03897 symbol_queue = NULL;
03898 symbol_queue_size = 0;
03899 }
03900 }
03901
03902
03903 static unsigned int
03904 rest_of_handle_final (void)
03905 {
03906 rtx x;
03907 const char *fnname;
03908
03909
03910
03911
03912 x = DECL_RTL (current_function_decl);
03913 gcc_assert (MEM_P (x));
03914 x = XEXP (x, 0);
03915 gcc_assert (GET_CODE (x) == SYMBOL_REF);
03916 fnname = XSTR (x, 0);
03917
03918 assemble_start_function (current_function_decl, fnname);
03919 final_start_function (get_insns (), asm_out_file, optimize);
03920 final (get_insns (), asm_out_file, optimize);
03921 final_end_function ();
03922
03923 #ifdef TARGET_UNWIND_INFO
03924
03925
03926 output_function_exception_table ();
03927 #endif
03928
03929 assemble_end_function (current_function_decl, fnname);
03930
03931 #ifndef TARGET_UNWIND_INFO
03932
03933 output_function_exception_table ();
03934 #endif
03935
03936 user_defined_section_attribute = false;
03937
03938 if (! quiet_flag)
03939 fflush (asm_out_file);
03940
03941
03942 free_basic_block_vars ();
03943
03944
03945
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955 timevar_push (TV_SYMOUT);
03956 (*debug_hooks->function_decl) (current_function_decl);
03957 timevar_pop (TV_SYMOUT);
03958 return 0;
03959 }
03960
03961 struct tree_opt_pass pass_final =
03962 {
03963 NULL,
03964 NULL,
03965 rest_of_handle_final,
03966 NULL,
03967 NULL,
03968 0,
03969 TV_FINAL,
03970 0,
03971 0,
03972 0,
03973 0,
03974 TODO_ggc_collect,
03975 0
03976 };
03977
03978
03979 static unsigned int
03980 rest_of_handle_shorten_branches (void)
03981 {
03982
03983 shorten_branches (get_insns ());
03984 return 0;
03985 }
03986
03987 struct tree_opt_pass pass_shorten_branches =
03988 {
03989 "shorten",
03990 NULL,
03991 rest_of_handle_shorten_branches,
03992 NULL,
03993 NULL,
03994 0,
03995 TV_FINAL,
03996 0,
03997 0,
03998 0,
03999 0,
04000 TODO_dump_func,
04001 0
04002 };
04003
04004
04005 static unsigned int
04006 rest_of_clean_state (void)
04007 {
04008 rtx insn, next;
04009
04010
04011
04012
04013
04014 for (insn = get_insns (); insn; insn = next)
04015 {
04016 next = NEXT_INSN (insn);
04017 NEXT_INSN (insn) = NULL;
04018 PREV_INSN (insn) = NULL;
04019 }
04020
04021
04022
04023
04024 #ifdef SDB_DEBUGGING_INFO
04025 if (write_symbols == SDB_DEBUG)
04026 sdbout_types (NULL_TREE);
04027 #endif
04028
04029 reload_completed = 0;
04030 epilogue_completed = 0;
04031 flow2_completed = 0;
04032 no_new_pseudos = 0;
04033 #ifdef STACK_REGS
04034 regstack_completed = 0;
04035 #endif
04036
04037
04038
04039 init_insn_lengths ();
04040
04041
04042 init_temp_slots ();
04043
04044 free_basic_block_vars ();
04045 free_bb_for_insn ();
04046
04047
04048 if (targetm.binds_local_p (current_function_decl))
04049 {
04050 int pref = cfun->preferred_stack_boundary;
04051 if (cfun->stack_alignment_needed > cfun->preferred_stack_boundary)
04052 pref = cfun->stack_alignment_needed;
04053 cgraph_rtl_info (current_function_decl)->preferred_incoming_stack_boundary
04054 = pref;
04055 }
04056
04057
04058
04059
04060
04061
04062
04063
04064
04065 init_recog_no_volatile ();
04066
04067
04068 free_after_parsing (cfun);
04069 free_after_compilation (cfun);
04070 return 0;
04071 }
04072
04073 #ifdef KEY
04074 static bool
04075 gate_rest_of_clean_state (void)
04076 {
04077
04078 return flag_spin_file == 0;
04079 }
04080 #endif
04081
04082 struct tree_opt_pass pass_clean_state =
04083 {
04084 NULL,
04085 #ifdef KEY
04086 gate_rest_of_clean_state,
04087 #else
04088 NULL,
04089 #endif
04090 rest_of_clean_state,
04091 NULL,
04092 NULL,
04093 0,
04094 TV_FINAL,
04095 0,
04096 0,
04097 PROP_rtl,
04098 0,
04099 0,
04100 0
04101 };
04102