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