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
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #define __STDC_LIMIT_MACROS
00062 #include <stdint.h>
00063 #include <ctype.h>
00064 #include <fcntl.h>
00065 #include <sys/types.h>
00066 #include <sys/stat.h>
00067 #include <errno.h>
00068 #include <bstring.h>
00069 #include "elf_stuff.h"
00070 #ifdef KEY
00071 #include "dwarf_stuff.h"
00072 #endif
00073 #include <elfaccess.h>
00074 #include <alloca.h>
00075 #include <stdlib.h>
00076 #include <cmplrs/rcodes.h>
00077 #include <stamp.h>
00078 #include <vector>
00079 #if defined(BUILD_OS_DARWIN)
00080 #include <set>
00081 #include <string>
00082 #endif
00083
00084 #define USE_STANDARD_TYPES 1
00085 #include "defs.h"
00086 #include "config.h"
00087 #include "config_asm.h"
00088 #include "config_targ_opt.h"
00089 #include "config_debug.h"
00090 #include "targ_const.h"
00091 #include "strtab.h"
00092 #include "symtab.h"
00093 #include "wn.h"
00094
00095 #include "erglob.h"
00096 #include "erlib.h"
00097 #include "ercg.h"
00098 #include "file_util.h"
00099 #include "flags.h"
00100 #include "glob.h"
00101 #include "xstats.h"
00102 #include "tracing.h"
00103 #include "cgir.h"
00104 #if defined(SHARED_BUILD)
00105 #include "import.h"
00106 #endif
00107 #include "opt_alias_interface.h"
00108 #include "anl_driver.h"
00109 #include "ti_asm.h"
00110 #include "ti_errors.h"
00111 #include "targ_proc_properties.h"
00112 #include "targ_abi_properties.h"
00113 #include "targ_isa_print.h"
00114 #include "targ_isa_enums.h"
00115 #include "targ_isa_pack.h"
00116 #include "targ_isa_bundle.h"
00117 #include "targ_isa_operands.h"
00118
00119 #include "cg.h"
00120 #include "const.h"
00121 #include "whirl2ops.h"
00122 #include "stblock.h"
00123 #include "data_layout.h"
00124 #include "sections.h"
00125 #include "dwarf_DST_mem.h"
00126
00127 #include "calls.h"
00128 #include "cgemit.h"
00129 #include "cgtarget.h"
00130 #include "irbdata.h"
00131 #include "em_elf.h"
00132 #include "cgdwarf.h"
00133 #include "cgdwarf_targ.h"
00134 #include "em_dwarf.h"
00135 #include "tn_set.h"
00136 #include "iface_scn.h"
00137 #include "config_targ.h"
00138 #include "config_list.h"
00139 #include "note.h"
00140 #include "cgexp.h"
00141 #include "eh_region.h"
00142 #include "cg_flags.h"
00143 #include "region_util.h"
00144 #include "cg_region.h"
00145 #include "targ_isa_lits.h"
00146 #include "freq.h"
00147 #include "vstring.h"
00148 #include "label_util.h"
00149 #include "cgemit_targ.h"
00150 #include "cg_swp.h"
00151 #include "tag.h"
00152 #include "be_symtab.h"
00153 #if defined(TARG_MIPS) && !defined(TARG_SL)
00154 #include "MIPS/cg_sas.h"
00155 #endif
00156
00157 #ifdef TARG_IA64
00158 #include "targ_issue_port.h"
00159 #include "cggrp_microsched.h"
00160 #include "val_prof.h"
00161 #endif
00162
00163 #include "be_util.h"
00164 #include "dwarf_stuff.h"
00165 extern "C" {
00166 #include "pro_encode_nm.h"
00167 }
00168
00169 #ifdef KEY
00170 #include "config_lno.h"
00171 #include "config_opt.h"
00172 #endif
00173
00174 #ifdef TARG_SL
00175 #include "disp_instr.h"
00176 #endif
00177
00178 #ifdef TARG_X8664
00179 #include "be_util.h"
00180 extern void EETARG_Emit_IP_Calc_Func(void);
00181 #endif
00182
00183 extern void Early_Terminate (INT status);
00184
00185 #define PAD_SIZE_LIMIT 2048
00186
00187
00188
00189
00190 #define LBUF_LEN (OP_MAX_FIXED_OPNDS*1024)
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 enum { IHOT=FALSE, ICOLD=TRUE };
00202
00203
00204
00205
00206 #define BB_cold BB_local_flag1
00207 #define Set_BB_cold Set_BB_local_flag1
00208 #define Reset_BB_cold Reset_BB_local_flag1
00209
00210 extern const char __Release_ID[];
00211 #ifdef KEY
00212 extern BOOL profile_arcs;
00213 extern BOOL PU_has_trampoline;
00214 #endif
00215
00216
00217
00218
00219
00220
00221
00222
00223 #if defined(TARG_IA64)
00224 BOOL CG_emit_asm_dwarf = TRUE;
00225 BOOL CG_emit_unwind_info = TRUE;
00226 BOOL CG_emit_unwind_directives = TRUE;
00227 #elif defined(TARG_NVISA)
00228 BOOL CG_emit_asm_dwarf = FALSE;
00229 BOOL CG_emit_unwind_info = FALSE;
00230 BOOL CG_emit_unwind_directives = FALSE;
00231 #else
00232 BOOL CG_emit_asm_dwarf = TRUE;
00233 BOOL CG_emit_unwind_info = TRUE;
00234 BOOL CG_emit_unwind_info_Set = FALSE;
00235 BOOL CG_emit_unwind_directives = FALSE;
00236 #endif
00237
00238 #ifdef KEY
00239 BOOL CG_emit_non_gas_syntax = FALSE;
00240 #ifdef TARG_NVISA
00241 BOOL CG_inhibit_size_directive = TRUE;
00242 #else
00243 BOOL CG_inhibit_size_directive = FALSE;
00244 #endif
00245 #endif
00246
00247 #ifndef TARG_NVISA
00248
00249 #define EMIT_DATA_SECTIONS
00250 #endif
00251
00252 static BOOL generate_dwarf = FALSE;
00253 static BOOL generate_elf_symbols = FALSE;
00254
00255
00256 static BOOL Trace_Init = FALSE;
00257 static BOOL Trace_Inst = FALSE;
00258 static BOOL Trace_Elf = FALSE;
00259 static BOOL Trace_Longbr = FALSE;
00260
00261 BOOL Use_Page_Zero = FALSE;
00262 static BOOL Use_Prefetch = FALSE;
00263
00264
00265
00266
00267
00268 static LABEL_IDX Last_Label = LABEL_IDX_ZERO;
00269 static INT32 Offset_From_Last_Label = 0;
00270
00271 static LABEL_IDX Initial_Pu_Label;
00272
00273
00274
00275
00276 static INT32 PC = 0;
00277 static INT32 text_PC = 0;
00278 static INT32 cold_PC = 0;
00279
00280 static ST *PU_base = NULL;
00281 static ST *text_base = NULL;
00282 static ST *cold_base = NULL;
00283
00284 static pSCNINFO PU_section = NULL;
00285 static pSCNINFO text_section = NULL;
00286 static pSCNINFO cold_section = NULL;
00287
00288 #if defined(TARG_SL)
00289 static BOOL Trace_PC = FALSE;
00290 static BOOL trace_pc = FALSE;
00291 #endif
00292
00293 static INT current_rid = 0;
00294
00295 typedef struct {
00296 pSCNINFO scninfo;
00297 Elf64_Word scn_ofst;
00298 ST *sym;
00299 } AUX_SCN;
00300
00301 static AUX_SCN *em_scn;
00302 static INT last_scn = 0;
00303 static INT max_scn = 0;
00304
00305
00306 static ST *cur_section = NULL;
00307
00308 static PU_IDX current_pu = 0;
00309
00310
00311
00312 #define Use_Separate_PU_Section(pu,st) \
00313 ((pu != (PU_IDX) NULL) \
00314 && (Section_For_Each_Function || PU_in_elf_section(pu)) \
00315 && (ST_class(st) == CLASS_BLOCK) \
00316 && (strcmp(ST_name(st),ELF_TEXT) == 0))
00317
00318 static FILE *anl_file;
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 #define MAX_SYMTAB_DEPTH 6
00339
00340 static INT32 *elf_index_array[MAX_SYMTAB_DEPTH] =
00341 {NULL,NULL,NULL,NULL,NULL,NULL};
00342 static INT max_elf_index[MAX_SYMTAB_DEPTH] = {0,0,0,0,0,0};
00343
00344 #ifdef TARG_SL
00345 vector<UINT32> *mvtcop = NULL;
00346 vector<UINT32> *mvfcop = NULL;
00347 static int using_section = -1;
00348 #endif
00349
00350 #if defined(BUILD_OS_DARWIN)
00351
00352
00353
00354
00355
00356
00357 static void
00358 emit_section_directive(ST *base) {
00359 char *name = ST_name(base);
00360 if (strcmp(name, BSS_RAW_NAME)) {
00361 fprintf ( Asm_File, "\n\t%s %s\n", AS_SECTION, map_section_name(name));
00362 }
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 static char *
00377 underscorify(char *name, darwin_indirect_t which = DO_UNDERSCORE) {
00378 static char *underscorify_buffer = 0;
00379 static unsigned underscorify_len = 0;
00380
00381
00382 if (*name == '.') {
00383 return name;
00384 }
00385
00386 unsigned name_len = strlen(name);
00387 const char *pattern = "%s";
00388 switch (which) {
00389 case DO_UNDERSCORE:
00390 pattern = "_%s";
00391 break;
00392 case DO_STUB:
00393 pattern = "L_%s$stub";
00394 break;
00395 case DO_NON_LAZY_PTR:
00396 pattern = "L_%s$non_lazy_ptr";
00397 break;
00398 }
00399 unsigned int sizeof_pattern = strlen(pattern) + sizeof '\0';
00400 if (name_len + sizeof_pattern > underscorify_len) {
00401 free(underscorify_buffer);
00402 underscorify_buffer = (char *) malloc(2 * name_len + sizeof_pattern);
00403 }
00404 sprintf(underscorify_buffer, pattern, name);
00405 return underscorify_buffer;
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415 static void
00416 gen_indirect(char *name, darwin_indirect_t which) {
00417 static std::set<std::string> already_generated_jump;
00418 static std::set<std::string> already_generated_ptr;
00419 std::string sname(name);
00420
00421 if (DO_STUB == which) {
00422 if (!already_generated_jump.insert(sname).second) {
00423 return;
00424 }
00425 fprintf(Asm_File, "\t.section __IMPORT,__jump_table,symbol_stubs,"
00426 "self_modifying_code+pure_instructions,5\n");
00427 fprintf(Asm_File, "%s:\n", underscorify(name, which));
00428 fprintf(Asm_File, "\t.indirect_symbol %s\n", underscorify(name,
00429 DO_UNDERSCORE));
00430 fprintf(Asm_File, "\thlt; hlt; hlt; hlt; hlt;\n");
00431 } else if (DO_NON_LAZY_PTR == which) {
00432 if (!already_generated_ptr.insert(sname).second) {
00433 return;
00434 }
00435 fprintf(Asm_File, "\t.section __IMPORT,__pointers,"
00436 "non_lazy_symbol_pointers\n");
00437 fprintf(Asm_File, "%s:\n", underscorify(name, which));
00438 fprintf(Asm_File, "\t.indirect_symbol %s\n", underscorify(name,
00439 DO_UNDERSCORE));
00440 fprintf(Asm_File, "\t.long 0\n");
00441 }
00442 fprintf(Asm_File, "\t%s __TEXT,__text\n", AS_SECTION);
00443 }
00444
00445
00446
00447 int
00448 logtwo(int value)
00449 {
00450 int result = 0;
00451 for (; value > 1; value >>= 1) {
00452 result++;
00453 }
00454 return result;
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 struct darwin_remember {
00467 char *name;
00468 UINT64 offset;
00469
00470 darwin_remember(char *name_, UINT64 offset_): name(strdup(name_)),
00471 offset(offset_) {}
00472 ~darwin_remember() { free(name); }
00473 private:
00474 darwin_remember(darwin_remember &) {}
00475 };
00476
00477 class darwin_bss {
00478 static vector< darwin_remember * > revisit_bss_list;
00479 static UINT64 revisit_bss_size;
00480 static unsigned revisit_bss_maxalign;
00481 static vstring &qualified_name(vstring &, ST *);
00482
00483 static UINT64 update_bss_size(ST *, UINT64 *, unsigned * = 0);
00484
00485 public:
00486
00487 static void remember_bss_symbol(ST *);
00488 static void finish_bss_symbols(FILE *);
00489 };
00490
00491 vector< darwin_remember * > darwin_bss::revisit_bss_list;
00492 UINT64 darwin_bss::revisit_bss_size;
00493 unsigned darwin_bss::revisit_bss_maxalign;
00494
00495
00496 vstring &
00497 darwin_bss::qualified_name(vstring &v, ST *st) {
00498
00499 if (0 == ST_name(st) || 0 == *(ST_name(st))) {
00500 return v;
00501 }
00502 vstr_concat(v, underscorify(ST_name(st)));
00503
00504 if (!strncmp (ST_name(st), ".range_table.", strlen(".range_table."))) {
00505 return v;
00506 }
00507
00508 if ( ST_is_export_local(st) && ST_class(st) == CLASS_VAR) {
00509 if (ST_level(st) == GLOBAL_SYMTAB)
00510 vstr_sprintf(&v, vstr_len(v), "%s%d",
00511 Label_Name_Separator, ST_index(st));
00512 else
00513 vstr_sprintf(&v, vstr_len(v), "%s%d%s%d", Label_Name_Separator,
00514 ST_pu(Get_Current_PU_ST()), Label_Name_Separator, ST_index(st) );
00515 }
00516 else if (*Symbol_Name_Suffix) {
00517 vstr_concat(v, Symbol_Name_Suffix);
00518 }
00519 return v;
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530 UINT64
00531 darwin_bss::update_bss_size(ST *sym, UINT64 *accum_size, unsigned *maxalign) {
00532 UINT64 save_accum_size = *accum_size;
00533 UINT64 size = TY_size(ST_type(sym));
00534 unsigned align = TY_align(ST_type(sym));
00535 unsigned modalign = save_accum_size % align;
00536 unsigned pad = modalign ? (align - modalign) : 0;
00537 if (maxalign) {
00538 *maxalign = MAX(align, (*maxalign));
00539 }
00540 *accum_size += (size + modalign);
00541 return save_accum_size + pad;
00542 }
00543
00544
00545
00546
00547
00548
00549 void
00550 darwin_bss::remember_bss_symbol(ST *sym) {
00551
00552 vstring v = vstr_begin(64);
00553 char *name = vstr_str(qualified_name(v, sym));
00554 revisit_bss_list.push_back(new darwin_remember(name,
00555 update_bss_size(sym, &revisit_bss_size, &revisit_bss_maxalign)));
00556 vstr_end(v);
00557 }
00558
00559
00560
00561
00562
00563
00564
00565 void
00566 darwin_bss::finish_bss_symbols(FILE *asm_file) {
00567 fprintf(asm_file, "\t.lcomm %s, %lld, %d\n",
00568 BSS_RAW_NAME, revisit_bss_size, logtwo(revisit_bss_maxalign));
00569 UINT64 accum_size = 0;
00570 for (vector< darwin_remember * >::iterator bi = revisit_bss_list.begin();
00571 bi != revisit_bss_list.end(); ++bi) {
00572 darwin_remember *r = *bi;
00573 fprintf(asm_file, "\t.set %s, %s+%lld\n",
00574 r->name, BSS_RAW_NAME, r->offset);
00575 delete r;
00576 }
00577 revisit_bss_size = 0;
00578 revisit_bss_maxalign = 0;
00579 revisit_bss_list.clear();
00580 }
00581 #endif
00582
00583 static void
00584 Allocate_Elf_Index_Space (UINT level)
00585 {
00586 INT num_sts = ST_Table_Size(level);
00587
00588 if (elf_index_array[level] == NULL) {
00589 max_elf_index[level] = num_sts + 100;
00590
00591 elf_index_array[level] = (INT32*) Src_Alloc(
00592 sizeof(INT32) * max_elf_index[level]);
00593 } else if (max_elf_index[level] < num_sts + 10) {
00594
00595
00596
00597 elf_index_array[level] = TYPE_MEM_POOL_REALLOC_N (INT32,
00598 &MEM_src_pool, elf_index_array[level],
00599 max_elf_index[level], num_sts + 100);
00600 max_elf_index[level] = num_sts + 100;
00601 }
00602 }
00603
00604 static void
00605 Init_ST_elf_index (UINT stab)
00606 {
00607 UINT level = stab;
00608 INT i;
00609 Allocate_Elf_Index_Space(GLOBAL_SYMTAB);
00610 Is_True((level < MAX_SYMTAB_DEPTH),
00611 ("Init_ST_elf_index overflow"));
00612 if (level > GLOBAL_SYMTAB && elf_index_array[level] != NULL) {
00613
00614
00615 for (i = 0; i < max_elf_index[level]; i++) {
00616 elf_index_array[level][i] = 0;
00617 }
00618 }
00619 Allocate_Elf_Index_Space(stab);
00620 }
00621
00622 static INT32
00623 ST_elf_index (ST *st)
00624 {
00625 INT level = ST_level(st);
00626 Is_True((level < MAX_SYMTAB_DEPTH),
00627 ("ST_elf_index overflow"));
00628 Is_True((ST_index(st) < max_elf_index[level]),
00629 ("ST_elf_index overflow"));
00630 return elf_index_array[level][ST_index(st)];
00631 }
00632
00633 static void
00634 Set_ST_elf_index (ST *st, INT32 v)
00635 {
00636 INT level = ST_level(st);
00637 Is_True((level < MAX_SYMTAB_DEPTH),
00638 ("Set_ST_elf_index overflow"));
00639 Is_True((ST_index(st) < max_elf_index[level]),
00640 ("Set_ST_elf_index overflow"));
00641 elf_index_array[level][ST_index(st)] = v;
00642 }
00643
00644
00645 static BOOL
00646 ST_is_gp_relative(ST *st)
00647 {
00648 ST *base_st = Base_Symbol (st);
00649
00650 return ((ST_class(base_st) == CLASS_BLOCK ||
00651 ST_class(base_st) == CLASS_VAR) &&
00652 ST_gprel(base_st));
00653 }
00654
00655
00656 #define Is_Text_Section(st) (STB_exec(st) && strncmp(ST_name(st), ELF_TEXT,5)==0)
00657
00658 static void
00659 Init_Section (ST *st)
00660 {
00661 Elf64_Word scn_type;
00662 Elf64_Word scn_flags;
00663 Elf64_Xword scn_entsize;
00664
00665 if (ST_elf_index(st) != 0) {
00666
00667 return;
00668 }
00669 if (last_scn >= (max_scn-1)) {
00670
00671 max_scn += 30;
00672 if (em_scn == NULL)
00673 em_scn = (AUX_SCN *)Src_Alloc(sizeof(AUX_SCN)*max_scn);
00674 else
00675 em_scn = TYPE_MEM_POOL_REALLOC_N (AUX_SCN,
00676 &MEM_src_pool, em_scn, (max_scn-30), max_scn);
00677 }
00678 last_scn++;
00679 Set_STB_scninfo_idx(st, last_scn);
00680
00681
00682 if (Is_Text_Section(st)) {
00683 #if defined(TARG_SL)
00684 text_base = st;
00685 #endif
00686 if (Align_Instructions)
00687 Set_STB_align(st, Align_Instructions);
00688 else if (OPT_Space
00689 #ifdef TARG_SL
00690 && !CG_check_quadword
00691 #endif
00692 )
00693 Set_STB_align(st, INST_BYTES);
00694 else
00695 Set_STB_align(st, CGTARG_Text_Alignment());
00696 }
00697 #ifdef TARG_SL
00698
00699 else if (STB_exec(st) && (ST_sclass(st) == SCLASS_TEXT)) {
00700 Set_STB_align(st, CGTARG_Text_Alignment());
00701 }
00702 #endif
00703
00704 em_scn[last_scn].sym = st;
00705
00706 scn_type = Get_Section_Elf_Type(STB_section_idx(st));
00707 scn_flags = Get_Section_Elf_Flags(STB_section_idx(st));
00708 if (Is_Text_Section(st) &&
00709 current_pu != (PU_IDX) NULL && PU_in_elf_section(current_pu))
00710 {
00711 scn_flags |= SHF_MIPS_NODUPE;
00712 }
00713
00714 scn_entsize = Get_Section_Elf_Entsize(STB_section_idx(st));
00715
00716 if (generate_elf_symbols) {
00717 em_scn[last_scn].scninfo = Em_New_Section (ST_name(st),
00718 scn_type, scn_flags, scn_entsize, STB_align(st));
00719
00720
00721 if (!STB_nobits(st)) {
00722 Em_New_Data_Buffer (em_scn[last_scn].scninfo,
00723 STB_size(st) + 100, 1);
00724 }
00725 Set_ST_elf_index(st,
00726 Em_Create_Section_Symbol (em_scn[last_scn].scninfo));
00727 }
00728 else {
00729
00730 Set_ST_elf_index(st, 1);
00731 }
00732
00733 if (Assembly) {
00734 #if defined(TARG_MIPS) || defined(TARG_X8664) || defined(TARG_NVISA)
00735 CGEMIT_Prn_Scn_In_Asm(st, cur_section);
00736 #else
00737 CGEMIT_Prn_Scn_In_Asm(st, scn_type, scn_flags, scn_entsize, cur_section);
00738 #endif
00739 #ifdef TARG_MIPS
00740 UINT32 tmp, power;
00741 power = 0;
00742 #ifdef TARG_SL
00743 if (!strncmp(ST_name(st),".gnu.linkonce",13) && (CG_check_quadword)) {
00744 power = 4;
00745 }
00746 else
00747 #endif
00748 for (tmp = STB_align(st); tmp > 1; tmp >>= 1) power++;
00749 fprintf(Asm_File, "\t%s\t%d\n", AS_ALIGN, power);
00750 #endif
00751 }
00752 }
00753
00754 static unsigned char
00755 st_other_for_sym (ST *sym)
00756 {
00757 unsigned char symother;
00758
00759 switch (ST_export(sym)) {
00760 case EXPORT_HIDDEN:
00761 symother = STO_HIDDEN;
00762 break;
00763 case EXPORT_PROTECTED:
00764 symother = STO_PROTECTED;
00765 break;
00766 case EXPORT_INTERNAL:
00767 symother = STO_INTERNAL;
00768 break;
00769 case EXPORT_OPTIONAL:
00770 symother = STO_OPTIONAL;
00771 break;
00772 default:
00773 symother = STO_DEFAULT;
00774 break;
00775 }
00776 return symother;
00777 }
00778
00779 static INT64
00780 Get_Offset_From_Full (ST *sym)
00781 {
00782
00783
00784
00785
00786
00787 char *offset_string;
00788 offset_string = strrchr (ST_name(sym), '.');
00789 FmtAssert(offset_string != NULL, ("Get_Offset_From_Full unexpected name format (%s)", ST_name(sym)));
00790 offset_string++;
00791 return atoll(offset_string);
00792 }
00793
00794
00795
00796 static void
00797 add_reloc_type (Elf64_AltRela *preloc, unsigned char reloc_type, pSCNINFO scn)
00798 {
00799 if (REL64_type3(*preloc) != 0) {
00800 Elf64_Addr sv_offset = REL_offset(*preloc);
00801 Em_Add_New_Composite_Rela (preloc, scn);
00802 #ifdef TARG_IA64
00803 BZERO (preloc, sizeof (Elf64_AltRela));
00804 #else
00805 BZERO (preloc, sizeof (Elf64_Rela));
00806 #endif
00807 REL_offset(*preloc) = sv_offset;
00808 REL64_type(*preloc) = reloc_type;
00809 }
00810 else if (REL64_type2(*preloc) != 0) {
00811 REL64_type3(*preloc) = reloc_type;
00812 }
00813 else if (REL64_type(*preloc) != 0) {
00814 REL64_type2(*preloc) = reloc_type;
00815 }
00816 else {
00817 REL64_type(*preloc) = reloc_type;
00818 }
00819 }
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840 inline INT32 PC_Bundle(INT32 pc)
00841 {
00842 return pc & ~(INST_BYTES - 1);
00843 }
00844
00845
00846
00847 inline INT32 PC_Slot(INT32 pc)
00848 {
00849 return pc & (INST_BYTES - 1);
00850 }
00851
00852
00853
00854
00855 inline INT32 PC_Incr(INT32 pc)
00856 {
00857 ++pc;
00858
00859 if (PC_Slot(pc) == ISA_MAX_SLOTS) {
00860 pc += INST_BYTES - ISA_MAX_SLOTS;
00861 }
00862
00863 return pc;
00864 }
00865
00866
00867
00868 inline INT32 PC_Incr_N(INT32 pc, UINT32 incr)
00869 {
00870 #if defined(TARG_SL)
00871 pc = pc + (2*incr);
00872 #else
00873 UINT slots = PC_Slot(pc) + incr;
00874 UINT bundles = slots / ISA_MAX_SLOTS;
00875 pc = PC_Bundle(pc) + (bundles * INST_BYTES) + (slots % ISA_MAX_SLOTS);
00876 #endif
00877 return pc;
00878 }
00879
00880 void
00881 EMT_Write_Qualified_Name (FILE *f, ST *st)
00882 {
00883 if (ST_name(st) && *(ST_name(st)) != '\0') {
00884 #if defined(BUILD_OS_DARWIN)
00885 fputs(underscorify(ST_name(st)), f);
00886 #else
00887 fputs(ST_name(st), f);
00888 #endif
00889 #if defined(KEY) && !defined(TARG_NVISA)
00890
00891 if (!strncmp (ST_name(st), ".range_table.", strlen(".range_table.")))
00892 return;
00893 #endif // KEY
00894 if ( ST_is_export_local(st) && ST_class(st) == CLASS_VAR) {
00895
00896
00897
00898
00899 if (ST_level(st) == GLOBAL_SYMTAB) {
00900 #ifdef KEY
00901
00902 if (Emit_Global_Data || ST_sclass(st) == SCLASS_PSTATIC)
00903 #endif
00904 fprintf (f, "%s%d", Label_Name_Separator, ST_index(st));
00905 }
00906 else
00907 fprintf (f, "%s%d%s%d", Label_Name_Separator,
00908 ST_pu(Get_Current_PU_ST()),
00909 Label_Name_Separator, ST_index(st) );
00910 }
00911 else if (*Symbol_Name_Suffix != '\0') {
00912 fputs(Symbol_Name_Suffix, f);
00913 }
00914 } else {
00915 fprintf (f, "%s %+lld", ST_name(ST_base(st)), ST_ofst(st));
00916 }
00917 }
00918
00919
00920 static void Print_Dynsym (FILE *pfile, ST *st)
00921 {
00922 const char* x = AS_DYNSYM;
00923 if (x) {
00924 fprintf (pfile, "\t%s\t", x);
00925 EMT_Write_Qualified_Name (pfile, st);
00926 switch (ST_export(st)) {
00927 case EXPORT_INTERNAL:
00928 fputs ("\tsto_internal\n", pfile);
00929 break;
00930 case EXPORT_HIDDEN:
00931 fputs ("\tsto_hidden\n", pfile);
00932 break;
00933 case EXPORT_PROTECTED:
00934 fputs ("\tsto_protected\n", pfile);
00935 break;
00936 case EXPORT_OPTIONAL:
00937 fputs ("\tsto_optional\n", pfile);
00938 break;
00939 default:
00940 fputs ("\tsto_default\n", pfile);
00941 break;
00942 }
00943 }
00944 }
00945
00946 static void Print_Label (FILE *pfile, ST *st, INT64 size)
00947 {
00948 ST *base_st;
00949 INT64 base_ofst;
00950
00951 if (ST_is_weak_symbol(st)) {
00952 fprintf ( pfile, "\t%s\t", AS_WEAK);
00953 EMT_Write_Qualified_Name(pfile, st);
00954 fputc ('\n', pfile);
00955 #ifdef KEY // bug 12145: write .hidden
00956 if (ST_export(st) == EXPORT_HIDDEN) {
00957 fprintf ( pfile, "\t.hidden\t");
00958 EMT_Write_Qualified_Name(pfile, st);
00959 fputc ('\n', pfile);
00960 }
00961 #endif
00962 }
00963 else if (!ST_is_export_local(st)) {
00964 fprintf ( pfile, "\t%s\t", AS_GLOBAL);
00965 EMT_Write_Qualified_Name(pfile, st);
00966 fputc ('\n', pfile);
00967 }
00968 #if (defined(TARG_X8664) || defined(TARG_NVISA)) && !defined(BUILD_OS_DARWIN)
00969
00970
00971 if (ST_class(st) == CLASS_FUNC) {
00972 fprintf ( pfile, "\t%s\t", AS_TYPE);
00973 EMT_Write_Qualified_Name(pfile, st);
00974 fprintf ( pfile, ", %s\n", AS_TYPE_FUNC);
00975 }
00976 #endif
00977 if (ST_class(st) == CLASS_VAR
00978 #if defined(BUILD_OS_DARWIN)
00979 && 0
00980 #endif
00981 #ifdef TARG_MIPS
00982 && !CG_emit_non_gas_syntax
00983 #endif
00984 ) {
00985 fprintf (pfile, "\t%s\t", AS_TYPE);
00986 EMT_Write_Qualified_Name (pfile, st);
00987 fprintf (pfile, ", %s\n", AS_TYPE_OBJECT);
00988 }
00989
00990 #if !defined(BUILD_OS_DARWIN)
00991 if (size != 0
00992 #if !defined(TARG_IA64)
00993 && !CG_inhibit_size_directive
00994 #endif
00995 ) {
00996
00997 fprintf ( pfile, "\t%s\t", AS_SIZE);
00998 EMT_Write_Qualified_Name(pfile, st);
00999 fprintf ( pfile, ", %" LL_FORMAT "d\n", size);
01000 }
01001 #endif
01002 Base_Symbol_And_Offset (st, &base_st, &base_ofst);
01003 EMT_Write_Qualified_Name (pfile, st);
01004 fprintf ( pfile, ":\t%s 0x%" LL_FORMAT "x\n", ASM_CMNT, base_ofst);
01005 Print_Dynsym (pfile, st);
01006 }
01007
01008 static void
01009 Print_Common (FILE *pfile, ST *st)
01010 {
01011 ST *base_st;
01012 INT64 base_ofst;
01013 Base_Symbol_And_Offset (st, &base_st, &base_ofst);
01014 if (st != base_st && ST_sclass(base_st) == SCLASS_COMMON) {
01015
01016 if (ST_elf_index(base_st) == 0) {
01017 Print_Common (pfile, base_st);
01018 }
01019 return;
01020 }
01021
01022 if (TY_size(ST_type(st)) > 0) {
01023
01024 if (ST_is_weak_symbol(st)) {
01025 fprintf ( pfile, "\t%s\t", AS_WEAK);
01026 EMT_Write_Qualified_Name(pfile, st);
01027 fputc ('\n', pfile);
01028 }
01029 #ifdef TARG_NVISA
01030 CGEMIT_Print_Variable(st);
01031 #else
01032 fprintf ( pfile, "\t%s\t", AS_COM);
01033 EMT_Write_Qualified_Name(pfile, st);
01034 #ifdef TARG_X8664
01035 #if defined(BUILD_OS_DARWIN)
01036 fprintf ( pfile, ", %" LL_FORMAT "d\n", TY_size(ST_type(st)));
01037 #else
01038 if (LNO_Run_Simd && Simd_Align && TY_size(ST_type(st)) >= 16)
01039 fprintf ( pfile, ", %" LL_FORMAT "d, 16\n", TY_size(ST_type(st)));
01040 else
01041 fprintf ( pfile, ", %" LL_FORMAT "d, %d\n",
01042 TY_size(ST_type(st)), TY_align(ST_type(st)));
01043 #endif
01044 #else
01045 fprintf ( pfile, ", %" LL_FORMAT "d, %d\n",
01046 TY_size(ST_type(st)), TY_align(ST_type(st)));
01047 #endif
01048 Print_Dynsym (pfile, st);
01049 #endif // TARG_NVISA
01050
01051 if (!generate_elf_symbols) Set_ST_elf_index(st, 1);
01052 }
01053 #ifdef KEY
01054 else {
01055
01056
01057
01058
01059
01060
01061 fprintf ( pfile, "\t%s\t", AS_COM);
01062 EMT_Write_Qualified_Name(pfile, st);
01063 #if defined(BUILD_OS_DARWIN)
01064 fputs (", 1\n", pfile);
01065 #else
01066 fputs (", 1, 1\n", pfile);
01067 #endif
01068 }
01069 #endif
01070 }
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081 #if defined(BUILD_OS_DARWIN)
01082
01083
01084
01085
01086
01087
01088 mINT32 EMT_Put_Elf_Symbol (ST *sym, darwin_indirect_t which)
01089 #else
01090 mINT32 EMT_Put_Elf_Symbol (ST *sym)
01091 #endif
01092 {
01093 unsigned char symbind;
01094 unsigned char symother;
01095 Elf64_Word symindex;
01096 TY_IDX sym_type;
01097 ST *base_st;
01098 INT64 base_ofst = 0;
01099 ST_SCLASS sclass;
01100
01101 symindex = ST_elf_index(sym);
01102
01103
01104 #ifdef TARG_IA64
01105 if (symindex != 0) return symindex;
01106 #else
01107 if (symindex != 0 &&
01108 (!LNO_Run_Simd || !Simd_Align))
01109 return symindex;
01110 #endif
01111
01112 if ( Trace_Elf ) {
01113 #pragma mips_frequency_hint NEVER
01114 fprintf ( TFile, "EMT_Put_Elf_Symbol:\n" );
01115 Print_ST ( TFile, sym, FALSE );
01116 }
01117 if ( ! generate_elf_symbols) {
01118
01119
01120 if (ST_class(sym) == CLASS_FUNC
01121 #if defined(BUILD_OS_DARWIN)
01122 && 0
01123 #endif
01124 #ifdef TARG_MIPS
01125 && !CG_emit_non_gas_syntax
01126 #endif
01127 ) {
01128 #ifndef TARG_NVISA // ptx should already have .func info
01129 fprintf (Asm_File, "\t%s\t", AS_TYPE);
01130 EMT_Write_Qualified_Name (Asm_File, sym);
01131 fprintf (Asm_File, ", %s\n", AS_TYPE_FUNC);
01132 #endif
01133 }
01134 else if (ST_class(sym) == CLASS_VAR && ST_sclass(sym) == SCLASS_COMMON) {
01135 Print_Common (Asm_File, sym);
01136 }
01137 Set_ST_elf_index(sym, 1);
01138 return 0;
01139 }
01140 #ifndef TARG_IA64
01141 #ifdef Is_True_On
01142 if (! profile_arcs || strncmp(ST_name(sym), "LPBX", 4) != 0)
01143 #endif
01144 #endif
01145 Is_True (!ST_is_not_used(sym) || ST_emit_symbol(sym),
01146 ("Reference to not_used symbol (%s)", ST_name(sym)));
01147
01148
01149 if (ST_is_weak_symbol(sym)) {
01150 symbind = STB_WEAK;
01151 }
01152 else if (ST_is_export_local(sym)) {
01153 symbind = STB_LOCAL;
01154 }
01155 else {
01156 symbind = STB_GLOBAL;
01157 }
01158
01159 symother = st_other_for_sym (sym);
01160
01161 Base_Symbol_And_Offset (sym, &base_st, &base_ofst);
01162
01163 if (ST_class(base_st) == CLASS_BLOCK && STB_section(base_st)
01164 && ST_elf_index(base_st) == 0)
01165 {
01166 Init_Section(base_st);
01167 }
01168
01169 if (ST_is_weak_symbol(sym) && ST_sclass(base_st) == SCLASS_EXTERN) {
01170
01171
01172 sclass = ST_sclass(base_st);
01173 }
01174 else {
01175 sclass = ST_sclass(sym);
01176 }
01177 switch (ST_class(sym)) {
01178 case CLASS_VAR:
01179 sym_type = ST_type(sym);
01180 switch (sclass) {
01181 case SCLASS_FSTATIC:
01182 #ifdef TARG_NVISA
01183
01184
01185
01186 case SCLASS_PSTATIC:
01187 #endif
01188 case SCLASS_DGLOBAL:
01189 case SCLASS_UGLOBAL:
01190 #ifdef KEY
01191 case SCLASS_EH_REGION:
01192 #endif // KEY
01193 symindex = Em_Add_New_Symbol (
01194 ST_name(sym), base_ofst, TY_size(sym_type),
01195 symbind, STT_OBJECT, symother,
01196 Em_Get_Section_Index (em_scn[STB_scninfo_idx(base_st)].scninfo));
01197 break;
01198 case SCLASS_EXTERN:
01199 symindex = Em_Add_New_Symbol (
01200 ST_name(sym), 0, TY_size(sym_type),
01201 symbind, STT_OBJECT, symother,
01202 ST_is_gp_relative(sym) ? SHN_MIPS_SUNDEFINED : SHN_UNDEF);
01203
01204 if (Assembly)
01205 if (ST_is_weak_symbol(sym)) {
01206 fprintf ( Asm_File, "\t%s\t", AS_WEAK);
01207 EMT_Write_Qualified_Name(Asm_File, sym);
01208 fputc ('\n', Asm_File);
01209 }
01210 else {
01211 #if defined(BUILD_OS_DARWIN)
01212
01213 if (DO_UNDERSCORE != which) {
01214 fprintf(Asm_File, "\t%s\t%s\n", AS_GLOBAL,
01215 underscorify(ST_name(sym)));
01216 }
01217 #else
01218 fprintf(Asm_File, "\t%s\t%s\n", AS_GLOBAL, ST_name(sym));
01219 #endif
01220 }
01221 break;
01222 case SCLASS_COMMON:
01223 if (sym != base_st && ST_sclass(base_st) == SCLASS_COMMON) {
01224
01225 return EMT_Put_Elf_Symbol (base_st);
01226 }
01227 if (Assembly) {
01228 Print_Common (Asm_File, sym);
01229 }
01230 if (generate_elf_symbols) {
01231 if (ST_is_split_common(sym)) {
01232 symbind = STB_SPLIT_COMMON;
01233 symother = STO_SC_ALIGN_UNUSED;
01234 symindex = Em_Add_New_Symbol (
01235 ST_name(sym), Get_Offset_From_Full(sym), TY_size(sym_type),
01236 symbind, STT_OBJECT, symother,
01237 EMT_Put_Elf_Symbol (ST_full(sym)) );
01238 }
01239 else {
01240 Elf64_Half symshndx;
01241 if (ST_is_thread_local(sym)) symshndx = SHN_MIPS_LCOMMON;
01242 else if (ST_is_gp_relative(sym)) symshndx = SHN_MIPS_SCOMMON;
01243 else symshndx = SHN_COMMON;
01244 symindex = Em_Add_New_Symbol (
01245 ST_name(sym), TY_align(sym_type), TY_size(sym_type),
01246 symbind, STT_OBJECT, symother, symshndx);
01247 }
01248 }
01249 break;
01250 #ifdef TARG_NVISA
01251
01252 case SCLASS_FORMAL:
01253 symindex = Em_Add_New_Symbol (
01254 ST_name(sym), TY_align(sym_type), TY_size(sym_type),
01255 STB_LOCAL, STT_OBJECT, symother, SHN_COMMON);
01256 break;
01257 #endif
01258 case SCLASS_UNKNOWN:
01259 default:
01260 break;
01261 }
01262 break;
01263
01264 case CLASS_NAME:
01265 if (ST_emit_symbol(sym)) {
01266
01267 symindex = Em_Add_New_Symbol (
01268 ST_name(sym), 0, 0,
01269 STB_LOCAL, STT_NOTYPE, symother, SHN_UNDEF);
01270
01271 }
01272 break;
01273
01274 case CLASS_FUNC:
01275 if (sclass == SCLASS_EXTERN) {
01276 symindex = Em_Add_New_Undef_Symbol (
01277 ST_name(sym), symbind, STT_FUNC, symother);
01278 if (Assembly) {
01279 if (ST_is_weak_symbol(sym)) {
01280 fprintf ( Asm_File, "\t%s\t", AS_WEAK);
01281 EMT_Write_Qualified_Name(Asm_File, sym);
01282 fputc ('\n', Asm_File);
01283 }
01284 else
01285 #if defined(BUILD_OS_DARWIN)
01286
01287 if (DO_UNDERSCORE != which) {
01288 fprintf(Asm_File, "\t%s\t%s\n", AS_GLOBAL,
01289 underscorify(ST_name(sym)));
01290 }
01291 #else
01292 fprintf(Asm_File, "\t%s\t%s\n", AS_GLOBAL, ST_name(sym));
01293 #endif
01294 }
01295 }
01296 else
01297 symindex = Em_Add_New_Symbol (
01298 ST_name(sym), base_ofst, 0,
01299 symbind, STT_FUNC, symother,
01300 Em_Get_Section_Index (em_scn[STB_scninfo_idx(base_st)].scninfo));
01301 break;
01302
01303 case CLASS_BLOCK:
01304 if (STB_section(sym)) {
01305 Init_Section(sym);
01306 return ST_elf_index(sym);
01307 }
01308
01309 symindex = Em_Add_New_Undef_Symbol (
01310 ST_name(sym), symbind, STT_OBJECT, symother);
01311 break;
01312 case CLASS_UNK:
01313 case CLASS_CONST:
01314 default:
01315 symindex = Em_Add_New_Undef_Symbol (
01316 ST_name(sym), STB_LOCAL, STT_OBJECT, symother);
01317 break;
01318 }
01319 Set_ST_elf_index(sym, symindex);
01320 return symindex;
01321 }
01322
01323 extern void
01324 EMT_Change_Symbol_To_Undefined (ST *sym)
01325 {
01326 Elf64_Word symindex = ST_elf_index(sym);
01327 if (symindex == 0)
01328
01329 return;
01330 Em_Undefine_Symbol (symindex);
01331 }
01332
01333 extern void
01334 EMT_Change_Symbol_To_Weak (ST *sym)
01335 {
01336 Elf64_Word symindex = ST_elf_index(sym);
01337 if (symindex == 0)
01338
01339 return;
01340 Em_Set_Symbol_Binding (symindex, STB_WEAK);
01341 }
01342
01343
01344
01345 static void
01346 put_TN_comment (TN *t, BOOL add_name, vstring *comment)
01347 {
01348 if (!add_name) return;
01349 if ( ! TN_is_constant(t) ) return;
01350 INT64 val = TN_offset(t);
01351 if ( TN_is_symbol(t) ) {
01352 if (ST_class(TN_var(t)) == CLASS_CONST) {
01353 #ifdef TARG_NVISA
01354 if (MTYPE_is_float(ST_mtype(TN_var(t))))
01355 *comment = vstr_concat (*comment,
01356 Targ_Print("%g", ST_tcon_val(TN_var(t))) );
01357 else
01358 #endif
01359 *comment = vstr_concat (*comment,
01360 Targ_Print(NULL, ST_tcon_val(TN_var(t))) );
01361 }
01362 else {
01363 *comment = vstr_concat (*comment, ST_name(TN_var(t)));
01364 }
01365 if (TN_offset(t) != 0) {
01366 vstr_sprintf (comment, vstr_len(*comment), "%+lld", val);
01367 }
01368 }
01369 else if ( TN_is_label(t) && val != 0) {
01370 *comment = vstr_concat (*comment, LABEL_name(TN_label(t)));
01371 vstr_sprintf (comment, vstr_len(*comment), "%+lld", val);
01372 }
01373 }
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385 static BOOL
01386 r_apply_l_const (
01387 OP *op,
01388 INT opidx,
01389 vstring *buf)
01390 {
01391 TN *t = OP_opnd(op, opidx);
01392 INT paren = 0;
01393 BOOL hexfmt = FALSE;
01394 BOOL print_TN_offset = TRUE;
01395 BOOL add_name = FALSE;
01396 ST *st;
01397 INT64 val;
01398
01399
01400 if ( TN_is_symbol(t) ) {
01401 ST *base_st;
01402 INT64 base_ofst;
01403
01404 st = TN_var(t);
01405 Base_Symbol_And_Offset (st, &base_st, &base_ofst);
01406 if (base_st == SP_Sym || base_st == FP_Sym) {
01407 val = base_ofst + TN_offset(t);
01408
01409 if ( TN_is_reloc_neg(t) ) {
01410 val = -val;
01411 }
01412 if ( TN_is_reloc_low16(t) ) {
01413 val = val & 0xffff;
01414 hexfmt = TRUE;
01415 } else if ( TN_is_reloc_high16(t) ) {
01416 val = ( ( val - (short)val ) >> 16) & 0xffff;
01417 hexfmt = TRUE;
01418 } else if ( TN_is_reloc_higher(t) ) {
01419 val = ( ( val + 0x80008000LL ) >> 32 ) & 0xffff;
01420 hexfmt = TRUE;
01421 } else if ( TN_is_reloc_highest(t) ) {
01422 val = ( ( val + 0x800080008000LL ) >> 48 ) & 0xffff;
01423 hexfmt = TRUE;
01424 }
01425 #ifdef TARG_SL
01426 if (((OP_code(op) == TOP_pop16) && (opidx == 1)) || ((OP_code(op) == TOP_push16) && (opidx == 2 ))) {
01427 val = val >> 2;
01428 }
01429 #endif
01430 #ifdef TARG_IA64
01431 vstr_sprintf (buf, vstr_len(*buf), (hexfmt ? "0x%" LL_FORMAT "x" : "%" LL_FORMAT "d"), val );
01432 #else
01433 if ( TN_is_reloc_low16(t) )
01434 vstr_sprintf (buf, vstr_len(*buf), "%hd", (signed short)val );
01435 else {
01436 vstr_sprintf (buf, vstr_len(*buf), (hexfmt ? "0x%" LL_FORMAT "x" : "%" LL_FORMAT "d"), val );
01437 }
01438 #endif
01439 return TRUE;
01440 }
01441 }
01442 val = TN_offset(t);
01443
01444 if ( TN_is_reloc_neg(t) ) {
01445 *buf = vstr_concat (*buf, "-");
01446 }
01447
01448 if ( TN_is_symbol(t) ) {
01449 #ifdef TARG_SL
01450 Is_True(!(OP_code(op) == TOP_pop16 || (OP_code(op) == TOP_push16)), ("unsupport pop16/push16 type of offset "));
01451 #endif
01452
01453 #if defined(BUILD_OS_DARWIN)
01454 darwin_indirect_t indirect = DO_UNDERSCORE;
01455 #endif
01456 st = TN_var(t);
01457
01458 if( (ST_class(st) != CLASS_CONST)
01459 #ifdef TARG_X8664
01460 && ( TN_relocs(t) != TN_RELOC_IA32_GLOBAL_OFFSET_TABLE )
01461 #endif
01462 ){
01463 #if defined(BUILD_OS_DARWIN)
01464
01465
01466
01467
01468
01469 if (Is_Target_32bit() && ST_class(st) == CLASS_FUNC &&
01470 ST_sclass(st) == SCLASS_EXTERN) {
01471 if (OP_code(op) == TOP_call) {
01472 indirect = DO_STUB;
01473 }
01474
01475 else if (OP_code(op) == TOP_ldc32) {
01476 indirect = DO_NON_LAZY_PTR;
01477 op->opr = TOP_ld32_n32;
01478 }
01479 }
01480 (void) EMT_Put_Elf_Symbol (st, indirect);
01481 gen_indirect(ST_name(st), indirect);
01482 #else
01483 (void) EMT_Put_Elf_Symbol (st);
01484 #endif
01485 }
01486 #ifdef TARG_NVISA
01487 if (ST_class(st) == CLASS_CONST) {
01488
01489 if (MTYPE_is_float(ST_mtype(st))) {
01490 *buf = vstr_concat(*buf, Targ_Print (NULL, STC_val(st)));
01491
01492 add_name = TRUE;
01493 }
01494 else {
01495 vstr_sprintf (buf, vstr_len(*buf), "__constant%d", ST_index(st));
01496 }
01497 }
01498 #else
01499 if (TN_relocs(t) != 0) {
01500 #ifdef TARG_SL
01501 Is_True(!(OP_code(op) == TOP_pop16 || (OP_code(op) == TOP_push16)),
01502 ("unsupport pop16/push16 type of offset "));
01503 #endif
01504
01505 if (CGEMIT_Use_Base_ST_For_Reloc (TN_relocs(t), st)) {
01506 ST *base_st;
01507 INT64 base_ofst;
01508 Base_Symbol_And_Offset (st, &base_st, &base_ofst);
01509 val += base_ofst;
01510 st = base_st;
01511 }
01512 if (Use_Separate_PU_Section(current_pu,st)) {
01513
01514 st = PU_base;
01515 }
01516 hexfmt = TRUE;
01517 print_TN_offset = TRUE;
01518
01519 add_name = TRUE;
01520 paren = CGEMIT_Relocs_In_Asm (t, st, buf, &val);
01521 }
01522 #endif // TARG_NVISA
01523 else {
01524 #if defined(BUILD_OS_DARWIN)
01525 *buf = vstr_concat(*buf, underscorify(ST_name(st), indirect));
01526 #else
01527 *buf = vstr_concat(*buf, ST_name(st));
01528 #endif
01529 if (*Symbol_Name_Suffix != '\0')
01530 *buf = vstr_concat(*buf, Symbol_Name_Suffix);
01531 }
01532 }
01533 else if ( TN_is_label(t) ) {
01534 #ifdef TARG_SL
01535 Is_True(!(OP_code(op) == TOP_pop16 || (OP_code(op) == TOP_push16)),
01536 ("unsupport pop16/push16 type of offset "));
01537 #endif
01538 if (val != 0) {
01539
01540
01541
01542 *buf = vstr_concat (*buf, LABEL_name(TN_label(t)));
01543 vstr_sprintf (buf, vstr_len(*buf), "%+lld", val);
01544 }
01545 else {
01546 *buf = vstr_concat(*buf, LABEL_name(TN_label(t)));
01547 if (isdigit(LABEL_name(TN_label(t))[0])) {
01548 *buf = vstr_concat(*buf, (PC > Get_Label_Offset(TN_label(t))) ? "b" : "f");
01549 }
01550 }
01551 print_TN_offset = FALSE;
01552 }
01553 else if (TN_is_tag(t)) {
01554 *buf = vstr_concat(*buf, LABEL_name(TN_label(t)));
01555 print_TN_offset = FALSE;
01556 }
01557 else if (TN_is_enum(t)) {
01558 #ifdef TARG_SL
01559 Is_True(!(OP_code(op) == TOP_pop16 || (OP_code(op) == TOP_push16)),
01560 ("unsupport pop16/push16 type of offset "));
01561 #endif
01562 if (ISA_PRINT_Operand_Is_Part_Of_Name(OP_code(op), opidx)) {
01563 vstr_sprintf (buf, vstr_len(*buf), "%s", ISA_ECV_Name(TN_enum(t)) );
01564 } else {
01565 #ifdef TARG_NVISA
01566
01567
01568 vstr_sprintf (buf, vstr_len(*buf), "%s", ISA_ECV_Name(TN_enum(t)) );
01569 #else
01570 vstr_sprintf (buf, vstr_len(*buf), "%d", ISA_ECV_Intval(TN_enum(t)) );
01571 #endif
01572 }
01573 print_TN_offset = FALSE;
01574 }
01575 else if ( TN_has_value(t) ) {
01576 #ifdef TARG_X8664
01577 vstr_sprintf (buf, vstr_len(*buf),
01578 (hexfmt ? "0x%" LL_FORMAT "x" : "%" LL_FORMAT "d"), TN_value(t) );
01579 #else
01580 if ( TN_size(t) <= 4 )
01581 #ifdef TARG_SL
01582 if (((OP_code(op) == TOP_pop16) && (opidx == 1)) ||
01583 ((OP_code(op) == TOP_push16) && (opidx == 2 ))) {
01584 vstr_sprintf (buf, vstr_len(*buf),
01585 (hexfmt ? "0x%x" : "%d"), (((mINT32)(TN_value(t)))>>2) );
01586 }
01587 else
01588 #endif
01589 vstr_sprintf (buf, vstr_len(*buf),
01590 (hexfmt ? "0x%x" : "%d"), (mINT32)TN_value(t) );
01591 else
01592 vstr_sprintf (buf, vstr_len(*buf),
01593 (hexfmt ? "0x%" LL_FORMAT "x" : "%" LL_FORMAT "d"), TN_value(t) );
01594 #endif
01595
01596 print_TN_offset = FALSE;
01597 }
01598 else {
01599 #pragma mips_frequency_hint NEVER
01600 FmtAssert (FALSE, ("r_apply_l_const: illegal constant TN"));
01601 }
01602
01603 if (print_TN_offset && (val != 0)) {
01604 vstr_sprintf (buf, vstr_len(*buf), "%+lld", val );
01605 }
01606
01607 while ( paren > 0 ) {
01608 *buf = vstr_concat(*buf, ")");
01609 --paren;
01610 }
01611 return add_name;
01612 }
01613
01614
01615
01616
01617
01618
01619
01620 static void print_prefetch_info(
01621 vstring *comment,
01622 WN *wn)
01623 {
01624
01625 if ( !wn ) return;
01626
01627 if ( WN_pf_stride_1L( wn ) != 0 ) {
01628 *comment = vstr_concat(*comment, "L1");
01629 return;
01630 }
01631
01632 if ( WN_pf_stride_2L( wn ) != 0 ) {
01633 *comment = vstr_concat(*comment, "L2");
01634 }
01635 }
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647 static void r_assemble_list (
01648 OP *op,
01649 BB *bb)
01650 {
01651 const char *result[ISA_OPERAND_max_results];
01652 const char *opnd[ISA_OPERAND_max_operands];
01653 vstring buf = vstr_begin(LBUF_LEN);
01654 INT i;
01655 INT lc = 0;
01656 BOOL add_name = FALSE;
01657
01658 Emit_Unwind_Directives_For_OP(op, Asm_File);
01659
01660 #if defined(GAS_TAGS_WORKED) || defined(TARG_SL)
01661
01662 if (OP_has_tag(op)) {
01663 fprintf(Asm_File, "%s:\n", LABEL_name(Get_OP_Tag(op)));
01664 }
01665 #endif
01666
01667 for (i = 0; i < OP_opnds(op); i++) {
01668 INT start = vstr_len(buf);
01669 TN *t = OP_opnd(op,i);
01670
01671 if ( TN_is_constant(t) ) {
01672 add_name |= r_apply_l_const (op, i, &buf);
01673 }
01674 else {
01675 const char *rname;
01676 ISA_REGISTER_CLASS rc = TN_register_class(t);
01677 REGISTER reg = TN_register(t);
01678 #ifdef HAS_STACKED_REGISTERS
01679 if (ABI_PROPERTY_Is_stacked(rc, REGISTER_machine_id(rc, reg))
01680 && ! BB_rotating_kernel(bb)
01681 && REGISTER_Is_Stacked_Output(rc, reg) )
01682 {
01683 reg = REGISTER_Translate_Stacked_Output(reg);
01684 }
01685 #endif
01686 FmtAssert (reg != REGISTER_UNDEFINED,
01687 ("r_assemble_list: illegal operand tn%d", TN_number(t)));
01688
01689 if (!TN_is_true_pred(t)) {
01690 ISA_REGISTER_SUBCLASS sc = OP_opnd_reg_subclass(op,i);
01691 if ( REGISTER_SET_MemberP(REGISTER_SUBCLASS_members(sc), reg)
01692 && REGISTER_SUBCLASS_reg_name(sc, reg))
01693 {
01694 rname = REGISTER_SUBCLASS_reg_name(sc, reg);
01695 } else if (List_Software_Names) {
01696 rname = ABI_PROPERTY_Reg_Name(rc, REGISTER_machine_id(rc, reg));
01697 } else {
01698 rname = REGISTER_name(rc, reg);
01699 }
01700 if (i == OP_PREDICATE_OPND && OP_has_predicate(op)) {
01701 vstr_sprintf(&buf, start, ISA_PRINT_PREDICATE, rname);
01702 } else {
01703 buf = vstr_concat(buf, rname);
01704 }
01705 }
01706 }
01707
01708 buf = vstr_append(buf, '\0');
01709 opnd[i] = vstr_str(buf)+start;
01710 }
01711
01712 for (i = 0; i < OP_results(op); i++) {
01713 const char *rname;
01714 INT start = vstr_len(buf);
01715 TN *t = OP_result(op,i);
01716 ISA_REGISTER_SUBCLASS sc = OP_result_reg_subclass(op,i);
01717 ISA_REGISTER_CLASS rc = TN_register_class(t);
01718 REGISTER reg = TN_register(t);
01719 FmtAssert (t != NULL && !TN_is_constant(t),
01720 ("r_assemble_list: illegal result tn"));
01721 #ifdef HAS_STACKED_REGISTERS
01722 if (ABI_PROPERTY_Is_stacked(rc, REGISTER_machine_id(rc, reg))
01723 && ! BB_rotating_kernel(bb)
01724 && REGISTER_Is_Stacked_Output(rc, reg) )
01725 {
01726 reg = REGISTER_Translate_Stacked_Output(reg);
01727 }
01728 #endif
01729 FmtAssert (reg != REGISTER_UNDEFINED,
01730 ("r_assemble_list: illegal result tn%d", TN_number(t)));
01731 if ( REGISTER_SET_MemberP(REGISTER_SUBCLASS_members(sc), reg)
01732 && REGISTER_SUBCLASS_reg_name(sc, reg))
01733 {
01734 rname = REGISTER_SUBCLASS_reg_name(sc, reg);
01735 } else if (List_Software_Names) {
01736 rname = ABI_PROPERTY_Reg_Name(rc, REGISTER_machine_id(rc, reg));
01737 } else {
01738 rname = REGISTER_name(rc, reg);
01739 }
01740 buf = vstr_concat(buf, rname);
01741 buf = vstr_append(buf, '\0');
01742 result[i] = vstr_str(buf)+start;
01743 }
01744
01745 fputc ('\t', Asm_File);
01746 #ifdef TARG_X8664
01747 lc = CGEMIT_Print_Inst( op, result, opnd, Asm_File );
01748 #elif defined(TARG_IA64)
01749 lc = CGEMIT_Print_Inst( op, result, opnd, Asm_File );
01750 #else
01751 lc = TI_ASM_Print_Inst( OP_code(op), result, opnd, Asm_File );
01752 #endif
01753 FmtAssert (lc != TI_RC_ERROR, ("%s", TI_errmsg));
01754 vstr_end(buf);
01755
01756 if (OP_end_group(op)) lc += fprintf(Asm_File, " %s", ISA_PRINT_END_GROUP);
01757
01758 while (lc < 30) {
01759 fputc (' ', Asm_File);
01760 lc++;
01761 }
01762
01763 vstring comment = vstr_begin(LBUF_LEN);
01764 for (i = 0; i < OP_opnds(op); i++) {
01765 put_TN_comment (OP_opnd(op,i), add_name, &comment);
01766 }
01767
01768 #ifdef TARG_IA64
01769 fprintf (Asm_File, "\t\t%s", ASM_CMNT);
01770 fprintf (Asm_File, " [");
01771 #else
01772 fprintf (Asm_File, "\t%s", ASM_CMNT);
01773 #endif
01774 if (OP_scycle(op) >= 0)
01775 if (BB_rotating_kernel(bb)) {
01776 ANNOTATION *annot = ANNOT_Get(BB_annotations(bb), ANNOT_ROTATING_KERNEL);
01777 ROTATING_KERNEL_INFO *info = ANNOT_rotating_kernel(annot);
01778 INT ii = info->ii;
01779 #ifdef TARG_IA64
01780 fprintf (Asm_File, "%d*II+%d", OP_scycle(op) / ii, OP_scycle(op) % ii);
01781 } else if (BB_scheduled(bb)) {
01782 if(!OP_noop(op))
01783 fprintf (Asm_File, "%d", OP_scycle(op));
01784 fprintf (Asm_File, ":%d", Srcpos_To_Line(OP_srcpos(op)));
01785 }
01786 fprintf (Asm_File, "]");
01787 #else
01788 fprintf (Asm_File, " [%d*II+%d]", OP_scycle(op) / ii, OP_scycle(op) % ii);
01789 } else if (BB_scheduled(bb))
01790 fprintf (Asm_File, " [%d]", OP_scycle(op));
01791 #endif
01792 if (vstr_len(comment) == 0) {
01793 WN *wn = Get_WN_From_Memory_OP (op);
01794 if (wn && Alias_Manager) {
01795 char tbuf[LBUF_LEN];
01796 tbuf[0] = '\0';
01797 Print_alias_info (tbuf, Alias_Manager, wn);
01798 comment = vstr_concat(comment, tbuf);
01799 }
01800 if (wn && OP_prefetch(op) && vstr_len(comment) == 0) {
01801 print_prefetch_info(&comment,wn);
01802 }
01803 }
01804
01805
01806
01807 if ((OP_call(op) || OP_tail_call(op)) && vstr_len(comment) == 0) {
01808 ANNOTATION *ant = ANNOT_Get (BB_annotations(bb), ANNOT_CALLINFO);
01809 if (ant != NULL) {
01810 ST *call_sym = CALLINFO_call_st(ANNOT_callinfo(ant));
01811 if (call_sym != NULL) {
01812 comment = vstr_concat(comment, ST_name(call_sym));
01813 }
01814 }
01815 }
01816 #ifdef TARG_IA64
01817
01818 if (OP_flags_val_prof(op) == VAL_PROF_FLAG)
01819 {
01820 char tbuf[1024];
01821 tbuf[0] = '\0';
01822 FB_TNV * fb_tnv = NULL;
01823 if (op_tnv_map)
01824 {
01825 fb_tnv = (FB_TNV *)OP_MAP_Get(op_tnv_map, op);
01826 if (fb_tnv == NULL)
01827 DevWarn("can not find tnv-info in op_tnv_map! val_prof_id = %d.", OP_val_prof_id(op));
01828 }
01829 if (fb_tnv != NULL)
01830 {
01831 fb_tnv->Print(stderr);
01832 sprintf(tbuf, " val_prof[%u, %llu] (%llu => %llu, %llu => %llu, %llu => %llu, %llu => %llu, %llu => %llu)",
01833 OP_val_prof_id(op), OP_exec_count(op),
01834 fb_tnv->_values[0], fb_tnv->_counters[0],
01835 fb_tnv->_values[1], fb_tnv->_counters[1],
01836 fb_tnv->_values[2], fb_tnv->_counters[2],
01837 fb_tnv->_values[3], fb_tnv->_counters[3],
01838 fb_tnv->_values[4], fb_tnv->_counters[4]
01839 );
01840 }
01841 else
01842 {
01843 sprintf(tbuf, " val_prof[%u, %llu]",
01844 OP_val_prof_id(op), OP_exec_count(op) );
01845 }
01846 comment = vstr_concat(comment, tbuf);
01847 }
01848
01849 char * spec_str = NULL ;
01850 if (OP_cntl_spec(op)) {
01851 spec_str = "c-spec " ;
01852 if (OP_if_converted(op)) {
01853 spec_str = "ci-spec";
01854 }
01855 } else if (OP_data_spec(op)) {
01856 spec_str = "d-spec ";
01857 }
01858
01859 if (OP_cntl_spec(op) && OP_data_spec(op)) {
01860 spec_str = "cd-spec" ;
01861 }
01862
01863 if (spec_str) {
01864 char tbuf[20];
01865
01866 sprintf (tbuf, "\t[%s BB:%u]",
01867 spec_str ? spec_str : "",
01868 OP_orig_bb_id(op));
01869 comment = vstr_concat(comment, tbuf);
01870 }
01871
01872 if (OP_renamed(op)) {
01873 char tbuf[20];
01874 sprintf (tbuf, "\t[renamed]");
01875 comment = vstr_concat(comment, tbuf);
01876 }
01877
01878 #endif
01879 fprintf (Asm_File, " %s\n", vstr_str(comment));
01880 vstr_end(comment);
01881 }
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892 static void Verify_Operand(
01893 const ISA_OPERAND_INFO *oinfo,
01894 OP *op,
01895 INT opnd,
01896 BOOL is_result)
01897 {
01898 const ISA_OPERAND_VALTYP *vtype = is_result
01899 ? ISA_OPERAND_INFO_Result(oinfo, opnd)
01900 : ISA_OPERAND_INFO_Operand(oinfo, opnd);
01901 TN *tn = is_result ? OP_result(op, opnd) : OP_opnd(op, opnd);
01902 const char * const res_or_opnd = is_result ? "result" : "operand";
01903
01904 if (ISA_OPERAND_VALTYP_Is_Register(vtype)) {
01905
01906 REGISTER_SET class_regs;
01907 ISA_REGISTER_SUBCLASS sc = ISA_OPERAND_VALTYP_Register_Subclass(vtype);
01908 ISA_REGISTER_CLASS rc = ISA_OPERAND_VALTYP_Register_Class(vtype);
01909 REGISTER reg = TN_register(tn);
01910
01911 FmtAssert(TN_is_register(tn),
01912 ("%s %d is not a register", res_or_opnd, opnd));
01913
01914 #ifdef TARG_X8664
01915 if( tn != Rip_TN() )
01916 #endif
01917 FmtAssert(TN_register_class(tn) == rc,
01918 ("incorrect register class for %s %d", res_or_opnd, opnd));
01919
01920 FmtAssert(reg != REGISTER_UNDEFINED,
01921 ("undefined register for %s %d", res_or_opnd, opnd));
01922
01923 class_regs = (sc == ISA_REGISTER_SUBCLASS_UNDEFINED)
01924 ? REGISTER_CLASS_universe(rc)
01925 : REGISTER_SUBCLASS_members(sc);
01926 FmtAssert(REGISTER_SET_MemberP(class_regs, reg),
01927 ("incorrect register for %s %d", res_or_opnd, opnd));
01928 } else if (ISA_OPERAND_VALTYP_Is_Literal(vtype)) {
01929 FmtAssert(TN_is_constant(tn),
01930 ("%s %d is not a constant", res_or_opnd, opnd));
01931
01932 if (TN_has_value(tn)) {
01933 ISA_LIT_CLASS lc = ISA_OPERAND_VALTYP_Literal_Class(vtype);
01934 INT64 imm = TN_value(tn);
01935
01936 if ((TFile != stdout) && !ISA_LC_Value_In_Class(imm, lc)) {
01937 #if defined(TARG_NVISA)
01938 DevWarn("literal doesn't fit");
01939 #endif
01940 Print_OP_No_SrcLine (op);
01941 }
01942 #ifdef TARG_X8664
01943 if( TN_size(tn) == 4 ){
01944 imm = (INT32) imm;
01945 }
01946 #endif
01947 #if !defined(TARG_NVISA)
01948 FmtAssert(ISA_LC_Value_In_Class(imm, lc),
01949 ("literal for %s %d is not in range", res_or_opnd, opnd));
01950 #endif
01951 } else if (TN_is_label(tn)) {
01952 #if Is_True_On
01953 LABEL_IDX lab = TN_label(tn);
01954 INT64 offset = TN_offset(tn);
01955 INT64 val = Get_Label_Offset(lab) + offset;
01956 if (CG_opt_level > 0 && CFLOW_Enable && !OP_likely(op)) {
01957 INT nextpc = PC + sizeof(ISA_BUNDLE);
01958 if (PROC_has_branch_delay_slot()) nextpc += sizeof(ISA_PACK_INST);
01959
01960 if (val == nextpc) {
01961 if (Trace_Inst)
01962 fprintf(TFile,"branch to next instruction at PC=0x%x\n", PC);
01963 DevWarn("branch to next instruction at PC=0x%x", PC);
01964 }
01965 }
01966 if (Get_Label_Offset(lab) == 0 && offset == 0) {
01967 BBLIST *item;
01968 BB *label_bb = Get_Label_BB(lab);
01969 BOOL okay = FALSE;
01970 FOR_ALL_BB_SUCCS(OP_bb(op), item) {
01971 if (BBLIST_item(item) == label_bb) okay = TRUE;
01972 }
01973 if (!okay) {
01974 DevWarn("branch to 0? (possible bug at PC=0x%x, label %s)",
01975 PC, LABEL_name(lab));
01976 }
01977 }
01978 #endif
01979 }
01980 } else if (ISA_OPERAND_VALTYP_Is_Enum(vtype)) {
01981 ISA_ENUM_CLASS_VALUE ecv;
01982 ISA_ENUM_CLASS ec = ISA_OPERAND_VALTYP_Enum_Class(vtype);
01983 ISA_ENUM_CLASS_VALUE first_ecv = ISA_EC_First_Value(ec);
01984 ISA_ENUM_CLASS_VALUE last_ecv = ISA_EC_Last_Value(ec);
01985
01986 FmtAssert(TN_is_enum(tn),
01987 ("%s %d is not an enum", res_or_opnd, opnd));
01988
01989 ecv = TN_enum(tn);
01990 FmtAssert(ecv >= first_ecv && ecv <= last_ecv,
01991 ("enum for %s %d is not in range", res_or_opnd, opnd));
01992 } else {
01993 FmtAssert(FALSE, ("unhandled vtype in Verify_Operand"));
01994 }
01995 }
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006 static void Verify_Instruction(OP *op)
02007 {
02008 INT i;
02009 const ISA_OPERAND_INFO *oinfo;
02010 TOP top = OP_code(op);
02011
02012
02013
02014 FmtAssert(ISA_SUBSET_Member(ISA_SUBSET_Value, top),
02015 ("%s is a member of ISA %s",
02016 TOP_Name(top),
02017 ISA_SUBSET_Name(ISA_SUBSET_Value)));
02018
02019 #ifdef TARG_X8664
02020 if( OP_x86_style( op ) ){
02021 if( TN_register_and_class( OP_opnd( op, 0 ) ) !=
02022 TN_register_and_class( OP_result( op , 0 ) ) )
02023 FmtAssert( false, ("Result and the first opnd use different register.") );
02024 }
02025
02026 if( OP_reads_rflags( op ) ){
02027 OP* prev = OP_prev( op );
02028 while( prev != NULL ){
02029 if( TOP_is_change_rflags( OP_code(prev) ) )
02030 break;
02031 prev = OP_prev( prev );
02032 }
02033
02034
02035
02036
02037 FmtAssert(prev != NULL || OP_code(op) == TOP_jnp,
02038 ("set_rflags op is missing") );
02039 }
02040
02041
02042 int index = TOP_Find_Operand_Use( top, OU_index );
02043 if( index >= 0 ){
02044 REGISTER reg = TN_register( OP_opnd(op,index) );
02045 FmtAssert( reg != RSP, ("%rsp can not serve as index register in lea") );
02046 }
02047 #endif
02048
02049 oinfo = ISA_OPERAND_Info(top);
02050
02051 INT results = OP_results(op);
02052 if (results != TOP_fixed_results(top)) {
02053 FmtAssert(TOP_is_var_opnds(top) && results > TOP_fixed_results(top),
02054 ("wrong number of results (%d) for %s",
02055 results,
02056 TOP_Name(top)));
02057 results = TOP_fixed_results(top);
02058 }
02059 for (i = 0; i < results; ++i) {
02060 Verify_Operand(oinfo, op, i, TRUE);
02061 }
02062
02063 INT opnds = OP_opnds(op);
02064 if (opnds != TOP_fixed_opnds(top)) {
02065 FmtAssert(TOP_is_var_opnds(top) && opnds > TOP_fixed_opnds(top),
02066 ("wrong number of operands (%d) for %s",
02067 opnds,
02068 TOP_Name(top)));
02069 opnds = TOP_fixed_opnds(top);
02070 }
02071 for (i = 0; i < opnds; ++i) {
02072 Verify_Operand(oinfo, op, i, FALSE);
02073 }
02074
02075 #ifdef KEY
02076
02077 if (OP_uniq_res(op)) {
02078 for (i = 0; i < results; i++) {
02079 int j;
02080 TN *result_tn = OP_result(op, i);
02081 for (j = 0; j < opnds; j++) {
02082 TN *opnd_tn = OP_opnd(op, j);
02083 if (TN_is_register(opnd_tn)) {
02084 FmtAssert(!TNs_Are_Equivalent(opnd_tn, result_tn),
02085 ("need unique registers for %s operand and result",
02086 TOP_Name(top)));
02087 }
02088 }
02089 }
02090 }
02091 #endif
02092
02093 }
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103 static INT r_assemble_binary ( OP *op, BB *bb, ISA_PACK_INST *pinst )
02104 {
02105 INT i;
02106 INT words;
02107 TOP opcode = OP_code(op);
02108 INT64 result[ISA_OPERAND_max_results];
02109 INT64 opnd[ISA_OPERAND_max_operands];
02110
02111 for (i = 0; i < OP_opnds(op); i++) {
02112 INT64 val = 0;
02113 TN *t = OP_opnd(op, i);
02114
02115 if (TN_is_constant(t)) {
02116 if (TN_is_label(t)) {
02117
02118
02119 val = Get_Label_Offset(TN_label(t)) + TN_offset(t);
02120
02121
02122 if (OP_opnd_is_pcrel(op, i)) {
02123 val -= PC_Bundle(PC);
02124 if (PROC_has_branch_delay_slot()) val -= sizeof(ISA_PACK_INST);
02125 }
02126
02127 FmtAssert (ISA_LC_Value_In_Class(val, OP_opnd_lit_class(op, i)),
02128 ("branch offset %lld doesn't fit; try recompiling with "
02129 "-CG:longbranch_limit=[try values smaller than %d]",
02130 val, EMIT_Long_Branch_Limit));
02131 }
02132 else if (TN_is_tag(t)) {
02133
02134 val = Get_Label_Offset(TN_label(t));
02135 }
02136 else if (TN_is_symbol(t)) {
02137 ST *base_st;
02138 INT64 base_ofst;
02139 ST *st = TN_var(t);
02140
02141 val = TN_offset(t);
02142 if (ST_class(st) == CLASS_VAR && ST_is_export_local(st)) {
02143 FmtAssert(Has_Base_Block(st),
02144 ("relocation of local symbol %s that hasn't been allocated?", ST_name(st)));
02145 }
02146 Base_Symbol_And_Offset (st, &base_st, &base_ofst);
02147
02148 if (OP_jump(op)) {
02149 Em_Add_New_Rel (EMT_Put_Elf_Symbol (st), R_MIPS_26, PC,
02150 PU_section);
02151 val = 0;
02152 }
02153 else if (base_st == SP_Sym || base_st == FP_Sym) {
02154 val += base_ofst;
02155 if ( TN_is_reloc_neg(t)) val = -val;
02156
02157 if (TN_is_reloc_low16(t)) {
02158 val = (val << 48) >> 48;
02159 } else if (TN_is_reloc_high16(t)) {
02160 val = ( (val - (short)val) << 32) >> 48;
02161 } else if (TN_is_reloc_higher(t)) {
02162 val = ( (val + 0x80008000LL) << 16) >> 48;
02163 } else if (TN_is_reloc_highest(t)) {
02164 val = ( (val + 0x800080008000LL) << 0) >> 48;
02165 }
02166 }
02167 else if (TN_relocs(t) != 0) {
02168 if (CGEMIT_Use_Base_ST_For_Reloc (TN_relocs(t), st)) {
02169 val += base_ofst;
02170 st = base_st;
02171 }
02172 if (Use_Separate_PU_Section(current_pu,st)) {
02173
02174 st = PU_base;
02175 }
02176 CGEMIT_Relocs_In_Object (t, st, PC, PU_section, &val);
02177 }
02178 else if (ST_is_gp_relative(st)) {
02179 DevWarn("is gp relative (%s)", ST_name(st));
02180 if (ST_class(st) == CLASS_CONST || ST_is_export_local(st)) {
02181 val -= GP_DISP;
02182 }
02183 #ifdef TARG_IA64
02184 if (!ISA_LC_Value_In_Class(val, LC_i16)) {
02185 #elif defined(TARG_X8664)
02186 if (!ISA_LC_Value_In_Class(val, LC_simm32)) {
02187 #elif defined(TARG_SL) || defined(TARG_MIPS)
02188 if (!ISA_LC_Value_In_Class(val, LC_simm16)) {
02189 #elif defined(TARG_NVISA)
02190 if (FALSE) {
02191 #endif
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201 Em_Add_New_Rela (EMT_Put_Elf_Symbol (st), R_MIPS_GPREL, PC,
02202 val, PU_section);
02203 val = 0;
02204 }
02205 else {
02206 #ifdef TARG_IA64
02207 FmtAssert (ISA_LC_Value_In_Class(val, LC_i16),
02208 ("immediate value %lld too large for GPREL relocation", val));
02209 #elif defined(TARG_X8664)
02210 FmtAssert (ISA_LC_Value_In_Class(val, LC_simm32),
02211 ("immediate value %lld too large for GPREL relocation", val));
02212 #elif defined(TARG_SL) || defined(TARG_MIPS)
02213 FmtAssert (ISA_LC_Value_In_Class(val, LC_simm16),
02214 ("immediate value %lld too large for GPREL relocation", val));
02215 #elif defined(TARG_NVISA)
02216
02217 #endif
02218 Em_Add_New_Rel (EMT_Put_Elf_Symbol (st), R_MIPS_GPREL, PC,
02219 PU_section);
02220 }
02221 }
02222 ISA_LIT_CLASS lc = OP_opnd_lit_class(op, i);
02223 FmtAssert(ISA_LC_Value_In_Class(val, lc),
02224 ("r_assemble_binary: illegal immediate value %lld for %s",
02225 val, ISA_LC_Name(lc)));
02226 }
02227 else if (TN_is_enum(t)) {
02228 val = ISA_ECV_Intval(TN_enum(t));
02229 }
02230 else if (TN_has_value(t)) {
02231 val = TN_value(t);
02232 }
02233 else {
02234 #pragma mips_frequency_hint NEVER
02235 FmtAssert (FALSE, ("r_assemble_binary: illegal constant TN"));
02236 }
02237 }
02238 else {
02239 ISA_REGISTER_CLASS rc = TN_register_class(t);
02240 REGISTER reg = TN_register(t);
02241 #ifdef HAS_STACKED_REGISTERS
02242 if (ABI_PROPERTY_Is_stacked(rc, REGISTER_machine_id(rc, reg))
02243 && ! BB_rotating_kernel(bb)
02244 && REGISTER_Is_Stacked_Output(rc, reg) )
02245 {
02246 reg = REGISTER_Translate_Stacked_Output(reg);
02247 }
02248 #endif
02249 val = REGISTER_machine_id (rc, reg);
02250 }
02251
02252 opnd[i] = val;
02253 }
02254
02255 for (i = 0; i < OP_results(op); ++i) {
02256 INT32 val;
02257 TN *t = OP_result(op,i);
02258 ISA_REGISTER_CLASS rc = TN_register_class(t);
02259 REGISTER reg = TN_register(t);
02260
02261 #ifdef HAS_STACKED_REGISTERS
02262 if (ABI_PROPERTY_Is_stacked(rc, REGISTER_machine_id(rc, reg))
02263 && ! BB_rotating_kernel(bb)
02264 && REGISTER_Is_Stacked_Output(rc, reg) )
02265 {
02266 reg = REGISTER_Translate_Stacked_Output(reg);
02267 }
02268 #endif
02269 val = REGISTER_machine_id (rc, reg);
02270
02271 result[i] = val;
02272 }
02273
02274 words = TI_ASM_Pack_Inst(opcode, result, opnd, pinst);
02275 FmtAssert (words > 0, ("%s", TI_errmsg));
02276 return words;
02277 }
02278
02279
02280 #if Is_True_On && !defined(TARG_NVISA)
02281
02282 static REGISTER_SET defined_regs[ISA_REGISTER_CLASS_MAX+1];
02283 static INT defining_pcs[ISA_REGISTER_CLASS_MAX+1][REGISTER_MAX+1];
02284 static OP *defining_ops[ISA_REGISTER_CLASS_MAX+1][REGISTER_MAX+1];
02285
02286 static void
02287 Init_Sanity_Checking_For_BB (void)
02288 {
02289 ISA_REGISTER_CLASS cl;
02290
02291 FOR_ALL_ISA_REGISTER_CLASS(cl)
02292 defined_regs[cl] = REGISTER_SET_EMPTY_SET;
02293 }
02294
02295 static void
02296 Perform_Sanity_Checks_For_OP (OP *op, BOOL check_def)
02297 {
02298 TN *tn;
02299 ISA_REGISTER_CLASS cl;
02300 REGISTER reg;
02301 INT i;
02302 BOOL predicated = OP_has_predicate(op) != 0;
02303
02304 #if 0 // wait until srcpos are more robust
02305 if (!OP_noop(op) && SRCPOS_linenum(OP_srcpos(op)) == 0) {
02306 DevWarn("0 linenum on op at PC 0x%x", PC);
02307 }
02308 #endif
02309 for (i = 0; i < OP_opnds(op); i++) {
02310 tn = OP_opnd (op, i);
02311 if (TN_is_register(tn)) {
02312 cl = TN_register_class(tn);
02313 reg = TN_register(tn);
02314 defined_regs[cl] = REGISTER_SET_Difference1 (defined_regs[cl], reg);
02315 }
02316 }
02317 if (check_def) {
02318 for (i = 0; i < OP_results(op); i++) {
02319 tn = OP_result(op, i);
02320 cl = TN_register_class(tn);
02321 reg = TN_register(tn);
02322 if (REGISTER_SET_MemberP(defined_regs[cl], reg)) {
02323 OP *def_op = defining_ops[cl][reg];
02324 if ((CG_opt_level > 0) &&
02325 !OP_has_implicit_interactions(def_op) &&
02326 !OP_cond_def(def_op) &&
02327 !OP_cond_def(op) &&
02328 OP_results(def_op) == 1 &&
02329 (!OP_has_predicate(def_op) || (OP_opnd(def_op,OP_PREDICATE_OPND) == True_TN)) &&
02330 (!OP_has_predicate(op) || (OP_opnd(op,OP_PREDICATE_OPND) == True_TN)))
02331 {
02332 DevWarn("Unused definition in %sBB:%d (PC=0x%x)",
02333 OP_bb(op) && BB_rotating_kernel(OP_bb(op)) ? "SWPd " : "",
02334 OP_bb(op) ? BB_id(OP_bb(op)) : -1, defining_pcs[cl][reg]);
02335 if (TFile != stdout) {
02336 Print_OP_No_SrcLine (def_op);
02337 }
02338 }
02339 }
02340 defined_regs[cl] = REGISTER_SET_Union1(defined_regs[cl], reg);
02341 defining_pcs[cl][reg] = PC;
02342 defining_ops[cl][reg] = op;
02343 }
02344 }
02345
02346 if (((tn = CGTARG_Copy_Operand_TN(op)) != NULL) &&
02347 #ifndef TARG_IA64
02348 TN_is_register(tn) &&
02349 #endif
02350 (!OP_has_predicate(op) || (OP_opnd(op,OP_PREDICATE_OPND) == True_TN))) {
02351 if (TN_register(OP_result(op,0)) == TN_register(tn)) {
02352 DevWarn("Redundant Copy instruction in %sBB:%d (PC=0x%x)",
02353 OP_bb(op) && BB_rotating_kernel(OP_bb(op)) ? "SWPd " : "",
02354 OP_bb(op) ? BB_id(OP_bb(op)) : -1, PC);
02355 if (TFile != stdout) {
02356 Print_OP_No_SrcLine (op);
02357 }
02358 }
02359 } else {
02360 if (OP_ixor(op) &&
02361 (TN_is_zero(OP_opnd(op,0+predicated)) || TN_is_zero(OP_opnd(op,1+predicated))) )
02362 {
02363 DevWarn ("Redundant XOR instruction in %sBB:%d (PC=0x%x)",
02364 BB_rotating_kernel(OP_bb(op)) ? "SWPd " : "",
02365 BB_id(OP_bb(op)), PC);
02366 if (TFile != stdout) {
02367 Print_OP_No_SrcLine (op);
02368 }
02369 }
02370
02371 if (CGTARG_Is_Right_Shift_Op (op)) {
02372 if (TN_register(OP_opnd(op,0+predicated)) == REGISTER_zero) {
02373 DevWarn ("Redundant shift instruction in %sBB:%d (PC=0x%x)",
02374 BB_rotating_kernel(OP_bb(op)) ? "SWPd " : "",
02375 BB_id(OP_bb(op)), PC);
02376 if (TFile != stdout) {
02377 Print_OP_No_SrcLine (op);
02378 }
02379 }
02380 }
02381 }
02382
02383 #ifndef TARG_X8664
02384 if (OP_unalign_ld(op)) {
02385 Is_True(TN_is_zero_reg(OP_opnd(op,2))
02386 || (TN_register(OP_opnd(op,2)) == TN_register(OP_result(op,0))),
02387 ("unaligned load last-result doesn't match new result "
02388 "in BB:%d", OP_bb(op) ? BB_id(OP_bb(op)) : -1));
02389 }
02390 #endif
02391
02392
02393 if ((tn = CGTARG_Copy_Operand_TN(op)) != NULL
02394 && TN_is_float(OP_result(op,0)) )
02395 {
02396 Is_True( ! TN_is_fpu_int(OP_opnd(op,0+predicated)),
02397 ("Illegal FP mov of integer TN%d in BB:%d",
02398 TN_number(tn), OP_bb(op) ? BB_id(OP_bb(op)) : -1));
02399 }
02400
02401 if (OP_code(op) == TOP_noop) {
02402 DevWarn("Noop not removed in BB:%d (PC=0x%x)", BB_id(OP_bb(op)), PC);
02403 if (TFile != stdout) {
02404 Print_OP_No_SrcLine(op);
02405 }
02406 }
02407 }
02408 #else
02409 #define Init_Sanity_Checking_For_BB()
02410 #define Perform_Sanity_Checks_For_OP(op, check_def)
02411 #endif // Is_True_On && !defined(TARG_NVISA)
02412
02413 #ifdef KEY
02414
02415
02416
02417
02418 static INT32 num_pus = 64;
02419 static BOOL dw_pu_tables_allocated = FALSE;
02420 LABEL_IDX *Label_pushbp=NULL;
02421 LABEL_IDX *Label_movespbp=NULL;
02422 LABEL_IDX *Label_adjustsp=NULL;
02423 LABEL_IDX *Label_Callee_Saved_Reg=NULL;
02424 LABEL_IDX *Label_First_BB_PU_Entry=NULL;
02425 LABEL_IDX *Label_Last_BB_PU_Entry=NULL;
02426
02427 #define ALLOCATE_LABEL_ENTRY \
02428 (TYPE_MEM_POOL_ALLOC_N(LABEL_IDX,&MEM_src_pool,num_pus))
02429
02430 #define DOUBLE_LABEL_ENTRY(label) \
02431 (label=TYPE_MEM_POOL_REALLOC_N(LABEL_IDX,&MEM_src_pool,label,num_pus, 2*num_pus))
02432
02433 static void init_dwarf_pu_tables()
02434 {
02435 if(!dw_pu_tables_allocated){
02436 Label_pushbp=ALLOCATE_LABEL_ENTRY;
02437 Label_movespbp=ALLOCATE_LABEL_ENTRY;
02438 Label_adjustsp=ALLOCATE_LABEL_ENTRY;
02439 Label_Callee_Saved_Reg=ALLOCATE_LABEL_ENTRY;
02440 Label_First_BB_PU_Entry=ALLOCATE_LABEL_ENTRY;
02441 Label_Last_BB_PU_Entry=ALLOCATE_LABEL_ENTRY;
02442 dw_pu_tables_allocated = TRUE;
02443 }
02444 for(INT i=0; i<num_pus; i++){
02445 Label_pushbp[i] = LABEL_IDX_ZERO;
02446 Label_movespbp[i] =LABEL_IDX_ZERO;
02447 Label_adjustsp[i] = LABEL_IDX_ZERO;
02448 Label_Callee_Saved_Reg[i] = LABEL_IDX_ZERO;
02449 Label_First_BB_PU_Entry[i] = LABEL_IDX_ZERO;
02450 Label_Last_BB_PU_Entry[i] = LABEL_IDX_ZERO;
02451 }
02452 }
02453
02454 static void double_dwarf_pu_tables()
02455 {
02456 FmtAssert(dw_pu_tables_allocated && Label_pushbp,
02457 ("double_dwarf_pu_tables: pu_tables were not allocated."));
02458 DOUBLE_LABEL_ENTRY(Label_pushbp);
02459 DOUBLE_LABEL_ENTRY(Label_movespbp);
02460 DOUBLE_LABEL_ENTRY(Label_adjustsp);
02461 DOUBLE_LABEL_ENTRY(Label_Callee_Saved_Reg);
02462 DOUBLE_LABEL_ENTRY(Label_First_BB_PU_Entry);
02463 DOUBLE_LABEL_ENTRY(Label_Last_BB_PU_Entry);
02464 num_pus = 2*num_pus;
02465 }
02466
02467 static INT32 pu_entries = 0;
02468 #endif // KEY
02469
02470 #ifdef TARG_X8664
02471 static inline BOOL
02472 tn_registers_identical (TN *tn1, TN *tn2)
02473 {
02474 return ((tn1 == tn2) ||
02475 ((TN_is_register(tn1) && TN_is_register(tn2) &&
02476 (TN_is_dedicated(tn1) ||
02477 (TN_register(tn1) != REGISTER_UNDEFINED)) &&
02478 (TN_is_dedicated(tn2) ||
02479 (TN_register(tn2) != REGISTER_UNDEFINED)) &&
02480 (TN_register_and_class(tn1) == TN_register_and_class(tn2)))));
02481 }
02482 #endif // TARG_X8664
02483
02484
02485
02486 static INT
02487 r_assemble_op(OP *op, BB *bb, ISA_BUNDLE *bundle, INT slot)
02488 {
02489 INT words;
02490 INT i;
02491
02492 if (Trace_Inst) {
02493 Print_OP(op);
02494 }
02495
02496 #ifdef TARG_IA64
02497 Remove_Hidden_Operands (op);
02498 #endif
02499 Verify_Instruction(op);
02500
02501 if (OP_prefetch(op)) Use_Prefetch = TRUE;
02502
02503 #ifdef KEY
02504 static INT32 label_adjustsp_pu = -1;
02505 static INT32 pu_entry_count = -1;
02506 BOOL adjustsp_instr = FALSE;
02507
02508
02509
02510
02511
02512 static BB *prev_bb = NULL;
02513 static INT32 prev_pu_count = -1;
02514 INT32 cur_pu_count = Current_PU_Count();
02515 BOOL is_first_bb_op = ((cur_pu_count != prev_pu_count) || (bb != prev_bb));
02516 Is_True(((op != BB_first_op(bb)) || is_first_bb_op),
02517 ("r_assemble_op: is_first_bb_op should be TRUE for first BB OP"));
02518 prev_bb = bb;
02519 prev_pu_count = cur_pu_count;
02520
02521 if ( BB_entry(bb) && CG_emit_unwind_info ) {
02522
02523
02524
02525
02526
02527 ST *entry_sym;
02528 ENTRYINFO *ent;
02529 ANNOTATION *ant;
02530 ant = ANNOT_Get (BB_annotations(bb), ANNOT_ENTRYINFO);
02531 ent = ANNOT_entryinfo(ant);
02532 entry_sym = ENTRYINFO_name(ent);
02533
02534 if (is_first_bb_op) {
02535 if (strcmp(ST_name(entry_sym), Cur_PU_Name) == 0) {
02536 pu_entries = 0;
02537 pu_entry_count ++;
02538 }
02539 else if (PU_ftn_lang(Get_Current_PU())) {
02540 pu_entries ++;
02541 pu_entry_count ++;
02542 }
02543
02544 if(!dw_pu_tables_allocated){
02545 Is_True (FALSE, ("r_assemble_op: dwarf pu tables not allocated."));
02546 init_dwarf_pu_tables();
02547 }
02548 if(pu_entries >= num_pus-1)
02549 double_dwarf_pu_tables();
02550
02551 Label_First_BB_PU_Entry[pu_entries] = Gen_Label_For_BB(bb);
02552 FmtAssert(pu_entries < num_pus-1,
02553 ("Too many pus, pu_tables should have been expanded."));
02554 }
02555
02556 #ifdef TARG_X8664
02557 if (OP_code(op) == TOP_pushq ||
02558 OP_code(op) == TOP_pushl &&
02559 Debug_Level > 0) {
02560 char* buf;
02561 LABEL* label;
02562 buf = (char *)alloca(strlen(ST_name(entry_sym)) +
02563 32);
02564 sprintf(buf, ".LEH_pushbp_%s", ST_name(entry_sym));
02565 label = &New_LABEL(CURRENT_SYMTAB, Label_pushbp[pu_entries]);
02566 LABEL_Init (*label, Save_Str(buf), LKIND_DEFAULT);
02567 fprintf( Asm_File, "%s:\n", LABEL_name(Label_pushbp[pu_entries]));
02568 } else if ((OP_code(op) == TOP_mov64 ||
02569 OP_code(op) == TOP_mov32) &&
02570 OP_result(op, 0) == FP_TN &&
02571 OP_opnd(op, 0) == SP_TN) {
02572 char* buf;
02573 LABEL* label;
02574 buf = (char *)alloca(strlen(ST_name(entry_sym)) +
02575 32);
02576 sprintf(buf, ".LEH_movespbp_%s", ST_name(entry_sym));
02577 label = &New_LABEL(CURRENT_SYMTAB, Label_movespbp[pu_entries]);
02578 LABEL_Init (*label, Save_Str(buf), LKIND_DEFAULT);
02579 fprintf( Asm_File, "%s:\n", LABEL_name(Label_movespbp[pu_entries]));
02580 } else if ((OP_code(op) == TOP_addi64 ||
02581 OP_code(op) == TOP_addi32 ||
02582 OP_code(op) == TOP_sub64 ||
02583 OP_code(op) == TOP_sub32) &&
02584 label_adjustsp_pu != pu_entry_count &&
02585 OP_result(op, 0) == SP_TN) {
02586 char* buf;
02587 LABEL* label;
02588 buf = (char *)alloca(strlen(ST_name(entry_sym)) +
02589 32);
02590 sprintf(buf, ".LEH_adjustsp_%s", ST_name(entry_sym));
02591 label = &New_LABEL(CURRENT_SYMTAB, Label_adjustsp[pu_entries]);
02592 LABEL_Init (*label, Save_Str(buf), LKIND_DEFAULT);
02593 fprintf( Asm_File, "%s:\n", LABEL_name(Label_adjustsp[pu_entries]));
02594 label_adjustsp_pu = pu_entry_count;
02595 adjustsp_instr = TRUE;
02596
02597
02598
02599
02600
02601
02602
02603 if (Cgdwarf_Num_Callee_Saved_Regs()) {
02604 buf = (char *)alloca(strlen(ST_name(entry_sym)) +
02605 32);
02606 sprintf(buf, ".LEH_csr_%s", ST_name(entry_sym));
02607 label = &New_LABEL(CURRENT_SYMTAB, Label_Callee_Saved_Reg[pu_entries]);
02608 LABEL_Init (*label, Save_Str(buf), LKIND_DEFAULT);
02609 fprintf( Asm_File, "%s:\n", LABEL_name(Label_Callee_Saved_Reg[pu_entries]));
02610 }
02611 }
02612 #endif // TARG_X8664
02613 }
02614
02615 Cg_Dwarf_First_Op_After_Preamble_End = FALSE;
02616 if (Debug_Level > 0 && OP_first_after_preamble_end(op)) {
02617 Cg_Dwarf_First_Op_After_Preamble_End = TRUE;
02618 if (OP_srcpos(op) == 0 && op->next != 0)
02619 OP_srcpos(op) = OP_srcpos(OP_next(op));
02620 }
02621
02622 Cg_Dwarf_BB_First_Op = FALSE;
02623 if (Debug_Level > 0 && is_first_bb_op &&
02624 (BB_preds_len(bb) != 1 ||
02625 (BB_preds_len(bb) == 1 &&
02626 BB_prev(bb) && BB_First_Pred(bb) != BB_prev(bb))))
02627 Cg_Dwarf_BB_First_Op = TRUE;
02628
02629 #endif // KEY
02630 Cg_Dwarf_Add_Line_Entry (PC, OP_srcpos(op));
02631 if (Assembly) {
02632 #ifdef TARG_SL
02633 #define SL_SINGLE_SIZE 4
02634
02635 switch (OP_code(op)) {
02636 case TOP_add16_sp: {
02637 TN *imm7 = OP_opnd(op, 1);
02638 INT32 value = TN_value(imm7);
02639 TN *tmp = Gen_Literal_TN((value>>2), 4);
02640 Set_OP_opnd(op, 1, tmp);
02641 r_assemble_list(op, bb);
02642 if (!Object_Code) words = ISA_PACK_Inst_Words(OP_code(op));
02643 break;
02644 }
02645 case TOP_ldc1: {
02646
02647 TN *imm16 = OP_opnd(op, 1);
02648 TN *res = OP_result(op, 0);
02649 OP_Change_Opcode(op, TOP_lwc1);
02650 Set_TN_offset(imm16, TN_offset(imm16));
02651 r_assemble_list( op, bb );
02652 if (!Object_Code) words = ISA_PACK_Inst_Words(OP_code(op));
02653
02654
02655 Set_TN_offset(imm16, TN_offset(imm16) + SL_SINGLE_SIZE);
02656 Set_TN_register_class(res, ISA_REGISTER_CLASS_float_odd);
02657 r_assemble_list( op, bb );
02658 if (!Object_Code) words = ISA_PACK_Inst_Words(OP_code(op));
02659
02660
02661 OP_Change_Opcode(op, TOP_ldc1);
02662 Set_TN_offset(imm16, TN_offset(imm16));
02663 Set_TN_register_class(res, ISA_REGISTER_CLASS_float);
02664 break;
02665 }
02666
02667 case TOP_sdc1: {
02668
02669 TN *imm16 = OP_opnd(op, 2);
02670 TN *st_val = OP_opnd(op, 0);
02671 OP_Change_Opcode(op, TOP_swc1);
02672 Set_TN_offset(imm16, TN_offset(imm16));
02673 r_assemble_list( op, bb );
02674 if (!Object_Code) words = ISA_PACK_Inst_Words(OP_code(op));
02675
02676
02677 Set_TN_offset(imm16, TN_offset(imm16) + SL_SINGLE_SIZE);
02678 Set_TN_register_class(st_val, ISA_REGISTER_CLASS_float_odd);
02679 r_assemble_list( op, bb );
02680 if (!Object_Code) words = ISA_PACK_Inst_Words(OP_code(op));
02681
02682
02683 OP_Change_Opcode(op, TOP_sdc1);
02684 Set_TN_offset(imm16, TN_offset(imm16));
02685 Set_TN_register_class(st_val, ISA_REGISTER_CLASS_float);
02686 break;
02687 }
02688
02689 case TOP_mov_d: {
02690 TN *opnd1 = OP_opnd(op, 0);
02691 TN *res = OP_result(op, 0);
02692
02693
02694 OP_Change_Opcode(op, TOP_mov_s);
02695 r_assemble_list( op, bb );
02696 if (!Object_Code) words = ISA_PACK_Inst_Words(OP_code(op));
02697
02698
02699 Set_TN_register_class(opnd1, ISA_REGISTER_CLASS_float_odd);
02700 Set_TN_register_class(res, ISA_REGISTER_CLASS_float_odd);
02701 r_assemble_list( op, bb );
02702 if (!Object_Code) words = ISA_PACK_Inst_Words(OP_code(op));
02703
02704
02705 OP_Change_Opcode(op, TOP_mov_d);
02706 Set_TN_register_class(opnd1, ISA_REGISTER_CLASS_float);
02707 Set_TN_register_class(res, ISA_REGISTER_CLASS_float);
02708 break;
02709 }
02710
02711 case TOP_movf_d: {
02712 TN *opnd1 = OP_opnd(op, 0);
02713 TN *res = OP_result(op, 0);
02714
02715
02716 OP_Change_Opcode(op, TOP_movf_s);
02717 r_assemble_list( op, bb );
02718 if (!Object_Code) words = ISA_PACK_Inst_Words(OP_code(op));
02719
02720
02721 Set_TN_register_class(opnd1, ISA_REGISTER_CLASS_float_odd);
02722 Set_TN_register_class(res, ISA_REGISTER_CLASS_float_odd);
02723 r_assemble_list( op, bb );
02724 if (!Object_Code) words = ISA_PACK_Inst_Words(OP_code(op));
02725
02726
02727 OP_Change_Opcode(op, TOP_movf_d);
02728 Set_TN_register_class(opnd1, ISA_REGISTER_CLASS_float);
02729 Set_TN_register_class(res, ISA_REGISTER_CLASS_float);
02730 break;
02731 }
02732
02733 case TOP_movt_d: {
02734 TN *opnd1 = OP_opnd(op, 0);
02735 TN *res = OP_result(op, 0);
02736
02737
02738 OP_Change_Opcode(op, TOP_movt_s);
02739 r_assemble_list( op, bb );
02740 if (!Object_Code) words = ISA_PACK_Inst_Words(OP_code(op));
02741
02742
02743 Set_TN_register_class(opnd1, ISA_REGISTER_CLASS_float_odd);
02744 Set_TN_register_class(res, ISA_REGISTER_CLASS_float_odd);
02745 r_assemble_list( op, bb );
02746 if (!Object_Code) words = ISA_PACK_Inst_Words(OP_code(op));
02747
02748
02749 OP_Change_Opcode(op, TOP_movt_d);
02750 Set_TN_register_class(opnd1, ISA_REGISTER_CLASS_float_odd);
02751 Set_TN_register_class(res, ISA_REGISTER_CLASS_float_odd);
02752 break;
02753 }
02754
02755 default:
02756 r_assemble_list ( op, bb );
02757 if (!Object_Code) words = ISA_PACK_Inst_Words(OP_code(op));
02758 }
02759 #else
02760 r_assemble_list ( op, bb );
02761 #endif // TARG_SL
02762 if (!Object_Code) words = ISA_PACK_Inst_Words(OP_code(op));
02763 }
02764 #ifdef TARG_X8664
02765 if (BB_entry(bb) && CG_emit_unwind_info && Frame_Len == 0) {
02766 char* entry_name;
02767 ST *entry_sym;
02768 ENTRYINFO *ent;
02769 ANNOTATION *ant;
02770 ant = ANNOT_Get (BB_annotations(bb), ANNOT_ENTRYINFO);
02771 ent = ANNOT_entryinfo(ant);
02772 entry_sym = ENTRYINFO_name(ent);
02773 entry_name = ST_name(entry_sym);
02774
02775
02776
02777
02778 if ((OP_code(op) == TOP_mov64 ||
02779 OP_code(op) == TOP_mov32) &&
02780 OP_result(op, 0) == FP_TN &&
02781 OP_opnd(op, 0) == SP_TN) {
02782 char* buf;
02783 LABEL* label;
02784 buf = (char *)alloca(strlen(entry_name) +
02785 32);
02786 sprintf(buf, ".LEH_adjustsp_%s", entry_name);
02787 label = &New_LABEL(CURRENT_SYMTAB, Label_adjustsp[pu_entries]);
02788 LABEL_Init (*label, Save_Str(buf), LKIND_DEFAULT);
02789 fprintf( Asm_File, "%s:\n", LABEL_name(Label_adjustsp[pu_entries]));
02790
02791 adjustsp_instr = TRUE;
02792 }
02793 }
02794 #endif // TARG_X8664
02795
02796 #if !defined(TARG_IA64) && !defined(TARG_SL) && !defined(TARG_NVISA) && !defined(TARG_MIPS)
02797
02798
02799
02800
02801 if (adjustsp_instr) {
02802
02803
02804
02805
02806
02807 if( Assembly && (REGION_First_BB == bb) &&
02808 ( strcmp( Cur_PU_Name, "MAIN__" ) == 0 ||
02809 strcmp( Cur_PU_Name, "main" ) == 0 ) ){
02810 CGEMIT_Setup_Ctrl_Register( Asm_File );
02811 }
02812 }
02813 #endif
02814
02815 if (Object_Code) {
02816 ISA_PACK_INST inst[ISA_PACK_MAX_INST_WORDS];
02817 words = r_assemble_binary ( op, bb, inst );
02818 for (i = 0; i < words; ++i) {
02819 ISA_BUNDLE_PACK_COMP slot_comp = (ISA_BUNDLE_PACK_COMP)
02820 (ISA_BUNDLE_PACK_COMP_slot + slot++);
02821 TI_ASM_Set_Bundle_Comp(bundle, slot_comp, inst[i]);
02822 if (slot == ISA_MAX_SLOTS) {
02823 slot = 0;
02824 ++bundle;
02825 }
02826 }
02827
02828
02829 if (OP_call(op) || OP_tail_call(op)) {
02830 CGEMIT_Add_Call_Information (op, bb, PC, PU_section);
02831 }
02832 if (Get_Trace ( TP_EMIT,0x100 )) {
02833
02834 if (OP_ijump(op) && !OP_call(op) && !BB_exit(bb)) {
02835 ANNOTATION *ant = ANNOT_Get(BB_annotations(bb), ANNOT_SWITCH);
02836 if (ant != NULL) {
02837 ST *jumptable = ANNOT_switch(ant);
02838 BOOL gprel = ST_is_gp_relative(jumptable);
02839 INT num_entries = TY_AR_ubnd_val(ST_type(jumptable),0)+1;
02840 Elf_Event_Kind event_type;
02841 event_type = (Use_32_Bit_Pointers ? EK_SWITCH_32 : EK_SWITCH_64);
02842
02843 Em_Add_New_Event (event_type, PC,
02844 gprel, EMT_Put_Elf_Symbol(jumptable), num_entries, PU_section);
02845 }
02846 }
02847 }
02848 }
02849
02850 PC = PC_Incr_N(PC, words);
02851
02852
02853
02854 if (OP_code(op) == TOP_asm) {
02855 Last_Label = LABEL_IDX_ZERO;
02856 }
02857 else {
02858 #if !defined(TARG_X8664) && !defined(TARG_NVISA)
02859
02860 Offset_From_Last_Label = PC_Incr_N(Offset_From_Last_Label, words);
02861 #endif
02862 }
02863
02864 return words;
02865 }
02866
02867
02868 #ifdef KEY
02869 #include "cxx_memory.h"
02870
02871 static char*
02872 Replace_Substring(char* in, char* from, const char* to)
02873 {
02874 if (strcmp(from, to) == 0) return in;
02875
02876
02877
02878
02879 UINT buflen = strlen(in) + 5*strlen(to) + 64;
02880 char* buf = CXX_NEW(char[buflen], &MEM_local_pool);
02881 char* tmp = CXX_NEW(char[buflen], &MEM_local_pool);
02882 char* cpy = in;
02883 char* p = NULL;
02884 char* q = NULL;
02885 char* leftover;
02886 INT times = 5;
02887 INT substitute = 1;
02888
02889 strcpy(buf, "");
02890 strcpy(tmp, "");
02891 strcat(in, "\0");
02892 while ((p = strstr(in, from)) != NULL) {
02893
02894 leftover = p + strlen(from);
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939 if (strlen(from) >= 2 &&
02940 from[0] == '%' &&
02941 (isdigit(from[1]) ||
02942 isalpha(from[1]) ||
02943 from[1] == '*' ||
02944 from[1] == '&')) {
02945
02946
02947
02948
02949
02950
02951
02952
02953
02954 q = p + 2;
02955
02956
02957
02958
02959
02960
02961
02962 while (*q != '\0' && (isdigit(*q) || isalpha(*q))) q++;
02963
02964
02965
02966
02967
02968
02969
02970 if ((q - p) == strlen(from))
02971 substitute = 1;
02972 else
02973 substitute = 0;
02974
02975 }
02976 else substitute = 1;
02977
02978 strncpy(tmp, in, strlen(in) - strlen(p));
02979 tmp[strlen(in) - strlen(p)] = '\0';
02980 strcat(buf, tmp);
02981 if (substitute)
02982 strcat(buf, to);
02983 else
02984 strcat(buf, from);
02985 in = leftover;
02986 if (--times == 0) {
02987 buf = TYPE_MEM_POOL_REALLOC_N(char, &MEM_local_pool, buf,
02988 buflen, buflen + 5*strlen(to) + 64);
02989 tmp = TYPE_MEM_POOL_REALLOC_N(char, &MEM_local_pool, tmp,
02990 buflen, buflen + 5*strlen(to) + 64);
02991 buflen += (5*strlen(to) + 64);
02992 times = 5;
02993 }
02994 }
02995 CXX_DELETE(tmp, &MEM_local_pool);
02996 if (strcmp(buf, "") == 0) {
02997 CXX_DELETE(buf, &MEM_local_pool);
02998 return cpy;
02999 }
03000 strcat(buf, in);
03001 return buf;
03002 }
03003 #else
03004 static char*
03005 Replace_Substring(char* in, char* from, const char* to)
03006 {
03007 UINT buflen = strlen(in) + 64;
03008 char* buf = (char*) alloca(buflen);
03009 char* p;
03010 while ((p = strstr(in, from)) != NULL) {
03011 char* leftover = p + strlen(from);
03012 *p = '\0';
03013 while (strlen(in) + strlen(to) + strlen(leftover) >= buflen) {
03014 buflen = buflen * 2;
03015 buf = (char*) alloca(buflen);
03016 }
03017 sprintf(buf, "%s%s%s", in, to, leftover);
03018 in = strdup(buf);
03019 }
03020 return in;
03021 }
03022 #endif
03023
03024 #ifdef TARG_X8664
03025 static const char* int_reg_names[5][16] = {
03026
03027 { "%al", "%bl", "%bpl", "%spl", "%dil", "%sil", "%dl", "%cl",
03028 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" },
03029
03030 { "%ah", "%bh", "%bph", "%sph", "%dih", "%sih", "%dh", "%ch",
03031
03032 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" },
03033
03034 { "%ax", "%bx", "%bp", "%sp", "%di", "%si", "%dx", "%cx",
03035 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" },
03036
03037 { "%eax", "%ebx", "%ebp", "%esp", "%edi", "%esi", "%edx", "%ecx",
03038 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" },
03039
03040 { "%rax", "%rbx", "%rbp", "%rsp", "%rdi", "%rsi", "%rdx", "%rcx",
03041 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" },
03042 };
03043 #endif
03044 static char*
03045 #ifdef TARG_IA64
03046 Modify_Asm_String (char* asm_string, UINT32 position, bool memory, TN* tn, BB *bb)
03047 #else
03048 Modify_Asm_String (char* asm_string, UINT32 position, bool memory,
03049 TN* offset_tn,
03050 TN* tn, BB *bb)
03051 #endif
03052 {
03053 char* name = NULL;
03054 #ifdef TARG_X8664
03055 char st_reg_name_template[7] = {'%', 's', 't', '(', '\0', ')', '\0'};
03056 #endif
03057 if( TN_is_register(tn) ){
03058 ISA_REGISTER_CLASS cl = TN_register_class(tn);
03059 REGISTER reg = TN_register(tn);
03060 #ifdef HAS_STACKED_REGISTERS
03061 if (ABI_PROPERTY_Is_stacked(cl, REGISTER_machine_id(cl, reg))
03062 && ! BB_rotating_kernel(bb)
03063 && REGISTER_Is_Stacked_Output(cl, reg))
03064 {
03065 reg = REGISTER_Translate_Stacked_Output(reg);
03066 }
03067 #endif
03068 name = (char*) REGISTER_name(cl, reg);
03069 #ifdef TARG_X8664
03070
03071 if (cl == ISA_REGISTER_CLASS_integer) {
03072 name = (char*) CGTARG_Modified_Asm_Opnd_Name('r', tn, name);
03073 }
03074
03075
03076 if (name[0] == '%' &&
03077 name[1] == 's' &&
03078 name[2] == 't' &&
03079 (name[3] == '0' || name[3] == '1') &&
03080 name[4] == '\0') {
03081 st_reg_name_template[4] = name[3];
03082 name = st_reg_name_template;
03083 }
03084 #endif
03085 if (memory) {
03086 #ifdef TARG_MIPS
03087 char* buf = (char*) alloca(strlen(name)+4);
03088 sprintf(buf, "0(%s)", name);
03089 #else
03090 char* buf = (char*) alloca(strlen(name)+3);
03091 #ifdef TARG_X8664
03092
03093
03094 if (Is_Target_32bit() && cl != ISA_REGISTER_CLASS_integer) {
03095 char modifier = 'r';
03096 name = (char*) CGTARG_Modified_Asm_Opnd_Name(modifier, tn, name);
03097 }
03098 #endif
03099 #if defined(TARG_IA32) || defined(TARG_X8664)
03100 if( offset_tn != NULL ){
03101 FmtAssert( !TN_is_symbol(offset_tn), ("NYI") );
03102 }
03103
03104 if( offset_tn != NULL &&
03105 TN_has_value(offset_tn) ){
03106 sprintf(buf, "%d(%s)", (INT)TN_value(offset_tn),name);
03107 } else {
03108 sprintf(buf, "(%s)", name);
03109 }
03110 #else
03111 sprintf(buf, "[%s]", name);
03112 #endif
03113 #endif
03114 name = buf;
03115 }
03116 }
03117 else if( TN_is_symbol(tn) && ST_class(TN_var(tn)) == CLASS_CONST) {
03118 name = Targ_String_Address(STC_val(TN_var(tn)));
03119 }
03120 #if defined(TARG_X8664) || defined(TARG_NVISA)
03121 else if( TN_is_symbol(tn) ){
03122 ST* base_st = NULL;
03123 INT64 base_ofst = 0;
03124 TN* base_tn = NULL;
03125
03126 ST* st = TN_var(tn);
03127 Base_Symbol_And_Offset( st, &base_st, &base_ofst );
03128
03129 #ifdef TARG_NVISA
03130
03131 base_ofst = TN_offset(tn);
03132 #else
03133 base_ofst += TN_offset(tn);
03134 #endif
03135
03136 char* buf = (char*)alloca(strlen(ST_name(st)) + 64);
03137
03138 if (ST_is_thread_local(st)) {
03139 name = ST_name(st);
03140 sprintf(buf, "%%fs:%s@TPOFF", name);
03141 } else if( base_st == SP_Sym || base_st == FP_Sym ){
03142 base_tn = base_st == SP_Sym ? SP_TN : FP_TN;
03143 name = (char*)REGISTER_name( TN_register_class(base_tn), TN_register(base_tn) );
03144 if( Is_Target_32bit() ){
03145 name = (char*)CGTARG_Modified_Asm_Opnd_Name( 'r', base_tn, name );
03146 }
03147 sprintf( buf, "%d(%s)", (int)base_ofst, name );
03148 } else {
03149 name = ST_name( st );
03150
03151 #if defined (TARG_X8664)
03152 if (!memory && !strcmp (name, ".rodata")) {
03153
03154
03155 if( base_ofst == 0 )
03156 sprintf( buf, "$%s", name );
03157 else
03158 sprintf( buf, "$%s+%d", name, (int)base_ofst );
03159 }
03160 else {
03161 #endif
03162 if( base_ofst == 0 ){
03163 #if defined(TARG_X8664)
03164 if( Is_Target_32bit() )
03165 sprintf( buf, "%s", name );
03166 else
03167 sprintf( buf, "%s(%%rip)", name );
03168 #else
03169 sprintf( buf, "%s", name );
03170 #endif
03171 } else
03172 #if defined(TARG_X8664)
03173 if( Is_Target_32bit() )
03174 sprintf( buf, "%s+%d", name, (int)base_ofst );
03175 else
03176 sprintf( buf, "%s+%d(%%rip)", name, (int)base_ofst );
03177 #else
03178 sprintf( buf, "%s+%d", name, (int)base_ofst );
03179 #endif
03180 }
03181 #if defined (TARG_X8664)
03182 }
03183 #endif
03184 name = buf;
03185 }
03186 else {
03187 FmtAssert(!memory && TN_is_constant(tn) && TN_has_value(tn),
03188 ("ASM operand must be a register or a numeric constant"));
03189 FmtAssert(!(TN_is_symbol(tn) && ST_is_thread_local(TN_var(tn))),
03190 ("Modify_Asm_String: thread-local ASM operand NYI"));
03191 char* buf = (char*) alloca(32);
03192 #ifdef TARG_NVISA
03193 #ifdef __MINGW32__
03194
03195
03196 sprintf(buf, "%d",(INT)TN_value(tn));
03197 #else
03198 sprintf(buf, "%lld",TN_value(tn));
03199 #endif
03200 #else
03201 sprintf(buf, "$%lld",TN_value(tn));
03202 #endif
03203 name = buf;
03204 }
03205 #else
03206 else {
03207 FmtAssert(!memory && TN_is_constant(tn) && TN_has_value(tn),
03208 ("ASM operand must be a register or a numeric constant"));
03209 FmtAssert(!(TN_is_symbol(tn) && ST_is_thread_local(TN_var(tn))),
03210 ("Modify_Asm_String: thread-local ASM operand NYI"));
03211 char* buf = (char*) alloca(32);
03212 sprintf(buf, "%lld",TN_value(tn));
03213 name = buf;
03214 }
03215 #endif
03216
03217 char pattern[4];
03218 #ifdef TARG_IA64
03219 sprintf(pattern, "%%%c", '0'+position);
03220 #else
03221 sprintf(pattern, "%%%d", position);
03222 #endif
03223
03224 asm_string = Replace_Substring(asm_string, pattern, name);
03225
03226 #ifdef TARG_IA64
03227 if (TN_is_register(tn)) {
03228 for (INT i = 0; i < CGTARG_Num_Asm_Opnd_Modifiers; i++) {
03229 char modifier = CGTARG_Asm_Opnd_Modifiers[i];
03230 sprintf(pattern, "%%%c%c", modifier, '0'+position);
03231 name = (char*) CGTARG_Modified_Asm_Opnd_Name(modifier, tn, name);
03232 asm_string = Replace_Substring(asm_string, pattern, name);
03233 }
03234 }
03235 #elif defined(TARG_MIPS)
03236
03237 if (TN_is_register(tn)) {
03238 if (strstr(asm_string, "%z")) {
03239 char replace[5];
03240 sprintf(replace, "%%z%d", position);
03241 asm_string = Replace_Substring(asm_string, replace, name);
03242 }
03243 }
03244
03245 if (!TN_is_register(tn) && !TN_is_symbol(tn)) {
03246 if (strstr(asm_string, "%x")) {
03247 FmtAssert(!memory && TN_is_constant(tn) && TN_has_value(tn),
03248 ("ASM operand for %x constraint must be numeric constant"));
03249 char* buf = (char*) alloca(32);
03250 sprintf(buf, "0x%llx",TN_value(tn));
03251 name = buf;
03252 char replace[5];
03253 sprintf(replace, "%%x%d", position);
03254 asm_string = Replace_Substring(asm_string, replace, name);
03255 }
03256 }
03257 #elif defined(TARG_X8664)
03258 if (TN_is_register(tn)) {
03259
03260
03261
03262
03263 if (strcmp(name, "%st") == 0 || strcmp(name, "%st(0)") == 0) {
03264 sprintf(pattern, "%%y%d", position);
03265 asm_string = Replace_Substring(asm_string, pattern, "%st(0)");
03266 }
03267 }
03268
03269
03270
03271 if (strstr(asm_string, "%c") && TN_is_symbol(tn) ) {
03272 char replace[5];
03273 sprintf(replace, "%%c%d", position);
03274
03275
03276 char* left = name;
03277 while( *left != '(' && *left != '\0' )
03278 left++;
03279 if( *left == '(' ) {
03280 *left = '\0';
03281 asm_string = Replace_Substring(asm_string, replace, name);
03282 *left = '(';
03283 }
03284 else {
03285 asm_string = Replace_Substring(asm_string, replace, name);
03286 }
03287 }
03288
03289
03290
03291 if (!TN_is_register(tn) && !TN_is_symbol(tn)) {
03292 if (strstr(asm_string, "%c")) {
03293 char replace[5];
03294 sprintf(replace, "%%c%d", position);
03295
03296 asm_string = Replace_Substring(asm_string, replace, name+1);
03297 }
03298 if (strstr(asm_string, "%n")) {
03299
03300
03301
03302
03303
03304 char replace[5];
03305 char tmp;
03306 sprintf(replace, "%%n%d", position);
03307 tmp = *name;
03308 *name = '-';
03309 asm_string = Replace_Substring(asm_string, replace, name);
03310 *name = tmp;
03311 }
03312 if (strstr(asm_string, "%P")) {
03313 char replace[5];
03314 sprintf(replace, "%%P%d", position);
03315
03316 asm_string = Replace_Substring(asm_string, replace, name+1);
03317 }
03318 }
03319
03320
03321 if (strchr(asm_string, '{')) {
03322 char buf[500];
03323 int next = 0;
03324 buf[0] = '\0';
03325 for (INT i = 0; i < strlen(asm_string); i ++) {
03326 if (asm_string[i] == '{' || asm_string[i] == '}')
03327 continue;
03328 else if (asm_string[i] == '|') {
03329 INT j = i+1;
03330 BOOL found = TRUE;
03331 while (asm_string[j] != '}') {
03332 j ++;
03333 if (j == strlen(asm_string)) {
03334 found = FALSE;
03335 break;
03336 }
03337 }
03338 if (found) {
03339 i = j;
03340 continue;
03341 } else {
03342 FmtAssert(FALSE,
03343 ("Modify_Asm_String: Inline assembly %s has unmatched '{'",
03344 asm_string));
03345 }
03346 } else {
03347 buf[next++] = asm_string[i];
03348 buf[next] = '\0';
03349 }
03350 }
03351 sprintf(asm_string, "%s", buf);
03352 }
03353
03354
03355
03356 {
03357
03358
03359
03360
03361
03362 char x86pattern[5];
03363 const char *tmp_name;
03364 REGISTER reg;
03365 BOOL is_reg = TN_is_register(tn);
03366
03367 if (is_reg) {
03368 reg = TN_register(tn);
03369 }
03370
03371
03372 tmp_name = is_reg ? int_reg_names[0][reg-REGISTER_MIN] : name;
03373 sprintf(x86pattern, "%%b%d", position);
03374 asm_string = Replace_Substring(asm_string, x86pattern, tmp_name);
03375
03376
03377 tmp_name = is_reg ? int_reg_names[1][reg-REGISTER_MIN] : name;
03378 sprintf(x86pattern, "%%h%d", position);
03379 asm_string = Replace_Substring(asm_string, x86pattern, tmp_name);
03380
03381
03382 tmp_name = is_reg ? int_reg_names[2][reg-REGISTER_MIN] : name;
03383 sprintf(x86pattern, "%%w%d", position);
03384 asm_string = Replace_Substring(asm_string, x86pattern, tmp_name);
03385
03386
03387 tmp_name = is_reg ? int_reg_names[3][reg-REGISTER_MIN] : name;
03388 sprintf(x86pattern, "%%k%d", position);
03389 asm_string = Replace_Substring(asm_string, x86pattern, tmp_name);
03390
03391
03392 tmp_name = is_reg ? int_reg_names[4][reg-REGISTER_MIN] : name;
03393 sprintf(x86pattern, "%%q%d", position);
03394 asm_string = Replace_Substring(asm_string, x86pattern, tmp_name);
03395
03396
03397 const char *suffix = NULL;
03398 sprintf(x86pattern, "%%z%d", position);
03399 if (strstr(asm_string, x86pattern) != NULL) {
03400 UINT size;
03401 if (TN_is_symbol(tn)) {
03402 ST* st = TN_var(tn);
03403 size = ST_size(st);
03404 } else {
03405 size = TN_size(tn);
03406 }
03407 switch (size) {
03408 case 1: suffix = "b"; break;
03409 case 2: suffix = "w"; break;
03410 case 4: suffix = "l"; break;
03411 case 8: suffix = "q"; break;
03412 default: FmtAssert(FALSE, ("Opcode suffix requested for operand %d which has size %d", position, size)); break;
03413 }
03414 asm_string = Replace_Substring(asm_string, x86pattern, suffix);
03415 }
03416 }
03417 #endif // TARG_X8664
03418
03419 return asm_string;
03420 }
03421
03422 #ifdef TARG_SL
03423 extern UINT32 Control_Register_Index( TN *tn);
03424 static void Check_QuadWord_Alignment(OP *op, BB *bb, ISA_BUNDLE *bundle)
03425 {
03426 UINT32 quadword_pc = 0;
03427 UINT32 quadword_size = 16;
03428
03429 if (OP_dummy(op))
03430 return;
03431 quadword_pc = PC % quadword_size;
03432 if (PC > 0 && (quadword_pc ==0)) {
03433
03434 mvtcop->clear();
03435 mvfcop->clear();
03436 }
03437 if (TOP_is_mvtc(OP_code(op))) {
03438 UINT32 control_register_idx = Control_Register_Index(OP_result(op, 0));
03439 mvtcop->insert(mvtcop->begin(), control_register_idx);
03440 } else if ( TOP_is_use_ctrl_reg(OP_code(op))) {
03441 if (mvtcop->size() > 0) {
03442 int cr_idx = -1;
03443 if (OP_code(op ) == TOP_loop) {
03444 cr_idx = Control_Register_Index(OP_opnd(op, 2));
03445 } else {
03446 cr_idx = Control_Register_Index(OP_opnd(op, 0));
03447 }
03448 vector<UINT32>::iterator temp;
03449 for (temp = mvtcop->begin(); temp != mvtcop->end(); temp++) {
03450 if (cr_idx == *temp) {
03451 BB *cur_bb = OP_bb(op);
03452 if (cur_bb) {
03453 int num = (quadword_size - (quadword_pc&0xf));
03454 num = (num + 3) >> 2;
03455 for (int j =0; j< num ; j++) {
03456 OP *op1 = Mk_OP(TOP_nop16);
03457 OP *op2 = Mk_OP(TOP_nop16);
03458 BB_Insert_Op_Before(cur_bb, op, op1);
03459 r_assemble_op(op1, cur_bb, bundle, 0);
03460 BB_Insert_Op_Before(cur_bb, op, op2);
03461 r_assemble_op(op2, cur_bb, bundle, 0);
03462 }
03463 mvtcop->erase(temp);
03464 break;
03465 } else {
03466 Is_True(0, ("Check_QuadWord_Alignment:: bb is null"));
03467 }
03468 DevWarn(("Check_QuadWord_Alignment::same quad-word--insert nop instruction"));
03469 }
03470 }
03471 }
03472 }
03473
03474 if (((OP_code(op) == TOP_mvfc16) || (OP_code(op) == TOP_mvfc)) && (Control_Register_Index(OP_opnd(op, 0)) == 4)) {
03475 mvfcop->insert(mvfcop->begin(), 4);
03476 } else if ((mvfcop->size() > 0) && TOP_is_lnk(OP_code(op))) {
03477 vector<UINT32>::iterator temp;
03478 for (temp = mvfcop->begin(); temp != mvfcop->end(); temp++) {
03479 BB *cur_bb = OP_bb(op);
03480 if (cur_bb) {
03481 int num = (quadword_size - (quadword_pc&0xf));
03482 num = (num + 3) >> 2;
03483 for (int j =0; j< num ; j++) {
03484 OP *op1 = Mk_OP(TOP_nop16);
03485 OP *op2 = Mk_OP(TOP_nop16);
03486 BB_Insert_Op_Before(cur_bb, op, op1);
03487 r_assemble_op(op1, cur_bb, bundle, 0);
03488 BB_Insert_Op_Before(cur_bb, op, op2);
03489 r_assemble_op(op2, cur_bb, bundle, 0);
03490 }
03491 mvfcop->erase(temp);
03492 break;
03493 } else {
03494 Is_True(0, ("Check_QuadWord_Alignment:: bb is null"));
03495 }
03496 DevWarn(("Check_QuadWord_Alignment::same quad-word--insert nop instruction"));
03497
03498 }
03499 }
03500
03501 }
03502
03503
03504 int Compute_Asm_Num (const char *asm_string, BOOL emit_phase=TRUE) {
03505
03506 int words = 0;
03507 char *p = (char *)asm_string;
03508 char *skip_string[3] = {"noreorder", "reorder", "set"};
03509
03510
03511 typedef struct Macro_instr {
03512 char *str;
03513 UINT8 expand_num;
03514 };
03515 struct Macro_instr general_macro_string[5] = {{"la", 4}, {"move", 2}, {"beqz", 2}, {"bnez", 2}, {"break16", 1}};
03516 while(*p != '\0') {
03517 if (*p == '#') {
03518 while (*p != '\n') {
03519
03520 if (!strncmp("#define", (const char *)(p), 7))
03521 break;
03522 p++;
03523 }
03524 }
03525 if (isalpha(*(p))) {
03526 int i=0;
03527 char *q = p;
03528 char instr[30];
03529 int is_label = 0;
03530 int flag = 0;
03531 while (q && ((*q != '\t') && (*q != '\n')) && (*q != '\0') && (*q!=' ')) {
03532 instr[i++]=*q;
03533 if (*q == ':')
03534 is_label=1;
03535 q++;
03536 }
03537 instr[i]='\0';
03538 if (is_label) {
03539 p = q;
03540 continue;
03541 }
03542 if (strlen(instr) < 2) {
03543
03544 p = p+1;
03545 continue;
03546 }
03547
03548 for(i = 0; i < 3; i++) {
03549 if (!strncmp(skip_string[i], instr, strlen(skip_string[i])) && (strlen(instr) == strlen(skip_string[i]))) {
03550 p = p+strlen(skip_string[i]);
03551 flag = 1;
03552 break;
03553 }
03554 }
03555 for (i = 0; (i < 5) && (!flag); i++) {
03556 if (!strncmp(general_macro_string[i].str, instr, strlen(general_macro_string[i].str))) {
03557 if (emit_phase) {
03558 PC = PC_Incr_N(PC, general_macro_string[i].expand_num);
03559 Offset_From_Last_Label = PC_Incr_N(Offset_From_Last_Label, general_macro_string[i].expand_num);
03560 }
03561 else
03562 words += general_macro_string[i].expand_num;
03563 p = p + strlen(general_macro_string[i].str);
03564 if (trace_pc)
03565 fprintf(TFile, "%s\n", general_macro_string[i].str);
03566 flag == 1;
03567 }
03568 }
03569 if ((!flag) && (!strncmp("li", instr, 2))) {
03570 char *k = q;
03571 char digit[10];
03572 int j =0;
03573 while ((*k != ',') && (*k != '\0')) k++;
03574 while ( (*k != '\0') && !isdigit(*k)) k++;
03575 while (isdigit(*k)) {
03576 digit[j++] = *k;
03577 k++;
03578 }
03579 digit[j] = '\0';
03580 j = atoi(digit);
03581 if (((j) &~ 0x7fff) == 0 || (((j) &~ 0x7fff) == ~ 0x7fff) || (j >= 0 && j < 65536)) {
03582 if (trace_pc)
03583 fprintf(TFile, "one instruction li: digit %d\n", j);
03584 if (emit_phase) {
03585 PC = PC_Incr_N(PC, 2);
03586 Offset_From_Last_Label = PC_Incr_N(Offset_From_Last_Label, 2);
03587 }
03588 else
03589 words += 2;
03590 } else {
03591 if (trace_pc)
03592 fprintf(TFile, "two instruction li :digit %d\n", j);
03593 if (emit_phase) {
03594 PC = PC_Incr_N(PC, 4);
03595 Offset_From_Last_Label = PC_Incr_N(Offset_From_Last_Label, 2);
03596 }
03597 else
03598 words += 4;
03599 }
03600 p = k;
03601 continue;
03602 } else if (!flag) {
03603 int j;
03604 int len;
03605 for (j = 0; j<= TOP_count; j++) {
03606 const char *opname = TOP_Name((topcode)j);
03607 len = strlen(opname);
03608 if (!strncmp(opname, instr, len)) {
03609 if (trace_pc)
03610 fprintf(TFile, "asm: \t %d %s\n", PC, instr);
03611 p = p+len;
03612
03613 while (*p && (*p != '\n') && (*p != ';')) {
03614 p++;
03615 }
03616 if (emit_phase) {
03617 if (TOP_is_instr16(j))
03618 PC = PC_Incr_N(PC, 1);
03619 else
03620 PC = PC_Incr_N(PC, 2);
03621 Offset_From_Last_Label = PC_Incr_N(Offset_From_Last_Label, 2);
03622 }
03623 else {
03624 if (TOP_is_instr16(j))
03625 words += 1;
03626 else
03627 words += 2;
03628 }
03629 break;
03630 }
03631 }
03632 if (j > TOP_count) {
03633 p++;
03634 }
03635 continue;
03636 }
03637 }
03638 p++;
03639 }
03640
03641 return words;
03642 }
03643 #endif // TARG_SL
03644
03645 #ifdef TARG_SL
03646 char*
03647 #else
03648 static char*
03649 #endif
03650 Generate_Asm_String (OP* asm_op, BB *bb)
03651 {
03652 UINT i;
03653 ASM_OP_ANNOT* asm_info = (ASM_OP_ANNOT*) OP_MAP_Get(OP_Asm_Map, asm_op);
03654 char* asm_string = strdup(WN_asm_string(ASM_OP_wn(asm_info)));
03655
03656 #ifndef TARG_IA64
03657
03658
03659
03660 UINT n, index_count;
03661 char *p, *q, c;
03662
03663 p = asm_string;
03664
03665
03666
03667 while(*p != '\0') {
03668
03669
03670 if (*p == '%' && *(p + 1) == '%') {
03671 p += 2;
03672 continue;
03673 }
03674 else if (*p == '%') {
03675 p++;
03676
03677 if (*p != '\0' && !isdigit(*p)
03678 #ifdef KEY
03679 && *p != 'r' && *p != 'R'
03680 #endif
03681 ) p++;
03682
03683 q = p;
03684 while (*p != '\0' && isdigit(*p)) p++;
03685
03686
03687 if (p - q > 0) {
03688 c = *p;
03689 *p = '\0';
03690 n = atoi(q);
03691 *p = c;
03692
03693 index_count = OP_opnds(asm_op) + OP_results(asm_op);
03694 if (n >= index_count) {
03695 char message[128];
03696
03697
03698
03699 if (index_count == 0)
03700 sprintf(message, "Not expecting to see any operand references");
03701 else if (index_count == 1)
03702 sprintf(message, "Only permissible reference can be to operand 0"); else
03703 sprintf(message,
03704 "Expecting to see references to operands numbered"
03705 " between 0 and %d inclusive",
03706 index_count - 1);
03707
03708
03709 ErrMsg(EC_ASM_Bad_Operand, Srcpos_To_Line(OP_srcpos(asm_op)), n,
03710 message);
03711 }
03712 }
03713 }
03714 else p++;
03715 }
03716
03717
03718 static INT asm_unique_number = 111;
03719 if (strstr(asm_string, "%=")) {
03720 char pattern[3];
03721 char name[10];
03722 strcpy(pattern, "%=");
03723 sprintf(name, "%d", asm_unique_number);
03724 asm_string = Replace_Substring(asm_string, pattern, name);
03725 asm_unique_number ++;
03726 }
03727
03728 if (strcmp(asm_string, "__asm_builtin_apply_load") == 0) {
03729 FmtAssert(OP_opnds(asm_op) == 1, ("Has to have 1 operand"));
03730 TN *tn = OP_opnd(asm_op, 0);
03731 FmtAssert(TN_is_register(tn), ("opnd has to be in register"));
03732 ISA_REGISTER_CLASS cl = TN_register_class(tn);
03733 REGISTER reg = TN_register(tn);
03734 char name[256];
03735 char *asm_string;
03736 asm_string = (char *)malloc(sizeof(char)*1024);
03737 sprintf(name, "%s", REGISTER_name(cl, reg));
03738 sprintf(asm_string, "ld $4, 8(%s)\n", name);
03739 sprintf(asm_string, "%s\tld $5, 16(%s)\n", asm_string, name);
03740 sprintf(asm_string, "%s\tld $6, 24(%s)\n", asm_string, name);
03741 sprintf(asm_string, "%s\tld $7, 32(%s)\n", asm_string, name);
03742 sprintf(asm_string, "%s\tld $8, 40(%s)\n", asm_string, name);
03743 sprintf(asm_string, "%s\tld $9, 48(%s)\n", asm_string, name);
03744 sprintf(asm_string, "%s\tld $10, 56(%s)\n", asm_string, name);
03745 sprintf(asm_string, "%s\tld $11, 64(%s)\n", asm_string, name);
03746 sprintf(asm_string, "%s\tldc1 $f12, 72(%s)\n", asm_string, name);
03747 sprintf(asm_string, "%s\tldc1 $f13, 80(%s)\n", asm_string, name);
03748 sprintf(asm_string, "%s\tldc1 $f14, 88(%s)\n", asm_string, name);
03749 sprintf(asm_string, "%s\tldc1 $f15, 96(%s)\n", asm_string, name);
03750 sprintf(asm_string, "%s\tldc1 $f16, 104(%s)\n", asm_string, name);
03751 sprintf(asm_string, "%s\tldc1 $f17, 112(%s)\n", asm_string, name);
03752 sprintf(asm_string, "%s\tldc1 $f18, 120(%s)\n", asm_string, name);
03753 sprintf(asm_string, "%s\tldc1 $f19, 128(%s)", asm_string, name);
03754 return asm_string;
03755 }
03756 #endif
03757 for (i = 0; i < OP_results(asm_op); i++) {
03758 asm_string = Modify_Asm_String(asm_string,
03759 ASM_OP_result_position(asm_info)[i],
03760 ASM_OP_result_memory(asm_info)[i],
03761 #ifndef TARG_IA64
03762 NULL,
03763 #endif
03764 OP_result(asm_op, i), bb);
03765 }
03766
03767 for (i = 0; i < OP_opnds(asm_op); i++) {
03768 asm_string = Modify_Asm_String(asm_string,
03769 ASM_OP_opnd_position(asm_info)[i],
03770 ASM_OP_opnd_memory(asm_info)[i],
03771 #ifndef TARG_IA64
03772 (TN*)ASM_OP_opnd_offset(asm_info)[i],
03773 #endif
03774 OP_opnd(asm_op, i), bb);
03775 }
03776
03777 #ifndef TARG_X8664
03778 CGTARG_Postprocess_Asm_String(asm_string);
03779 #else
03780 if (strstr(asm_string, "%%")) {
03781 char replace[3] = { '%', '%', '\0' };
03782 char name[2] = { '%', '\0' };
03783 asm_string = Replace_Substring(asm_string, replace, name);
03784 }
03785 #endif
03786
03787 return asm_string;
03788 }
03789
03790
03791
03792
03793 static void
03794 Assemble_Simulated_OP(OP *op, BB *bb)
03795 {
03796
03797
03798
03799
03800
03801 const char *stop_bit = AS_STOP_BIT;
03802
03803 if (OP_code(op) == TOP_asm) {
03804 FmtAssert(Assembly && !Object_Code,
03805 ("can't emit object code when ASM"));
03806 if (stop_bit && (EMIT_stop_bits_for_asm
03807 || (EMIT_stop_bits_for_volatile_asm && OP_volatile(op)) ) )
03808 {
03809 fprintf(Asm_File, "\t%s\n", stop_bit);
03810 }
03811 #ifdef TARG_MIPS
03812 const char *asm_string = Generate_Asm_String(op, bb);
03813 if (!CG_emit_non_gas_syntax)
03814 if (asm_string)
03815 if (strstr(asm_string, ".set"))
03816 fprintf (Asm_File, "\t.set\tpush\n");
03817 #ifdef TARG_SL
03818 if (asm_string && (CG_check_quadword)) {
03819 Compute_Asm_Num(asm_string);
03820 }
03821 #endif
03822 #endif
03823 fprintf(Asm_File, "\t%s\n", Generate_Asm_String(op, bb));
03824 #ifdef TARG_MIPS
03825 if (!CG_emit_non_gas_syntax)
03826 if (asm_string)
03827 if (strstr(asm_string, ".set"))
03828 fprintf (Asm_File, "\t.set\tpop\n");
03829 #endif
03830 if (stop_bit && (EMIT_stop_bits_for_asm
03831 || (EMIT_stop_bits_for_volatile_asm && OP_volatile(op)) ) )
03832 {
03833 fprintf(Asm_File, "\t%s\n", stop_bit);
03834 }
03835 return;
03836 }
03837
03838 #ifdef TARG_NVISA
03839 if (OP_code(op) == TOP_call || OP_code(op) == TOP_call_uni) {
03840
03841 CGEMIT_Call (op);
03842 return;
03843 }
03844 #endif
03845
03846 bool is_intrncall = OP_code(op) == TOP_intrncall;
03847 OPS ops = OPS_EMPTY;
03848
03849 if (Trace_Inst) {
03850 fprintf (TFile, "<cgemit> transform simulated OP: ");
03851 Print_OP (op);
03852 }
03853
03854 Exp_Simulated_Op (op, &ops, PC);
03855 if (is_intrncall && Object_Code) {
03856 Em_Add_New_Content (CK_NO_XFORM, PC, OPS_length(&ops)*4, 0, PU_section);
03857 }
03858
03859 if (Trace_Inst) {
03860 fprintf (TFile, "... to: ");
03861 Print_OPS (&ops);
03862 }
03863
03864 if (is_intrncall && Assembly) {
03865 ASM_DIR_NOTRANSFORM();
03866 }
03867 FOR_ALL_OPS_OPs_FWD (&ops, op) {
03868 ISA_BUNDLE bundle[ISA_PACK_MAX_INST_WORDS];
03869 INT words;
03870 Perform_Sanity_Checks_For_OP(op, FALSE);
03871 words = r_assemble_op (op, bb, bundle, 0);
03872 if (Object_Code) {
03873
03874 Em_Add_Bytes_To_Scn (PU_section, (char *)&bundle,
03875 INST_BYTES * words, INST_BYTES);
03876 }
03877 }
03878 if (is_intrncall && Assembly) {
03879 ASM_DIR_TRANSFORM();
03880 }
03881 }
03882
03883
03884
03885 #ifdef TARG_IA64
03886 static INT
03887 #else
03888 static void
03889 #endif
03890 Assemble_Bundles(BB *bb)
03891 {
03892 OP *op;
03893
03894 FmtAssert(ISA_MAX_SLOTS > 1,("Assemble_Bundles shouldn't have been called"));
03895 #ifdef TARG_IA64
03896 INT bb_cycle_count = 0;
03897 extern INT EMIT_count_cycles;
03898 extern INT Track_Split(INT template_index, UINT stop_mask, BOOL &extra);
03899 OP *last = NULL;
03900
03901 FmtAssert(ISA_MAX_SLOTS > 1,("Assemble_Bundles shouldn't have been called"));
03902
03903 if (BB_emitted(bb))
03904 return 0;
03905
03906 Set_BB_emitted(bb);
03907 #else
03908 FmtAssert(ISA_MAX_SLOTS > 1,("Assemble_Bundles shouldn't have been called"));
03909 #endif
03910
03911 for (op = BB_first_op(bb);;) {
03912 ISA_BUNDLE bundle;
03913 UINT64 slot_mask;
03914 UINT stop_mask;
03915 INT slot;
03916 OP *slot_op[ISA_MAX_SLOTS];
03917 INT ibundle;
03918
03919
03920
03921 stop_mask = 0;
03922 slot_mask = 0;
03923 #ifdef TARG_IA64
03924 for (slot = 0; op && slot < ISA_MAX_SLOTS; op = OP_far_next(op) ) {
03925 #else
03926 for (slot = 0; op && slot < ISA_MAX_SLOTS; op = OP_next(op) ) {
03927 #endif
03928 INT words;
03929 INT w;
03930 #ifdef TARG_IA64
03931 Set_BB_emitted(OP_bb(op));
03932 #endif
03933 if (OP_dummy(op)) continue;
03934
03935 if (OP_simulated(op)) {
03936 FmtAssert(slot == 0, ("can't bundle a simulated OP in BB:%d.",BB_id(bb)));
03937 Assemble_Simulated_OP(op, bb);
03938 continue;
03939 }
03940
03941 words = ISA_PACK_Inst_Words(OP_code(op));
03942 for (w = 0; w < words; ++w) {
03943 FmtAssert(slot < ISA_MAX_SLOTS,("multi-word inst extends past end of bundle in BB:%d.",BB_id(bb)));
03944 slot_op[slot++] = op;
03945
03946 #ifdef TARG_IA64
03947 slot_mask = slot_mask << ISA_TAG_SHIFT;
03948 if ( EXEC_PROPERTY_is_M_Unit(OP_code(op)) && EXEC_PROPERTY_is_I_Unit(OP_code(op)) ){
03949
03950
03951 slot_mask |= OP_m_unit(op)?
03952 ((slot-1)%ISA_MAX_SLOTS==2) ? ISA_EXEC_PROPERTY_I_Unit : ISA_EXEC_PROPERTY_M_Unit
03953 : ISA_EXEC_PROPERTY_I_Unit;
03954
03955
03956 } else { slot_mask |= ISA_EXEC_Unit_Prop(OP_code(op)); }
03957 stop_mask = stop_mask << 1;
03958 }
03959
03960
03961
03962 if (TSI_Issue_Ports(OP_code(op)).In(ip_B2) &&
03963 TSI_Issue_Ports(OP_code(op)).In(ip_B0)){
03964 slot_mask = slot_mask | ISA_EXEC_PROPERTY_B_Unit;
03965 }
03966 stop_mask |= (OP_end_group(op) != 0);
03967 #else // TARG_IA64
03968 slot_mask = (slot_mask << ISA_TAG_SHIFT) | ISA_EXEC_Unit_Prop(OP_code(op));
03969 stop_mask = stop_mask << 1;
03970 }
03971 stop_mask |= (OP_end_group(op) != 0);
03972 #endif // TARG_IA64
03973
03974 #ifndef GAS_TAGS_WORKED
03975
03976 if (OP_has_tag(op)) {
03977 fprintf(Asm_File, "\n%s:\n", LABEL_name(Get_OP_Tag(op)));
03978 }
03979 #endif
03980 }
03981
03982 if (slot == 0) break;
03983
03984
03985
03986 if (LOCS_Enable_Bundle_Formation) {
03987 FmtAssert(slot == ISA_MAX_SLOTS, ("not enough OPs for bundle in BB:%d\n",BB_id(bb)));
03988 }
03989
03990
03991
03992 for (ibundle = 0; ibundle < ISA_MAX_BUNDLES; ++ibundle) {
03993 UINT64 this_slot_mask = ISA_EXEC_Slot_Mask(ibundle);
03994 UINT32 this_stop_mask = ISA_EXEC_Stop_Mask(ibundle);
03995 if ( (slot_mask & this_slot_mask) == this_slot_mask
03996 #ifdef TARG_IA64
03997 && (stop_mask & ~1) == this_stop_mask) break;
03998 #else
03999 && stop_mask == this_stop_mask) break;
04000 #endif
04001 }
04002
04003
04004
04005 if (LOCS_Enable_Bundle_Formation) {
04006 if (Trace_Inst && ibundle == ISA_MAX_BUNDLES) {
04007 Print_OP_No_SrcLine (slot_op[0]);
04008 Print_OP_No_SrcLine (slot_op[1]);
04009 Print_OP_No_SrcLine (slot_op[2]);
04010 }
04011 #ifdef TARG_IA64
04012 if(ibundle == ISA_MAX_BUNDLES){
04013
04014
04015 Print_OP_No_SrcLine (slot_op[0]);
04016 Print_OP_No_SrcLine (slot_op[1]);
04017 Print_OP_No_SrcLine (slot_op[2]);
04018 FmtAssert(ibundle != ISA_MAX_BUNDLES,
04019 ("couldn't find bundle for slot mask=0x%llx, stop mask=0x%x in BB:%d\n",
04020 slot_mask, stop_mask, BB_id(bb)));
04021 }
04022 #else
04023 FmtAssert(ibundle != ISA_MAX_BUNDLES,
04024 ("couldn't find bundle for slot mask=0x%llx, stop mask=0x%x in BB:%d\n",
04025 slot_mask, stop_mask, BB_id(bb)));
04026 #endif
04027 }
04028
04029 #ifdef TARG_IA64
04030 BOOL split;
04031
04032 bb_cycle_count += Track_Split(ibundle, stop_mask, split);
04033 if (split && last && EMIT_count_cycles) {
04034 Set_OP_end_group(last);
04035 }
04036 last = slot_op[ISA_MAX_SLOTS-1];
04037 #endif
04038 #ifdef ISA_PRINT_BEGIN_BUNDLE
04039
04040
04041
04042 const char *begin_bundle = ISA_PRINT_BEGIN_BUNDLE;
04043 if (Assembly && EMIT_explicit_bundles) {
04044 fputc (' ', Asm_File);
04045 fprintf(Asm_File, begin_bundle, ISA_EXEC_AsmName(ibundle));
04046 fputc ('\n', Asm_File);
04047 }
04048 #endif
04049
04050
04051
04052 #ifdef TARG_IA64
04053 INT slot_i = 0;
04054 do {
04055 OP *sl_op = slot_op[slot_i];
04056 Perform_Sanity_Checks_For_OP(sl_op, TRUE);
04057 slot_i += r_assemble_op(sl_op, bb, &bundle, slot_i);
04058 } while ((slot_i < ISA_MAX_SLOTS) && (slot_i < slot));
04059 #else
04060 slot = 0;
04061 do {
04062 OP *sl_op = slot_op[slot];
04063 Perform_Sanity_Checks_For_OP(sl_op, TRUE);
04064 slot += r_assemble_op(sl_op, bb, &bundle, slot);
04065 } while (slot < ISA_MAX_SLOTS);
04066 #endif
04067
04068
04069
04070 if (Object_Code) {
04071 TI_ASM_Set_Bundle_Comp(&bundle,
04072 #ifdef TARG_IA64
04073 ISA_BUNDLE_PACK_COMP_stop,
04074 stop_mask & 1);
04075
04076 TI_ASM_Set_Bundle_Comp(&bundle,
04077 #endif
04078 ISA_BUNDLE_PACK_COMP_template,
04079 ibundle);
04080
04081 Em_Add_Bytes_To_Scn (PU_section, (char *)&bundle, INST_BYTES, INST_BYTES);
04082 }
04083 #ifdef ISA_PRINT_END_BUNDLE
04084 if (Assembly && EMIT_explicit_bundles) {
04085 fprintf(Asm_File, " %s", ISA_PRINT_END_BUNDLE);
04086 }
04087 #endif
04088 }
04089 if (Assembly) {
04090 fputc ('\n', Asm_File);
04091 }
04092 #ifdef TARG_IA64
04093 bb_cycle_count = BB_length(bb) ? BB_cycle(bb) : 0;
04094 return bb_cycle_count;
04095 #endif
04096 }
04097
04098
04099
04100
04101 #ifdef TARG_IA64
04102 static INT
04103 #else
04104 static void
04105 #endif
04106 Assemble_Ops(BB *bb)
04107 {
04108 OP *op;
04109 #ifdef TARG_IA64
04110 INT bb_cycle_count = 0;
04111 #endif
04112
04113 FmtAssert(ISA_MAX_SLOTS == 1,
04114 ("Assemble_Ops shouldn't have been called"));
04115
04116 FOR_ALL_BB_OPs_FWD(bb, op) {
04117 ISA_BUNDLE bundle[ISA_PACK_MAX_INST_WORDS];
04118 INT words;
04119
04120 #ifdef TARG_SL
04121
04122
04123 if (CG_check_quadword)
04124 Check_QuadWord_Alignment(op, bb, bundle);
04125 if (Trace_PC) {
04126 fprintf(TFile, "pc = %x\t", PC);
04127 Print_OP(op);
04128 }
04129 #endif
04130
04131 if (OP_dummy(op)) continue;
04132
04133 if (OP_simulated(op)) {
04134 Assemble_Simulated_OP(op, bb);
04135 continue;
04136 }
04137
04138 Perform_Sanity_Checks_For_OP(op, TRUE);
04139 words = r_assemble_op(op, bb, bundle, 0);
04140 #ifdef TARG_IA64
04141 if (OP_end_group(op)) bb_cycle_count++;
04142 #endif
04143
04144 if (Object_Code) {
04145 Em_Add_Bytes_To_Scn(PU_section, (char *)bundle,
04146 INST_BYTES * words, INST_BYTES);
04147 }
04148 }
04149 #ifdef TARG_IA64
04150 return bb_cycle_count;
04151 #endif
04152 }
04153
04154 #ifdef TARG_IA64
04155
04156
04157
04158
04159
04160
04161
04162
04163 static void
04164 Emit_Loop_Unrolling_Note(BB *bb, FILE *file)
04165 {
04166 BOOL anl_note = file == anl_file;
04167 BB *head = BB_loop_head_bb(bb);
04168 UINT16 unrollings = BB_unrollings(bb);
04169 ANNOTATION *info_ant = ANNOT_Get(BB_annotations(head), ANNOT_LOOPINFO);
04170 LOOPINFO *info = info_ant ? ANNOT_loopinfo(info_ant) : NULL;
04171 BOOL unroll_pragma = FALSE;
04172 ANNOTATION *unroll_ant = ANNOT_Get(BB_annotations(head), ANNOT_PRAGMA);
04173
04174 while (unroll_ant && WN_pragma(ANNOT_pragma(unroll_ant)) != WN_PRAGMA_UNROLL)
04175 unroll_ant = ANNOT_Get(ANNOT_next(unroll_ant), ANNOT_PRAGMA);
04176 if (unroll_ant) {
04177 WN *wn = ANNOT_pragma(unroll_ant);
04178 if (WN_pragma_arg1(wn) > 1) {
04179 if (WN_pragma_arg1(wn) == unrollings)
04180 unroll_pragma = TRUE;
04181 #ifndef TARG_NVISA // unrolling happens before cg so not in bb_unrollings
04182 else if (BB_innermost(bb))
04183 DevWarn("BB:%d unrolled %d times but pragma says to unroll %d times",
04184 BB_id(bb), unrollings, WN_pragma_arg1(wn));
04185 #endif // TARG_NVISA
04186 }
04187 }
04188
04189 if (unrollings > 1) {
04190 if (anl_note) {
04191 fprintf(anl_file, "\"unrolled %d times%s%s\"\n", unrollings,
04192 BB_unrolled_fully(bb) ? " (fully)" : "",
04193 unroll_pragma ? " (pragma)" : "");
04194 } else {
04195 fprintf(file, "%s<loop> unrolled %d times%s%s\n",
04196 ASM_CMNT_LINE,
04197 unrollings,
04198 BB_unrolled_fully(bb) ? " (fully)" : "",
04199 unroll_pragma ? " (pragma)" : "");
04200 }
04201 }
04202 }
04203
04204
04205
04206
04207
04208
04209
04210
04211
04212 static void
04213 Emit_Loop_Note(BB *bb, FILE *file)
04214 {
04215 BOOL anl_note = file == anl_file;
04216 BB *head = BB_loop_head_bb(bb);
04217 ANNOTATION *info_ant = ANNOT_Get(BB_annotations(head), ANNOT_LOOPINFO);
04218 LOOPINFO *info = info_ant ? ANNOT_loopinfo(info_ant) : NULL;
04219
04220 if (bb == head) {
04221 SRCPOS srcpos = BB_Loop_Srcpos(bb);
04222 INT32 lineno = SRCPOS_linenum(srcpos);
04223
04224 if (anl_note) {
04225 INT32 fileno = SRCPOS_filenum(srcpos);
04226 INT32 colno = SRCPOS_column(srcpos);
04227 fprintf (anl_file,
04228 "\nmsg loop lines [%d %d %d]",
04229 fileno,
04230 lineno,
04231 colno);
04232 } else {
04233 fprintf (file, "// <lentry>\n");
04234 }
04235
04236
04237
04238
04239
04240
04241
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252 } else if (anl_note) {
04253
04254
04255
04256 return;
04257 } else {
04258 ANNOTATION *lbl_ant = ANNOT_Get(BB_annotations(head), ANNOT_LABEL);
04259 DevAssert(lbl_ant, ("loop head BB:%d has no label", BB_id(head)));
04260 fprintf(file,
04261 "%s<loop> Part of loop body line %d"
04262 ", head labeled %s\n",
04263 ASM_CMNT_LINE, BB_Loop_Lineno(head), LABEL_name(ANNOT_label(lbl_ant)));
04264 }
04265 }
04266
04267 static void Emit_Preds_And_Succs(BB*bb, FILE *file)
04268 {
04269 BBLIST *bb_succs = BB_succs(bb);
04270 BBLIST *bb_preds = BB_preds(bb);
04271
04272 fprintf(file, "// Block: %d ", BB_id(bb));
04273
04274 fprintf(file, "Pred: ");
04275
04276 if (BBlist_Len(bb_preds)>0) {
04277 BBLIST *pred;
04278
04279
04280 FOR_ALL_BBLIST_ITEMS(bb_preds, pred) {
04281 fprintf(file, "%d ", BB_id(BBLIST_item(pred)));
04282 }
04283 }
04284
04285 fprintf(file, "Succ: ");
04286
04287 if (BBlist_Len(bb_succs)>0) {
04288 BBLIST *succ;
04289
04290 FOR_ALL_BBLIST_ITEMS(bb_succs, succ) {
04291 fprintf(file, "%d ", BB_id(BBLIST_item(succ)));
04292 }
04293 }
04294 fprintf(file, "\n");
04295 }
04296 #else // TARG_IA64
04297
04298
04299
04300
04301
04302
04303
04304
04305 static void
04306 Emit_Loop_Note(BB *bb, FILE *file)
04307 {
04308 BOOL anl_note = file == anl_file;
04309 BB *head = BB_loop_head_bb(bb);
04310 UINT16 unrollings = BB_unrollings(bb);
04311 ANNOTATION *info_ant = ANNOT_Get(BB_annotations(head), ANNOT_LOOPINFO);
04312 LOOPINFO *info = info_ant ? ANNOT_loopinfo(info_ant) : NULL;
04313 BOOL unroll_pragma = FALSE;
04314 ANNOTATION *unroll_ant = ANNOT_Get(BB_annotations(head), ANNOT_PRAGMA);
04315
04316 while (unroll_ant && WN_pragma(ANNOT_pragma(unroll_ant)) != WN_PRAGMA_UNROLL)
04317 unroll_ant = ANNOT_Get(ANNOT_next(unroll_ant), ANNOT_PRAGMA);
04318 if (unroll_ant) {
04319 WN *wn = ANNOT_pragma(unroll_ant);
04320 if (WN_pragma_arg1(wn) > 1) {
04321 if (WN_pragma_arg1(wn) == unrollings)
04322 unroll_pragma = TRUE;
04323 else if (BB_innermost(bb))
04324 DevWarn("BB:%d unrolled %d times but pragma says to unroll %d times",
04325 BB_id(bb), unrollings, WN_pragma_arg1(wn));
04326 }
04327 }
04328
04329 if (bb == head) {
04330 #ifdef TARG_X8664
04331 if (CG_p2align)
04332 fputs ("\t.p2align 6,,7\n", file);
04333 #endif
04334 SRCPOS srcpos = BB_Loop_Srcpos(bb);
04335 INT32 lineno = SRCPOS_linenum(srcpos);
04336
04337 if (anl_note) {
04338 INT32 fileno = SRCPOS_filenum(srcpos);
04339 INT32 colno = SRCPOS_column(srcpos);
04340 fprintf (anl_file,
04341 "\nmsg loop lines [%d %d %d]",
04342 fileno,
04343 lineno,
04344 colno);
04345 } else {
04346 fprintf (file, "%s<loop> Loop body line %d", ASM_CMNT_LINE, lineno);
04347 }
04348
04349 if (info) {
04350 WN *wn = LOOPINFO_wn(info);
04351 TN *trip_tn = LOOPINFO_trip_count_tn(info);
04352 BOOL constant_trip = trip_tn && TN_is_constant(trip_tn);
04353 INT depth = WN_loop_depth(wn);
04354 const char *estimated = constant_trip ? "" : "estimated ";
04355 INT64 trip_count = constant_trip ? TN_value(trip_tn) :
04356 (INT64)WN_loop_trip_est(wn);
04357 const char * const fmt = anl_note
04358 ? " \"nesting depth: %d, %siterations: %lld\""
04359 : ", nesting depth: %d, %siterations: %lld";
04360
04361 fprintf (file, fmt, depth, estimated, trip_count);
04362 }
04363
04364 fputc ('\n', file);
04365 } else if (anl_note) {
04366
04367
04368
04369 return;
04370 } else {
04371 ANNOTATION *lbl_ant = ANNOT_Get(BB_annotations(head), ANNOT_LABEL);
04372 DevAssert(lbl_ant, ("loop head BB:%d has no label", BB_id(head)));
04373 fprintf(file,
04374 "%s<loop> Part of loop body line %d"
04375 ", head labeled %s\n",
04376 ASM_CMNT_LINE, BB_Loop_Lineno(head), LABEL_name(ANNOT_label(lbl_ant)));
04377 }
04378
04379 if (unrollings > 1) {
04380 if (anl_note) {
04381 fprintf(anl_file, "\"unrolled %d times%s%s\"\n", unrollings,
04382 BB_unrolled_fully(bb) ? " (fully)" : "",
04383 unroll_pragma ? " (pragma)" : "");
04384 } else {
04385 fprintf(file, "%s<loop> unrolled %d times%s%s\n",
04386 ASM_CMNT_LINE,
04387 unrollings,
04388 BB_unrolled_fully(bb) ? " (fully)" : "",
04389 unroll_pragma ? " (pragma)" : "");
04390 }
04391 }
04392 }
04393 #endif // TARG_IA64
04394
04395
04396
04397
04398
04399
04400
04401
04402
04403
04404 #ifdef TARG_IA64
04405 static INT
04406 #else
04407 static void
04408 #endif
04409 EMT_Assemble_BB ( BB *bb, WN *rwn )
04410 {
04411 ST *st;
04412 ANNOTATION *ant;
04413 RID *rid = BB_rid(bb);
04414
04415 #ifdef TARG_SL
04416 if (BB_zdl_body(bb)) {
04417 FmtAssert(BB_has_tag(bb), ("zdl body has no tag"));
04418 LABEL_IDX tag = Get_BB_Tag(bb);
04419 FmtAssert(tag!=0, ("EMT_Assemble_BB: zdl body tag is 0"));
04420 OP *last_op=BB_last_op(bb);
04421 while(last_op && OP_dummy(last_op)) {
04422 last_op=OP_prev(last_op);
04423 }
04424 FmtAssert(last_op, ("cannot find op to carry tag"));
04425 Set_OP_Tag(last_op, tag);
04426 }
04427 #endif
04428
04429 #ifdef TARG_IA64
04430 INT bb_cycle_count = 0;
04431 ROTATING_KERNEL_INFO *info ;
04432
04433 if (Trace_Inst) {
04434 #pragma mips_frequency_hint NEVER
04435 fprintf(TFile, "assemble BB %d\n", BB_id(bb));
04436 }
04437
04438
04439
04440
04441 if (BB_length(bb) == 0 && BB_next(bb) == NULL && BB_Has_Exc_Label(bb)) {
04442 fprintf(Asm_File, "//nop bb, code padding for eh only\n{ .mii\n\tnop.m 0\n\tnop.i 0\n\tnop.i 0;;\n }\n");
04443 }
04444
04445
04446 if (Assembly) {
04447 if (BB_annotations(bb) && ((ant= ANNOT_Get(BB_annotations(bb),ANNOT_ROTATING_KERNEL))!=NULL)){
04448 info = ANNOT_rotating_kernel(ant);
04449 BB_cycle(bb) = ROTATING_KERNEL_INFO_ii(info);
04450 }
04451 }
04452 if (Assembly && List_Notes) {
04453 if (Assembly) {
04454
04455 NOTE_BB_Act (bb, NOTE_PRINT_TO_FILE, Asm_File);
04456 }
04457
04458 if (Assembly) {
04459 Emit_Preds_And_Succs(bb,Asm_File);
04460 FREQ_Print_BB_Note(bb, Asm_File);
04461 }
04462
04463 if (Assembly) {
04464 if (BB_loop_head_bb(bb)) Emit_Loop_Note(bb,Asm_File);
04465 }
04466
04467 if (Assembly) {
04468
04469 fprintf(Asm_File,"// BB:%d cycle count: %d\n",BB_id(bb),BB_cycle(bb));
04470 }
04471 }
04472
04473
04474 for (ant = ANNOT_First (BB_annotations(bb), ANNOT_LABEL);
04475 ant != NULL;
04476 ant = ANNOT_Next (ant, ANNOT_LABEL))
04477 {
04478 LABEL_IDX lab = ANNOT_label(ant);
04479
04480 if ( Assembly ) {
04481 fprintf ( Asm_File, "%s:\t%s 0x%" LL_FORMAT "x\n",
04482 LABEL_name(lab), ASM_CMNT, Get_Label_Offset(lab) );
04483 }
04484 }
04485
04486
04487 if (Last_Label == LABEL_IDX_ZERO) {
04488 Last_Label = Gen_Label_For_BB (bb);
04489 Offset_From_Last_Label = 0;
04490 if (Initial_Pu_Label == LABEL_IDX_ZERO) {
04491 Initial_Pu_Label = Last_Label;
04492 }
04493 }
04494 #else // TARG_IA64
04495 #ifdef TARG_X8664
04496 if (!BB_entry(bb)) {
04497 float fall_thru_freq = 0.0;
04498 float branch_in_freq = 0.0;
04499 BBLIST *edge;
04500 BB *fall_thru_pred = BB_Fall_Thru_Predecessor(bb);
04501 FOR_ALL_BB_PREDS(bb, edge) {
04502 BB* pred = BBLIST_item(edge);
04503 BBLIST *succ_edge = BB_Find_Succ(pred, bb);
04504 FmtAssert(succ_edge != NULL, ("EMT_Assemble_BB: succ bb not found"));
04505 if (pred == fall_thru_pred) {
04506 fall_thru_freq = BB_freq(pred) * BBLIST_prob(succ_edge);
04507 } else {
04508 branch_in_freq += BB_freq(pred) * BBLIST_prob(succ_edge);
04509 }
04510 }
04511
04512 int max_skip_bytes = CG_p2align_max_skip_bytes;
04513 float branch_in_ratio = branch_in_freq / fall_thru_freq;
04514 bool add_p2align = FALSE;
04515
04516
04517 if (branch_in_freq > 100000000.0 &&
04518 branch_in_ratio > 50.0) {
04519 max_skip_bytes = 15;
04520 add_p2align = TRUE;
04521 }
04522
04523 if (add_p2align ||
04524 (CG_p2align_freq > 0 &&
04525 branch_in_freq > CG_p2align_freq &&
04526 branch_in_ratio > 0.5)) {
04527 fprintf(Asm_File, "\t.p2align 4,,%d\n", max_skip_bytes);
04528 }
04529 }
04530 #endif
04531
04532 if (Trace_Inst) {
04533 #pragma mips_frequency_hint NEVER
04534 fprintf(TFile, "assemble BB %d\n", BB_id(bb));
04535 }
04536 #endif // TARG_IA64
04537
04538 if (Assembly) {
04539 if (rid != NULL && RID_cginfo(rid) != NULL) {
04540 if (current_rid == RID_id(rid)) {
04541
04542 }
04543 else if (current_rid > 0) {
04544
04545 fprintf (Asm_File, "%s END REGION %d\n",
04546 ASM_CMNT_LINE, current_rid);
04547 if (RID_id(rid) > 0 && !RID_is_glue_code(rid)) {
04548 fprintf (Asm_File, "%s BEGIN REGION %d\n",
04549 ASM_CMNT_LINE, RID_id(rid));
04550 current_rid = RID_id(rid);
04551 }
04552 else if (RID_is_glue_code(rid)) {
04553 current_rid = 0;
04554 }
04555 else {
04556 current_rid = RID_id(rid);
04557 }
04558 }
04559 else if (RID_id(rid) > 0 && !RID_is_glue_code(rid)) {
04560
04561 fprintf (Asm_File, "%s BEGIN REGION %d\n",
04562 ASM_CMNT_LINE, RID_id(rid));
04563 current_rid = RID_id(rid);
04564 }
04565 }
04566 else if (current_rid > 0) {
04567
04568 fprintf (Asm_File, "%s END REGION %d\n", ASM_CMNT_LINE, current_rid);
04569 current_rid = 0;
04570 }
04571 }
04572 if ( BB_entry(bb) ) {
04573 #ifndef KEY
04574
04575 char *entry_name;
04576 #endif
04577 ST *entry_sym;
04578 ENTRYINFO *ent;
04579 SRCPOS entry_srcpos;
04580 ant = ANNOT_Get (BB_annotations(bb), ANNOT_ENTRYINFO);
04581 ent = ANNOT_entryinfo(ant);
04582 entry_srcpos = ENTRYINFO_srcpos(ent);
04583 entry_sym = ENTRYINFO_name(ent);
04584 #ifndef KEY
04585
04586 entry_name = ST_name(entry_sym);
04587 #endif
04588
04589
04590 #ifndef TARG_IA64
04591 if (strcmp(ST_name(entry_sym), Cur_PU_Name) != 0 &&
04592 PU_ftn_lang(Get_Current_PU())) {
04593 char *buf;
04594 LABEL *label;
04595 buf = (char *)alloca(strlen(ST_name(entry_sym)) + 32);
04596 sprintf(buf, ".LDWend_%s", ST_name(entry_sym));
04597 label = &New_LABEL(CURRENT_SYMTAB, Label_Last_BB_PU_Entry[pu_entries+1]);
04598 LABEL_Init (*label, Save_Str(buf), LKIND_DEFAULT);
04599 if (pu_entries > 0)
04600 fprintf( Asm_File,
04601 "%s:\n", LABEL_name(Label_Last_BB_PU_Entry[pu_entries]));
04602 }
04603 #endif
04604
04605
04606
04607
04608 if (entry_srcpos) Cg_Dwarf_Add_Line_Entry (PC, entry_srcpos);
04609
04610 if ( ST_is_not_used(entry_sym)) {
04611
04612 DevWarn("CG reached entry marked as unused; will ignore it (%s)\n",
04613 ST_name(entry_sym));
04614 }
04615 else {
04616 Set_ST_ofst(entry_sym, PC);
04617 if (strcmp( Cur_PU_Name, ST_name(entry_sym) ) != 0) {
04618
04619 if ( Assembly ) {
04620 fprintf ( Asm_File, "\t%s\t%s\n", AS_AENT, ST_name(entry_sym));
04621 Print_Label (Asm_File, entry_sym, 0 );
04622 }
04623 EMT_Put_Elf_Symbol (entry_sym);
04624 if ( Object_Code ) {
04625 Em_Define_Symbol (
04626 EMT_Put_Elf_Symbol(entry_sym), PC, 0, PU_section);
04627 Em_Add_New_Event (EK_ENTRY, PC, 0, 0, 0, PU_section);
04628 }
04629 }
04630 if (Object_Code) {
04631 #ifndef TARG_NVISA
04632 if ( EMIT_interface_section && !BB_handler(bb))
04633 Interface_Scn_Add_Def( entry_sym, rwn );
04634 #endif
04635 }
04636 }
04637 }
04638
04639 #ifndef TARG_IA64
04640
04641
04642 for (ant = ANNOT_First (BB_annotations(bb), ANNOT_LABEL);
04643 ant != NULL;
04644 ant = ANNOT_Next (ant, ANNOT_LABEL))
04645 {
04646 LABEL_IDX lab = ANNOT_label(ant);
04647
04648 if ( Assembly ) {
04649 #ifdef KEY
04650
04651
04652
04653
04654
04655
04656 #if !defined (TARG_X8664)
04657
04658
04659
04660
04661
04662
04663
04664 BOOL emit_label = TRUE;
04665 if( !BB_Has_Exc_Label(bb) ){
04666 if (
04667
04668
04669
04670
04671
04672
04673
04674 CG_opt_level > 0 &&
04675 BB_preds(bb) &&
04676 !BB_entry(bb) &&
04677 (BBlist_Len(BB_preds(bb)) == 1) &&
04678 (BBLIST_item(BB_preds(bb)) == bb->prev) &&
04679 (bb->ops.length == 1) &&
04680 BB_asm(bb))
04681 emit_label = FALSE;
04682 }
04683
04684 if (emit_label)
04685 #endif
04686 fprintf ( Asm_File, "%s:\n", LABEL_name(lab));
04687 #else
04688 fprintf ( Asm_File, "%s:\t%s 0x%" LL_FORMAT "x\n",
04689 LABEL_name(lab), ASM_CMNT, Get_Label_Offset(lab) );
04690 #endif
04691 }
04692 #ifdef KEY
04693 static BOOL seen_asm = FALSE;
04694 static WN *rwn_tmp = NULL;
04695 if (rwn_tmp != rwn) {
04696 rwn_tmp = rwn;
04697 seen_asm = FALSE;
04698 }
04699 if (BB_asm(bb)) {
04700 seen_asm = TRUE;
04701 }
04702 #endif
04703 #if !defined (TARG_IA64)
04704 if (Get_Label_Offset(lab) != PC) {
04705 #ifdef KEY
04706 if (!seen_asm)
04707 #endif
04708 DevWarn ("label %s offset %lld doesn't match PC %d",
04709 LABEL_name(lab), Get_Label_Offset(lab), PC);
04710 }
04711 #endif
04712 }
04713
04714
04715 if (Last_Label == LABEL_IDX_ZERO) {
04716 Last_Label = Gen_Label_For_BB (bb);
04717 Offset_From_Last_Label = 0;
04718 if (Initial_Pu_Label == LABEL_IDX_ZERO) {
04719 Initial_Pu_Label = Last_Label;
04720 }
04721 }
04722 #endif // !TARG_IA64
04723 st = BB_st(bb);
04724 if (st) {
04725 if ( Assembly ) {
04726 #ifdef TARG_IA64
04727
04728 #else
04729 fprintf ( Asm_File, "%s:\t%s 0x%" LL_FORMAT "x\n", ST_name(st), ASM_CMNT, ST_ofst(st));
04730 #endif
04731 }
04732 Is_True (ST_ofst(st) == PC, ("st %s offset %lld doesn't match PC %d",
04733 ST_name(st), ST_ofst(st), PC));
04734 Is_True ( !Has_Base_Block(st)
04735 || (ST_base(st) == (BB_cold(bb) ? cold_base : text_base)),
04736 ("sym %s base doesn't match BB:%d",
04737 ST_name(st), BB_id(bb)));
04738 FmtAssert(ST_is_export_local(st),
04739 ("ST for BB:%d not EXPORT_LOCAL", BB_id(bb)));
04740 }
04741
04742
04743 if (Assembly && List_Notes) {
04744 if (BB_loop_head_bb(bb)) {
04745 #ifdef TARG_IA64
04746 Emit_Loop_Unrolling_Note(bb, Asm_File);
04747 #else
04748 Emit_Loop_Note(bb, Asm_File);
04749 #endif
04750 }
04751 if (BB_annotations(bb) &&
04752 ANNOT_Get(BB_annotations(bb), ANNOT_ROTATING_KERNEL)){
04753 #if defined(KEY) && defined(TARG_MIPS)
04754 #if !defined(TARG_SL)
04755 Emit_KEY_SWP_Note( bb, Asm_File );
04756 #endif
04757 #elif !defined(TARG_NVISA)
04758 Emit_SWP_Note(bb, Asm_File);
04759 #endif
04760 }
04761
04762 #ifdef TARG_IA64
04763 if (BB_has_note(bb)) {
04764 NOTE_BB_Act (bb, NOTE_PRINT_TO_FILE, Asm_File);
04765 }
04766
04767 FREQ_Print_BB_Note(bb, Asm_File);
04768 #endif
04769 }
04770 if (Run_prompf) {
04771 #ifndef TARG_NVISA
04772 if (BB_loop_head_bb(bb)) {
04773 Emit_Loop_Note(bb, anl_file);
04774 }
04775
04776 if (BB_has_note(bb)) {
04777 NOTE_BB_Act (bb, NOTE_PRINT_TO_ANL_FILE, anl_file);
04778 }
04779 #endif
04780 }
04781
04782 #if Is_True_On
04783 Init_Sanity_Checking_For_BB ();
04784 #endif
04785
04786 #if !defined(TARG_IA64) && !defined(TARG_SL) && !defined(TARG_NVISA) && !defined(TARG_MIPS)
04787
04788
04789
04790
04791
04792 if(
04793 #if defined(TARG_X8664)
04794 !CG_emit_unwind_info &&
04795 #endif
04796 Assembly && (REGION_First_BB == bb) &&
04797 ( strcmp( Cur_PU_Name, "MAIN__" ) == 0 ||
04798 strcmp( Cur_PU_Name, "main" ) == 0 ) ){
04799 CGEMIT_Setup_Ctrl_Register( Asm_File );
04800 }
04801 #endif
04802 if (ISA_MAX_SLOTS > 1) {
04803 #ifdef TARG_IA64
04804 bb_cycle_count = Assemble_Bundles(bb);
04805 #else
04806 Assemble_Bundles(bb);
04807 #endif
04808 } else {
04809 #ifdef TARG_IA64
04810 bb_cycle_count = Assemble_Ops(bb);
04811 #else
04812 Assemble_Ops(bb);
04813 #endif
04814 }
04815
04816 if (Object_Code && BB_exit(bb)) {
04817 Em_Add_New_Event (EK_EXIT, PC - 2*INST_BYTES, 0, 0, 0, PU_section);
04818 }
04819 #ifdef TARG_IA64
04820 return bb_cycle_count;
04821 #endif
04822 }
04823
04824
04825
04826
04827
04828
04829
04830 #define FUDGE_ZONE 16000
04831
04832 static INT num_longb_inst_words;
04833
04834 typedef struct {
04835 BB *bb_ptr;
04836 INT32 bb_inum;
04837 struct longb_info *bb_longb;
04838 } BB_INFO;
04839
04840 static BB_INFO *bb_info;
04841
04842 typedef struct longb_info {
04843 INT bbindex;
04844 INT32 longb_inum;
04845 INT32 distance;
04846 OP *op;
04847 UINT8 opnd;
04848 struct longb_info *next;
04849 } LONGB_INFO;
04850
04851 typedef struct stub_info {
04852 struct stub_info *next;
04853 BB *stub;
04854 INT32 stub_loc;
04855 BB *targ;
04856 INT64 offset;
04857 } STUB_INFO;
04858
04859
04860
04861
04862
04863
04864
04865
04866
04867
04868
04869
04870
04871 static BB *
04872 Find_Stub_BB (const LONGB_INFO *longb, const STUB_INFO *stubs)
04873 {
04874 const STUB_INFO *stub;
04875 TN *tn = OP_opnd(longb->op, longb->opnd);
04876 BB *targ = Get_Label_BB(TN_label(tn));
04877 INT64 offset = TN_offset(tn);
04878
04879 for (stub = stubs; stub; stub = stub->next) {
04880 INT32 stub_distance;
04881 if (stub->targ != targ || stub->offset != offset) continue;
04882 stub_distance = stub->stub_loc - longb->longb_inum;
04883 if (stub_distance == 0) continue;
04884 if ((longb->distance ^ stub_distance) < 0) continue;
04885 if (stub_distance < 0) stub_distance = -stub_distance;
04886 if (stub_distance < EMIT_Long_Branch_Limit) return stub->stub;
04887 }
04888
04889 return NULL;
04890 }
04891
04892
04893 static BB *
04894 Create_Stub_BB (LONGB_INFO *longb, INT *stub_loc, BOOL fwd_branch)
04895 {
04896 INT save_idx;
04897 BB *next_bb = NULL;
04898 INT idx = longb->bbindex;
04899 BB *orig_bb = bb_info[idx].bb_ptr;
04900 BB *stub_bb = Gen_BB_Like (orig_bb);
04901
04902 if (BB_cold(orig_bb)) Set_BB_cold(stub_bb);
04903
04904 if (Trace_Longbr) {
04905 #pragma mips_frequency_hint NEVER
04906 fprintf (TFile, "Create_Stub_BB: idx: %d, stub_loc: %d, fwd:%d\n",
04907 idx, *stub_loc, fwd_branch);
04908 }
04909
04910
04911
04912
04913
04914
04915
04916
04917
04918
04919 if (fwd_branch) {
04920 while (bb_info[++idx].bb_inum < *stub_loc);
04921 save_idx = --idx;
04922 do {
04923 BB *bb = bb_info[idx].bb_ptr;
04924 BB *bb_prev = BB_prev(bb);
04925
04926
04927
04928
04929
04930
04931 if (bb_prev != NULL && !BB_in_preds(bb, bb_prev)) {
04932 next_bb = bb;
04933 save_idx = idx;
04934 break;
04935 }
04936 } while (--idx >= 0 && bb_info[idx].bb_inum > (*stub_loc - FUDGE_ZONE));
04937 }
04938 else {
04939 while (bb_info[--idx].bb_inum > *stub_loc);
04940 save_idx = ++idx;
04941 do {
04942 BB *bb = bb_info[idx].bb_ptr;
04943 BB *bb_prev = BB_prev(bb);
04944
04945
04946
04947
04948
04949
04950 if (bb_prev != NULL && !BB_in_preds(bb, bb_prev)) {
04951 next_bb = bb;
04952 save_idx = idx;
04953 break;
04954 }
04955 } while ( ++idx < PU_BB_Count
04956 && bb_info[idx].bb_inum < (*stub_loc + FUDGE_ZONE));
04957 }
04958 if (Trace_Longbr) {
04959 #pragma mips_frequency_hint NEVER
04960 fprintf (TFile, "next_bb: %p, save_idx: %d\n", next_bb, save_idx);
04961 }
04962 if (next_bb == NULL) {
04963
04964
04965
04966
04967
04968
04969 BB *branch_around_bb;
04970 BBLIST *item;
04971 TN *label_tn;
04972 ANNOTATION *ant;
04973 float prob;
04974 OP *new_op;
04975 OPS new_ops = OPS_EMPTY;
04976
04977 next_bb = bb_info[save_idx].bb_ptr;
04978
04979 Is_True(BB_prev(next_bb) && BB_in_preds(next_bb, BB_prev(next_bb)),
04980 ("branch around stub not required"));
04981
04982 branch_around_bb = Gen_BB_Like (orig_bb);
04983 if (BB_cold(orig_bb)) Set_BB_cold(branch_around_bb);
04984
04985 if (Trace_Longbr) {
04986 #pragma mips_frequency_hint NEVER
04987 fprintf (TFile, "Inserting a branch around the stub bb\n");
04988 fprintf (TFile, "Looking for BB:%d among preds of BB:%d\n",
04989 BB_id(BB_prev(next_bb)), BB_id(next_bb));
04990 Print_BB_Header(next_bb, TRUE, FALSE);
04991 }
04992
04993
04994
04995
04996 FOR_ALL_BB_PREDS(next_bb, item) {
04997 if (BBLIST_item(item) == BB_prev(next_bb)) {
04998 prob = BBLIST_prob(item);
04999 BB_freq(branch_around_bb) = BB_freq(BBLIST_item(item)) * prob;
05000 break;
05001 }
05002 }
05003 FmtAssert(item != NULL,
05004 ("Can't insert branch_around_bb; "
05005 "incomplete fallthrough pred/succ"));
05006
05007 if (BB_freq_fb_based(BB_prev(next_bb)))
05008 Set_BB_freq_fb_based(branch_around_bb);
05009 Insert_BB (branch_around_bb, BB_prev(next_bb));
05010
05011
05012
05013
05014
05015
05016 Unlink_Pred_Succ(BB_prev(branch_around_bb), next_bb);
05017 Link_Pred_Succ_with_Prob(BB_prev(branch_around_bb), branch_around_bb, prob);
05018 Link_Pred_Succ_with_Prob(branch_around_bb, next_bb, 1.0);
05019
05020 ant = ANNOT_Get (BB_annotations(next_bb), ANNOT_LABEL);
05021 label_tn = Gen_Label_TN (ANNOT_label(ant), 0);
05022 Exp_OP1 (OPC_GOTO, NULL, label_tn, &new_ops);
05023 new_op = OPS_last(&new_ops);
05024 OP_scycle(new_op) = 0;
05025 BB_Append_Op(branch_around_bb, new_op);
05026 num_longb_inst_words += OP_Real_Inst_Words(new_op);
05027 if (PROC_has_branch_delay_slot()) {
05028 Exp_Noop(&new_ops);
05029 new_op = OPS_last(&new_ops);
05030 OP_scycle(new_op) = 1;
05031 BB_Append_Op(branch_around_bb, new_op);
05032 num_longb_inst_words += OP_Real_Inst_Words(new_op);
05033 }
05034
05035 if (Trace_Longbr) {
05036 #pragma mips_frequency_hint NEVER
05037 fprintf(TFile, "Previous BB:\n");
05038 Print_BB_Header(BB_prev(branch_around_bb), TRUE, FALSE);
05039 fprintf(TFile, "Inserted branch_around_bb:\n");
05040 Print_BB_Header(branch_around_bb, TRUE, FALSE);
05041 fprintf(TFile, "Next BB:\n");
05042 Print_BB_Header(next_bb, TRUE, FALSE);
05043 fprintf(TFile, "====== end of branch-around insertion ========\n");
05044 }
05045 }
05046 *stub_loc = bb_info[save_idx].bb_inum;
05047 if (Trace_Longbr) {
05048 #pragma mips_frequency_hint NEVER
05049 ANNOTATION *ant = ANNOT_Get (BB_annotations(next_bb), ANNOT_LABEL);
05050 fprintf (TFile, "Inserting stub bb before bb: %s\n",
05051 LABEL_name(ANNOT_label(ant)));
05052 }
05053 Insert_BB (stub_bb, BB_prev(next_bb));
05054 return stub_bb;
05055 }
05056
05057 static void
05058 Recompute_Label_Offset(INT32 pcs[2])
05059 {
05060 BB *bb;
05061 INT32 cur_pcs[2];
05062
05063
05064 cur_pcs[IHOT] = text_PC;
05065 cur_pcs[ICOLD] = cold_PC;
05066 for (bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
05067 ANNOTATION *ant;
05068 OP *op;
05069 INT isect = BB_cold(bb) ? ICOLD : IHOT;
05070 INT32 cur_pc = cur_pcs[isect];
05071 LABEL_IDX lab;
05072 ST *st = BB_st(bb);
05073 if (st) {
05074 Set_ST_ofst(st, cur_pc);
05075 Set_ST_base(st, BB_cold(bb) ? cold_base : text_base);
05076 }
05077 for (ant = ANNOT_First (BB_annotations(bb), ANNOT_LABEL);
05078 ant != NULL;
05079 ant = ANNOT_Next (ant, ANNOT_LABEL))
05080 {
05081 lab = ANNOT_label(ant);
05082 Set_Label_Offset(lab, cur_pc);
05083 }
05084 for (op = BB_first_op(bb); op; op = OP_next(op)) {
05085 if (OP_has_tag(op)) {
05086 lab = Get_OP_Tag(op);
05087 Set_Label_Offset(lab, cur_pc);
05088 }
05089 INT num_inst_words = OP_Real_Inst_Words (op);
05090 cur_pc = PC_Incr_N(cur_pc, num_inst_words);
05091 #if defined(TARG_SL)
05092 if (trace_pc) {
05093 fprintf(TFile, "second: %10d\t ", cur_pc);
05094 Print_OP(op);
05095 }
05096 #endif
05097 }
05098 cur_pcs[isect] = cur_pc;
05099 }
05100
05101 Is_True(cur_pcs[IHOT] == pcs[IHOT],
05102 ("Recompute_Label_Offsets: hot region PC mismatch (%d vs %d).",
05103 cur_pcs[IHOT], pcs[IHOT]));
05104 Is_True(cur_pcs[ICOLD] == pcs[ICOLD],
05105 ("Recompute_Label_Offsets: cold region PC mismatch (%d vs %d).",
05106 cur_pcs[ICOLD], pcs[ICOLD]));
05107 }
05108
05109
05110
05111
05112
05113
05114 static INT
05115 BB_Info_Maintain_Sort (BB_INFO *bb_info,
05116 INT n_bb_info,
05117 INT bbindex,
05118 INT stub_len)
05119
05120 {
05121 INT i = bbindex + 1;
05122
05123 FmtAssert(bbindex < n_bb_info,
05124 ("Reference to BB:%2d out of range", bbindex));
05125
05126
05127
05128
05129 for ( ;
05130 i < n_bb_info &&
05131 bb_info[bbindex].bb_inum > bb_info[i].bb_inum;
05132 ++i) ;
05133
05134
05135
05136
05137
05138 if (i == bbindex + 1) {
05139 for ( ;
05140 i > 0 &&
05141 bb_info[bbindex].bb_inum <= bb_info[i - 1].bb_inum;
05142 --i) ;
05143 ++i;
05144 }
05145
05146
05147
05148 if (i != bbindex + 1) {
05149 BB_INFO temp = bb_info[bbindex];
05150 LONGB_INFO *longb_list;
05151
05152 while (i <= bbindex) {
05153 Is_True(bb_info[bbindex - 1].bb_inum >= temp.bb_inum,
05154 ("Moving too low a BB upward"));
05155 bb_info[bbindex] = bb_info[bbindex - 1];
05156 if ((longb_list = bb_info[bbindex - 1].bb_longb) != NULL) {
05157 for (Is_True(longb_list->bbindex == bbindex - 1,
05158 ("Rotate right: longb_list->bbindex == %d; should be %d",
05159 longb_list->bbindex, bbindex - 1));
05160 (longb_list != NULL) && (longb_list->bbindex == bbindex - 1);
05161 longb_list = longb_list->next) {
05162 ++(longb_list->bbindex);
05163 }
05164 }
05165 --bbindex;
05166 }
05167 bb_info[bbindex] = temp;
05168 while (i > bbindex + 1) {
05169 Is_True(bb_info[bbindex + 1].bb_inum < temp.bb_inum,
05170 ("Moving too high a BB downward"));
05171 bb_info[bbindex] = bb_info[bbindex + 1];
05172 if ((longb_list = bb_info[bbindex + 1].bb_longb) != NULL) {
05173 for (Is_True(longb_list->bbindex == bbindex + 1,
05174 ("Rotate left: longb_list->bbindex == %d; should be %d",
05175 longb_list->bbindex, bbindex + 1));
05176 (longb_list != NULL) && (longb_list->bbindex == bbindex + 1);
05177 longb_list = longb_list->next) {
05178 --(longb_list->bbindex);
05179 }
05180 }
05181 ++bbindex;
05182 }
05183 bb_info[bbindex] = temp;
05184 }
05185
05186
05187
05188
05189 for (i = bbindex + 1; i < n_bb_info; ++i) {
05190 bb_info[i].bb_inum += stub_len;
05191 }
05192 return bbindex;
05193 }
05194
05195
05196
05197
05198
05199
05200
05201
05202
05203
05204
05205
05206
05207
05208 static INT
05209 Compare_Long_Branches(const void *p1, const void *p2)
05210 {
05211
05212
05213
05214
05215 enum {
05216 sort_1_before_2 = -1,
05217 sort_1_after_2 = 1,
05218 sort_1_same_2 = 0
05219 };
05220 LONGB_INFO *lb1 = *(LONGB_INFO **)p1;
05221 LONGB_INFO *lb2 = *(LONGB_INFO **)p2;
05222 INT32 dist1 = lb1->distance;
05223 INT32 dist2 = lb2->distance;
05224 INT32 targ1 = lb1->longb_inum + dist1;
05225 INT32 targ2 = lb2->longb_inum + dist2;
05226
05227 if ((dist1 ^ dist2) < 0) {
05228
05229
05230 return dist1 < 0 ? sort_1_after_2 : sort_1_before_2;
05231 } else if (dist1 < 0) {
05232
05233
05234 if (targ1 > targ2) {
05235 return sort_1_after_2;
05236 } else if (targ1 < targ2) {
05237 return sort_1_before_2;
05238 } else {
05239 Is_True(dist1 != dist2, ("two branches from the same address???"));
05240 return dist1 > dist2 ? sort_1_before_2 : sort_1_after_2;
05241 }
05242 } else {
05243
05244
05245 if (targ1 > targ2) {
05246 return sort_1_before_2;
05247 } else if (targ1 < targ2) {
05248 return sort_1_after_2;
05249 } else {
05250 Is_True(dist1 != dist2, ("two branches from the same address???"));
05251 return dist1 > dist2 ? sort_1_before_2 : sort_1_after_2;
05252 }
05253 }
05254 }
05255
05256
05257
05258
05259
05260
05261
05262
05263
05264
05265
05266
05267 static LONGB_INFO *
05268 Sort_Long_Branches(INT num_longb, LONGB_INFO *longb_list)
05269 {
05270 LONGB_INFO *longb;
05271 INT i;
05272 LONGB_INFO **vec = (LONGB_INFO **)alloca(sizeof(LONGB_INFO *) * num_longb);
05273
05274
05275
05276 longb = longb_list;
05277 for (i = 0; i < num_longb; ++i) {
05278 vec[i] = longb;
05279 longb = longb->next;
05280 }
05281
05282 qsort(vec, num_longb, sizeof(LONGB_INFO *), Compare_Long_Branches);
05283
05284
05285
05286 longb = NULL;
05287 for (i = num_longb - 1; i >= 0; --i) {
05288 LONGB_INFO *vec_i = vec[i];
05289 vec_i->next = longb;
05290 longb = vec_i;
05291 }
05292 return longb;
05293 }
05294
05295
05296
05297
05298
05299
05300
05301
05302
05303
05304 static void
05305 Print_Long_Branches(LONGB_INFO *longb_list)
05306 {
05307 LONGB_INFO *longb;
05308 for (longb = longb_list; longb; longb = longb->next) {
05309 fprintf(TFile, " bbindex=%d (BB:%d)"
05310 ", longb_inum=%d"
05311 ", distance=%d"
05312 ", target=%d\n",
05313 longb->bbindex, BB_id(bb_info[longb->bbindex].bb_ptr),
05314 longb->longb_inum,
05315 longb->distance,
05316 longb->longb_inum + longb->distance);
05317 }
05318 }
05319
05320
05321 static void
05322 Fixup_Long_Branches (INT32 *hot_size, INT32 *cold_size)
05323 {
05324 BB *bb;
05325 OP *op;
05326 INT32 cur_pcs[2];
05327 INT32 start_pcs[2];
05328 TN *t;
05329 INT i;
05330 INT num_bbs;
05331 INT num_longb;
05332 LONGB_INFO *longb_list, *new_longb;
05333 STUB_INFO *stubs;
05334
05335 Trace_Longbr = Get_Trace (TP_EMIT, 0x800);
05336 num_longb_inst_words = 0;
05337 bb_info = (BB_INFO *) alloca ((PU_BB_Count + 2) * sizeof (*bb_info));
05338 num_bbs = 0;
05339 num_longb = 0;
05340 longb_list = NULL;
05341 cur_pcs[IHOT] = start_pcs[IHOT] = text_PC;
05342 cur_pcs[ICOLD] = start_pcs[ICOLD] = cold_PC;
05343 for (bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
05344 INT isect = BB_cold(bb) ? ICOLD : IHOT;
05345 INT32 cur_pc = cur_pcs[isect];
05346 INT32 start_pc = start_pcs[isect];
05347 bb_info[num_bbs].bb_ptr = bb;
05348 bb_info[num_bbs].bb_inum = cur_pc - start_pc;
05349 bb_info[num_bbs].bb_longb = NULL;
05350 for (op = BB_first_op(bb); op; op = OP_next(op)) {
05351 INT num_inst_words = OP_Real_Inst_Words (op);
05352 if (OP_xfer(op)) {
05353 for (i = 0; i < OP_opnds(op); i++) {
05354 t = OP_opnd(op,i);
05355 if (TN_is_label(t) && OP_opnd_is_pcrel(op,i)) {
05356 LABEL_IDX lab = TN_label(t);
05357 INT64 val = Get_Label_Offset(lab) + TN_offset(t) - PC_Bundle(cur_pc);
05358 if (PROC_has_branch_delay_slot()) val -= sizeof(ISA_PACK_INST);
05359 if (val > -EMIT_Long_Branch_Limit && val < EMIT_Long_Branch_Limit) break;
05360 if (Trace_Longbr) {
05361 #pragma mips_frequency_hint NEVER
05362 fprintf (TFile, "Found a long branch to %s, ", LABEL_name(lab));
05363 fprintf (TFile, "location: %d, distance: %lld\n",
05364 cur_pc - start_pc, val);
05365 }
05366 new_longb = (LONGB_INFO *)alloca (sizeof(LONGB_INFO));
05367 new_longb->bbindex = num_bbs;
05368 new_longb->longb_inum = cur_pc - start_pc;
05369 new_longb->distance = val;
05370 new_longb->op = op;
05371 new_longb->opnd = i;
05372 new_longb->next = longb_list;
05373 longb_list = new_longb;
05374 bb_info[num_bbs].bb_longb = new_longb;
05375 ++num_longb;
05376 }
05377 }
05378 }
05379 else if (OP_branch_predict(op)) {
05380
05381
05382
05383 for (i = 0; i < OP_opnds(op); i++) {
05384 t = OP_opnd(op,i);
05385 if ((TN_is_label(t) || TN_is_tag(t)) && OP_opnd_is_pcrel(op,i)) {
05386 LABEL_IDX lab = TN_label(t);
05387 INT64 val = Get_Label_Offset(lab) + TN_offset(t) - PC_Bundle(cur_pc);
05388 if ( ! ISA_LC_Value_In_Class (val, OP_opnd_lit_class(op, i))) {
05389
05390 OP *new_op;
05391 OPS new_ops;
05392 OPS_Init(&new_ops);
05393 DevWarn("%s label %s doesn't fit; replace with nop",
05394 TOP_Name(OP_code(op)), LABEL_name(lab));
05395 Exp_Noop(&new_ops);
05396 new_op = OPS_last(&new_ops);
05397 OP_scycle(new_op) = OP_scycle(op);
05398
05399 OP_Change_Opcode(new_op,
05400 CGTARG_Noop_Top (ISA_EXEC_Unit_Prop(OP_code(op))) );
05401 BB_Insert_Op_After (bb, op, new_op);
05402 BB_Remove_Op (bb, op);
05403 op = new_op;
05404 break;
05405 }
05406 }
05407 }
05408 }
05409 cur_pc = PC_Incr_N(cur_pc, num_inst_words);
05410 #if defined(TARG_SL)
05411 if (trace_pc) {
05412 fprintf(TFile, "third: %10d\t", cur_pc);
05413 Print_OP(op);
05414 }
05415 #endif
05416 }
05417 cur_pcs[isect] = cur_pc;
05418 num_bbs++;
05419 }
05420
05421 longb_list = Sort_Long_Branches(num_longb, longb_list);
05422 if (Trace_Longbr) {
05423 #pragma mips_frequency_hint NEVER
05424 fprintf(TFile, "\nLong branches after sorting:\n");
05425 Print_Long_Branches(longb_list);
05426 }
05427
05428 stubs = NULL;
05429 for (; longb_list != NULL; longb_list = longb_list->next) {
05430 BOOL fwd_branch = (longb_list->distance > 0);
05431 INT br_limit = (fwd_branch ? EMIT_Long_Branch_Limit : -EMIT_Long_Branch_Limit);
05432 INT stub_loc = longb_list->longb_inum + br_limit;
05433 INT tgt_loc = longb_list->longb_inum + longb_list->distance;
05434 TN *tgt_tn = OP_opnd(longb_list->op, longb_list->opnd);
05435 BB *tgt_bb = Get_Label_BB(TN_label(tgt_tn));
05436 while ((fwd_branch && stub_loc < tgt_loc) ||
05437 (!fwd_branch && stub_loc > tgt_loc))
05438 {
05439 BBLIST *item;
05440 STUB_INFO *stub_info;
05441 BB *longb_bb;
05442 BB *stub_bb;
05443 TN *label_tn;
05444 TN *old_label_tn;
05445 BB *old_tgt_bb;
05446 OP *new_op;
05447 OPS new_ops;
05448 INT stub_inst_words;
05449 INT stub_bytes;
05450 float longb_prob;
05451 INT pc_idx;
05452
05453 if (Trace_Longbr) {
05454 #pragma mips_frequency_hint NEVER
05455 fprintf(TFile, "========= Creating a stub BB ========\n");
05456 fprintf(TFile, " BB with long branch:\n");
05457 Print_BB_Header(bb_info[longb_list->bbindex].bb_ptr, TRUE, FALSE);
05458 }
05459 old_label_tn = OP_opnd(longb_list->op, longb_list->opnd);
05460 old_tgt_bb = Get_Label_BB(TN_label(old_label_tn));
05461 longb_bb = bb_info[longb_list->bbindex].bb_ptr;
05462
05463
05464
05465 if (Trace_Longbr) {
05466 #pragma mips_frequency_hint NEVER
05467 fprintf(TFile, "Looking for branch target BB (labeled %s)\n",
05468 LABEL_name(TN_label(old_label_tn)));
05469 }
05470 FOR_ALL_BB_SUCCS(longb_bb, item) {
05471 if (old_tgt_bb == BBLIST_item(item)) {
05472 longb_prob = BBLIST_prob(item);
05473 if (Trace_Longbr) {
05474 #pragma mips_frequency_hint NEVER
05475 fprintf(TFile, "Found BB:%2d labeled %s\n",
05476 BB_id(BBLIST_item(item)),
05477 LABEL_name(TN_label(old_label_tn)));
05478 }
05479 break;
05480 }
05481 }
05482 FmtAssert(item != NULL,
05483 ("Didn't find branch target BB among successors!"));
05484
05485
05486
05487
05488
05489 stub_bb = Find_Stub_BB(longb_list, stubs);
05490 if (stub_bb) {
05491 if (Trace_Longbr) {
05492 #pragma mips_frequency_hint NEVER
05493 fprintf (TFile, "Targetting existing stub-bb: BB:%d\n", BB_id(stub_bb));
05494 }
05495 BB_freq(stub_bb) += longb_prob * BB_freq(longb_bb);
05496
05497 label_tn = Gen_Label_TN (Gen_Label_For_BB (stub_bb), 0);
05498 Set_OP_opnd(longb_list->op, longb_list->opnd, label_tn);
05499
05500 Unlink_Pred_Succ(longb_bb, old_tgt_bb);
05501 Link_Pred_Succ_with_Prob(longb_bb, stub_bb, longb_prob);
05502
05503 break;
05504 }
05505
05506
05507
05508 stub_inst_words = num_longb_inst_words;
05509 stub_bb = Create_Stub_BB (longb_list, &stub_loc, fwd_branch);
05510
05511
05512
05513
05514
05515
05516
05517
05518 if (stubs && stubs->targ != tgt_bb) stubs = NULL;
05519 stub_info = (STUB_INFO *)alloca(sizeof(STUB_INFO));
05520 stub_info->stub = stub_bb;
05521 stub_info->stub_loc = stub_loc;
05522 stub_info->targ = tgt_bb;
05523 stub_info->offset = TN_offset(tgt_tn);
05524 stub_info->next = stubs;
05525 stubs = stub_info;
05526
05527
05528
05529 BB_freq(stub_bb) = longb_prob * BB_freq(longb_bb);
05530
05531 Unlink_Pred_Succ(longb_bb, old_tgt_bb);
05532 Link_Pred_Succ_with_Prob(longb_bb, stub_bb, longb_prob);
05533 Link_Pred_Succ_with_Prob(stub_bb, old_tgt_bb, 1.0);
05534
05535 if (Trace_Longbr) {
05536 #pragma mips_frequency_hint NEVER
05537 fprintf (TFile, "Location of stub-bb: %d\n", stub_loc);
05538 }
05539 label_tn = Gen_Label_TN (Gen_Label_For_BB (stub_bb), 0);
05540 Set_OP_opnd(longb_list->op, longb_list->opnd, label_tn);
05541 OPS_Init(&new_ops);
05542 Exp_OP1 (OPC_GOTO, NULL, old_label_tn, &new_ops);
05543 new_op = OPS_last(&new_ops);
05544
05545 longb_list->op = new_op;
05546 longb_list->opnd = OP_find_opnd_use(new_op, OU_target);
05547 longb_list->longb_inum = stub_loc;
05548
05549
05550
05551
05552
05553 bb_info[longb_list->bbindex].bb_ptr = stub_bb;
05554
05555
05556
05557
05558
05559
05560
05561
05562
05563
05564
05565
05566
05567
05568
05569
05570
05571
05572
05573
05574
05575
05576
05577
05578
05579
05580
05581
05582
05583
05584
05585
05586
05587
05588
05589
05590
05591
05592
05593
05594
05595 bb_info[longb_list->bbindex].bb_inum = stub_loc;
05596
05597
05598
05599 OP_scycle(new_op) = 0;
05600 BB_Append_Op(stub_bb, new_op);
05601 num_longb_inst_words += OP_Real_Inst_Words(new_op);
05602 if (PROC_has_branch_delay_slot()) {
05603 Exp_Noop(&new_ops);
05604 new_op = OPS_last(&new_ops);
05605 OP_scycle(new_op) = 1;
05606 BB_Append_Op(stub_bb, new_op);
05607 num_longb_inst_words += OP_Real_Inst_Words(new_op);
05608 }
05609
05610 stub_inst_words = num_longb_inst_words - stub_inst_words;
05611 stub_bytes = stub_inst_words * INST_BYTES;
05612
05613 pc_idx = BB_cold(stub_bb) ? ICOLD : IHOT;
05614 cur_pcs[pc_idx] = PC_Incr_N(cur_pcs[pc_idx], stub_inst_words);
05615
05616 longb_list->bbindex = BB_Info_Maintain_Sort(bb_info,
05617 num_bbs,
05618 longb_list->bbindex,
05619 stub_bytes);
05620
05621
05622
05623 for (stub_info = stubs->next; stub_info; stub_info = stub_info->next) {
05624 if (stub_info->stub_loc >= stub_loc) {
05625 stub_info->stub_loc += stub_bytes;
05626 }
05627 }
05628
05629 if (Trace_Longbr) {
05630 #pragma mips_frequency_hint NEVER
05631 INT num_longb_inst_bytes = num_longb_inst_words * INST_BYTES;
05632 fprintf (TFile, "Number of instruction bytes in branch stubs: %d\n",
05633 num_longb_inst_bytes * INST_BYTES);
05634 if (num_longb_inst_bytes > ((MIN_BRANCH_DISP - EMIT_Long_Branch_Limit)))
05635 fprintf (TFile, "ERROR: too many long branches\n");
05636 fprintf (TFile, "New stub BB:\n");
05637 Print_BB_Header(stub_bb, TRUE, FALSE);
05638 }
05639 stub_loc += br_limit;
05640 }
05641 if (Trace_Longbr) {
05642 #pragma mips_frequency_hint NEVER
05643 fprintf (TFile, "--- Resolved\n");
05644 }
05645 }
05646
05647 Recompute_Label_Offset(cur_pcs);
05648 *hot_size = cur_pcs[IHOT] - text_PC;
05649 *cold_size = cur_pcs[ICOLD] - cold_PC;
05650 }
05651
05652
05653
05654
05655
05656
05657 static BOOL
05658 Branch_Skips_First_Op (BB *pred, BB *succ)
05659 {
05660 OP *op;
05661
05662 if (BB_next(pred) == succ) return FALSE;
05663
05664 op = BB_branch_op (pred);
05665 if (op != NULL) {
05666 INT i;
05667 for (i = 0; i < OP_opnds(op); i++) {
05668 TN *opnd_tn = OP_opnd(op,i);
05669 if (TN_is_label(opnd_tn) && TN_offset(opnd_tn) != 0) return TRUE;
05670 }
05671 }
05672 return FALSE;
05673 }
05674
05675 static INT
05676 Num_of_OPs_in_First_Group(BB* bb)
05677 {
05678 INT Num_of_OPs = 0;
05679 OP* op;
05680
05681 for ( op = BB_first_op(bb); op; op = OP_next(op) ) {
05682
05683 if (OP_dummy(op)) continue;
05684
05685 Num_of_OPs++;
05686
05687 if (OP_end_group(op)) break;
05688 }
05689
05690 return Num_of_OPs;
05691 }
05692
05693
05694
05695
05696
05697 INT
05698 Check_If_Should_Align_BB (BB *bb, INT32 curpc)
05699 {
05700 BBLIST *preds;
05701 INT32 targpc;
05702 float skip_freq = 0.01;
05703 float noskip_freq = 0.01;
05704 INT targ_alignment;
05705 INT num_of_ops = 0;
05706 #ifdef TARG_IA64
05707 #define FREQUENT_BB_DIFF 10.0
05708 #else
05709 #define FREQUENT_BB_DIFF 5.0
05710 #endif
05711
05712 #ifdef TARG_SL
05713
05714 return 0;
05715 #endif
05716
05717
05718
05719
05720
05721
05722 if (OPT_Space)
05723 return 0;
05724 if (BB_freq(bb) <= 1.0)
05725 return 0;
05726 if (BB_prev(bb) == NULL)
05727 return 0;
05728 #ifdef TARG_IA64
05729
05730 if (Num_of_OPs_in_First_Group(bb) <= ISA_MAX_SLOTS)
05731 return 0;
05732
05733
05734 if (!BB_loophead(bb) &&
05735 (BB_freq(BB_prev(bb)) ? BB_freq(bb) / BB_freq(BB_prev(bb)) < FREQUENT_BB_DIFF : TRUE))
05736 #else
05737 if (BB_freq(bb) / BB_freq(BB_prev(bb)) < FREQUENT_BB_DIFF)
05738 #endif
05739 return 0;
05740
05741
05742 FOR_ALL_BB_PREDS (bb, preds) {
05743 if (Branch_Skips_First_Op (BBLIST_item(preds), bb)) {
05744 skip_freq += BB_freq(BBLIST_item(preds));
05745 } else {
05746 noskip_freq += BB_freq(BBLIST_item(preds));
05747 }
05748 }
05749 if ((skip_freq / noskip_freq) > FREQUENT_BB_DIFF)
05750 targpc = PC_Incr(curpc);
05751 else if ((noskip_freq / skip_freq) > FREQUENT_BB_DIFF)
05752 targpc = curpc;
05753 else {
05754
05755
05756
05757 return 0;
05758 }
05759 if (Trace_Inst) {
05760 #pragma mips_frequency_hint NEVER
05761 fprintf(TFile, "align_bb %d: bb_freq = %f, prev_bb_freq = %f, skip_freq = %f, noskip_freq = %f\n",
05762 BB_id(bb), BB_freq(bb), BB_freq(BB_prev(bb)),
05763 skip_freq, noskip_freq);
05764 }
05765 if (Align_Instructions)
05766 targ_alignment = Align_Instructions;
05767 else
05768 targ_alignment = CGTARG_Text_Alignment();
05769 targ_alignment /= INST_BYTES;
05770 targpc /= INST_BYTES;
05771 if (Get_Trace(TP_EMIT, 0x400)) {
05772
05773
05774
05775
05776
05777
05778
05779
05780
05781
05782 #define R10K_PRIMARY_ICACHE_LINE_WORDS 16
05783 INT targ_cachesize = R10K_PRIMARY_ICACHE_LINE_WORDS;
05784 UINT ops_till_cacheline =
05785 (targ_cachesize - (targpc % targ_cachesize));
05786 INT aligned_line_crossings = BB_length(bb) / targ_cachesize;
05787 INT orig_line_crossings = (BB_length(bb) + targ_cachesize - ops_till_cacheline) / targ_cachesize;
05788 if (aligned_line_crossings < orig_line_crossings
05789 && ops_till_cacheline <= 4)
05790 {
05791 num_of_ops = ops_till_cacheline;
05792 }
05793 }
05794 else {
05795 num_of_ops = ((targ_alignment - (targpc % targ_alignment)) % targ_alignment);
05796 }
05797 return num_of_ops;
05798 }
05799
05800
05801
05802
05803 static void Pad_BB_With_Noops(BB *bb, INT num)
05804 {
05805 OP *new_op;
05806 OPS new_ops = OPS_EMPTY;
05807
05808 #ifdef TARG_IA64
05809
05810 if (ISA_MAX_ISSUE_BUNDLES == 2) Reset_OP_end_group(BB_last_op(bb));
05811
05812 if (ISA_MAX_SLOTS > 1) {
05813 UINT64 slot_mask;
05814
05815
05816
05817 slot_mask = ((UINT64 ISA_EXEC_PROPERTY_M_Unit) << ISA_TAG_SHIFT * (ISA_MAX_SLOTS -1)) +
05818 ((UINT64 ISA_EXEC_PROPERTY_F_Unit) << ISA_TAG_SHIFT * (ISA_MAX_SLOTS -2)) +
05819 ((UINT64 ISA_EXEC_PROPERTY_B2_Unit) << ISA_TAG_SHIFT * (ISA_MAX_SLOTS -3));
05820
05821 #else // TARG_IA64
05822
05823 if (ISA_MAX_SLOTS > 1) {
05824 INT ibundle;
05825 UINT64 slot_mask;
05826
05827
05828
05829
05830
05831 for (ibundle = 0; ibundle < ISA_MAX_BUNDLES; ++ibundle) {
05832 UINT32 stop_mask = ISA_EXEC_Stop_Mask(ibundle);
05833 slot_mask = ISA_EXEC_Slot_Mask(ibundle);
05834 if (stop_mask == 0) break;
05835 }
05836 #endif // TARG_IA64
05837 do {
05838 INT slot = ISA_MAX_SLOTS - 1;
05839 do {
05840 ISA_EXEC_UNIT_PROPERTY unit;
05841 unit = (ISA_EXEC_UNIT_PROPERTY)(
05842 (slot_mask >> (ISA_TAG_SHIFT * slot))
05843 & ((1 << ISA_TAG_SHIFT) - 1));
05844 Exp_Noop(&new_ops);
05845 new_op = OPS_last(&new_ops);
05846 OP_scycle(new_op) = OP_scycle(BB_last_op(bb));
05847 OP_Change_Opcode(new_op, CGTARG_Noop_Top(unit));
05848 BB_Append_Op (bb, new_op);
05849 slot -= OP_Real_Inst_Words(new_op);
05850 } while (slot >= 0);
05851 } while (--num);
05852 } else {
05853 do {
05854 Exp_Noop(&new_ops);
05855 new_op = OPS_last(&new_ops);
05856 OP_scycle(new_op) = OP_scycle(BB_last_op(bb));
05857 BB_Append_Op (bb, new_op);
05858 } while (--num);
05859 }
05860 #ifdef TARG_IA64
05861
05862 Set_OP_end_group(BB_last_op(bb));
05863 #endif
05864 }
05865
05866
05867
05868
05869
05870
05871
05872
05873
05874
05875 static void
05876 R_Resolve_Branches (ST *pu_st)
05877 {
05878 BB *bb;
05879 BB *prev_nonempty_bbs[2] = { NULL, NULL };
05880 INT32 curpcs[2];
05881 INT32 hot_size, cold_size;
05882
05883
05884 Hardware_Workarounds();
05885
05886 curpcs[IHOT] = text_PC;
05887 curpcs[ICOLD] = cold_PC;
05888 for ( bb = REGION_First_BB; bb; bb = BB_next(bb) ) {
05889 INT32 bb_start_pc;
05890 OP *op;
05891 INT32 isect = BB_cold(bb) ? ICOLD : IHOT;
05892 INT32 curpc = curpcs[isect];
05893 BB *prev_nonempty_bb = prev_nonempty_bbs[isect];
05894
05895
05896 if (prev_nonempty_bb != NULL) {
05897 INT32 num = Check_If_Should_Align_BB (bb, curpc);
05898 if (num != 0) {
05899 if (Trace_Inst) {
05900 #pragma mips_frequency_hint NEVER
05901 fprintf(TFile, "insert %d noops at bb %d\n", num, BB_id(bb));
05902 }
05903
05904 curpc += INST_BYTES * num;
05905 Pad_BB_With_Noops(prev_nonempty_bb, num);
05906 }
05907 }
05908
05909 bb_start_pc = curpc;
05910
05911 #ifndef TARG_NVISA // extra labels hurt OCG optimization
05912
05913 Gen_Label_For_BB ( bb );
05914 #endif
05915
05916 for (op = BB_first_op(bb); op; op = OP_next(op)) {
05917 INT num_inst_words = OP_Real_Inst_Words (op);
05918 curpc = PC_Incr_N(curpc, num_inst_words);
05919 }
05920
05921 if (curpc != bb_start_pc) prev_nonempty_bbs[isect] = bb;
05922
05923 curpcs[isect] = curpc;
05924 }
05925
05926 Recompute_Label_Offset(curpcs);
05927
05928 hot_size = curpcs[IHOT] - text_PC;
05929 cold_size = curpcs[ICOLD] - cold_PC;
05930
05931
05932
05933 if (hot_size >= MIN_BRANCH_DISP || cold_size >= MIN_BRANCH_DISP
05934 || CGTARG_Has_Branch_Predict())
05935 {
05936 Fixup_Long_Branches (&hot_size, &cold_size);
05937 }
05938
05939 if (generate_elf_symbols) {
05940 Em_Define_Symbol (EMT_Put_Elf_Symbol(pu_st),
05941 text_PC, hot_size, text_section);
05942 }
05943
05944 if ( Trace_Inst ) {
05945 #pragma mips_frequency_hint NEVER
05946 fprintf (TFile, "INSTS IN PROCEDURE: %d\n", hot_size + cold_size);
05947 }
05948 }
05949
05950
05951
05952
05953
05954
05955
05956
05957
05958
05959 static void
05960 Trace_Init_Loc ( INT scn_idx, Elf64_Xword scn_ofst, INT32 repeat)
05961 {
05962
05963
05964
05965 #ifdef TARG_IA64
05966
05967
05968 if (em_scn[scn_idx].sym)
05969 #endif
05970 fprintf ( TFile, "<init>: Section %s (offset %4lld x%d): ",
05971 ST_name(em_scn[scn_idx].sym), (INT64)scn_ofst, repeat );
05972 }
05973
05974
05975 #ifndef TARG_IA64
05976
05977 static int exception_table_id=0;
05978 const char *lsda_ttype_base = ".LSDATTYPEB";
05979 const char *lsda_ttype_disp = ".LSDATTYPED";
05980 const char *lsda_cs_begin = ".LSDACSB";
05981 const char *lsda_cs_end = ".LSDACSE";
05982
05983 static Elf64_Word Write_Diff (LABEL_IDX, LABEL_IDX, INT, Elf64_Word);
05984
05985 static Elf64_Xword Handle_EH_Region_Length (LABEL_IDX l,
05986 INT scn_idx, Elf64_Xword scn_ofst)
05987 {
05988 static bool first_label_seen = false;
05989 static LABEL_IDX first_label=0;
05990
05991
05992 if (!first_label_seen)
05993 {
05994 FmtAssert (first_label==0,("EH table processing error"));
05995 first_label_seen = true;
05996 first_label = l;
05997 }
05998 else
05999 {
06000 FmtAssert (first_label!=0,("EH table processing error"));
06001 scn_ofst = Write_Diff (first_label, l, scn_idx, scn_ofst);
06002
06003 first_label_seen = false;
06004 first_label = 0;
06005 }
06006 return scn_ofst;
06007 }
06008 #endif // !TARG_IA64
06009
06010
06011
06012
06013
06014
06015
06016
06017
06018
06019 static Elf64_Word
06020 Write_TCON (
06021 TCON *tcon,
06022 INT scn_idx,
06023 Elf64_Xword scn_ofst,
06024 INT32 repeat
06025 #ifdef KEY
06026 #if !defined(TARG_IA64)
06027 , bool etable = 0
06028 , int format = 0
06029 #endif
06030 #endif
06031 )
06032 {
06033 BOOL add_null = TCON_add_null(*tcon);
06034 pSCNINFO scn = em_scn[scn_idx].scninfo;
06035
06036 if (Trace_Init) {
06037 #pragma mips_frequency_hint NEVER
06038 Trace_Init_Loc ( scn_idx, scn_ofst, repeat);
06039 fprintf (TFile, "TCON: >>%s<<\n", Targ_Print (NULL, *tcon));
06040 }
06041 if (Assembly) {
06042 INT32 scn_ofst32 = (INT32)scn_ofst;
06043 FmtAssert(scn_ofst32 == scn_ofst, ("section offset exceeds 32 bits: 0x%llx",
06044 (INT64)scn_ofst));
06045 #if !defined(TARG_IA64) && !defined(TARG_SL) && !defined(TARG_MIPS)
06046 if (etable)
06047 Targ_Emit_EH_Const ( Asm_File, *tcon, add_null, repeat, scn_ofst32, format );
06048 else
06049 #endif // KEY
06050 Targ_Emit_Const ( Asm_File, *tcon, add_null, repeat, scn_ofst32 );
06051 }
06052 if (Object_Code) {
06053 Em_Targ_Emit_Const ( scn, *tcon, add_null, repeat );
06054 }
06055
06056 if ( TCON_ty(*tcon) == MTYPE_STRING )
06057 scn_ofst += (Targ_String_Length (*tcon) + (add_null ? 1 : 0)) * repeat;
06058 else
06059 scn_ofst += TY_size(Be_Type_Tbl(TCON_ty(*tcon))) * repeat;
06060
06061 return scn_ofst;
06062 }
06063
06064
06065 #ifdef TARG_IA64
06066
06067
06068
06069
06070
06071
06072
06073
06074
06075 static Elf64_Word
06076 Write_Symoff (
06077 ST * sym,
06078 Elf64_Sxword sym_ofst,
06079 INT scn_idx,
06080 Elf64_Word scn_ofst,
06081 INT32 repeat)
06082 {
06083 INT32 i;
06084 ST *basesym;
06085 INT64 base_ofst = 0;
06086 pSCNINFO scn = em_scn[scn_idx].scninfo;
06087 INT address_size = ((Use_32_Bit_Pointers) ? 4 : 8);
06088
06089
06090 if ( Trace_Init ) {
06091 #pragma mips_frequency_hint NEVER
06092 Trace_Init_Loc (scn_idx, scn_ofst, repeat);
06093 fprintf ( TFile, "SYM " );
06094 fprintf ( TFile, "%s %+lld\n", ST_name(sym), (INT64)sym_ofst );
06095 }
06096
06097
06098 if (!Has_Base_Block(sym)) {
06099 Allocate_Object(sym);
06100
06101 Is_True(!Has_Base_Block(sym) || Is_Global_Symbol(Base_Symbol(sym)),
06102 ("Write_Symoff: too late to allocate object on stack"));
06103 }
06104
06105
06106
06107
06108
06109 if (ST_sclass(sym) == SCLASS_TEXT && !Has_Base_Block(sym)) {
06110 INT32 padding;
06111 padding = repeat * address_size;
06112 if (Assembly && padding > 0) {
06113 ASM_DIR_ZERO(Asm_File, padding);
06114 }
06115 if (Object_Code) {
06116 Em_Add_Zeros_To_Scn (scn, padding, 1);
06117 }
06118 scn_ofst += padding;
06119 return scn_ofst;
06120 }
06121
06122
06123
06124 basesym = sym;
06125 if (Has_Base_Block(sym) && ST_is_export_local(sym) && ST_class(sym) != CLASS_FUNC) {
06126 Base_Symbol_And_Offset (sym, &basesym, &base_ofst);
06127 }
06128 if (Use_Separate_PU_Section (current_pu, basesym)) {
06129
06130 basesym = PU_base;
06131 }
06132 base_ofst += sym_ofst;
06133
06134 if (Object_Code && repeat != 0) {
06135 if (Use_32_Bit_Pointers) {
06136 Em_Add_New_Content (CK_SADDR_32, scn_ofst, 4*repeat, 0, scn);
06137 }
06138 else {
06139 Em_Add_New_Content (CK_SADDR_64, scn_ofst, 8*repeat, 0, scn);
06140 }
06141 }
06142
06143 for ( i = 0; i < repeat; i++ ) {
06144
06145 if (Object_Code) {
06146 if (ST_sclass(sym) == SCLASS_EH_REGION_SUPP) {
06147 Em_Add_Displacement_To_Scn (scn, EMT_Put_Elf_Symbol (basesym),
06148 base_ofst, 1);
06149 } else {
06150 Em_Add_Address_To_Scn (scn, EMT_Put_Elf_Symbol (basesym),
06151 base_ofst, 1);
06152 }
06153 }
06154 if (Assembly) {
06155 fprintf (Asm_File, "\t%s\t",
06156 (scn_ofst % address_size) == 0 ?
06157 AS_ADDRESS : AS_ADDRESS_UNALIGNED);
06158 if (ST_class(sym) == CLASS_CONST) {
06159 EMT_Write_Qualified_Name (Asm_File, basesym);
06160 fprintf (Asm_File, " %+lld\n", base_ofst);
06161 }
06162 else if (ST_class(sym) == CLASS_FUNC && AS_FPTR) {
06163 fprintf (Asm_File, " %s(", AS_FPTR);
06164 EMT_Write_Qualified_Name (Asm_File, sym);
06165 fprintf (Asm_File, " %+lld)\n", (INT64)sym_ofst);
06166 }
06167 else {
06168 EMT_Write_Qualified_Name (Asm_File, sym);
06169 fprintf (Asm_File, " %+lld\n", (INT64)sym_ofst);
06170 }
06171 if (ST_class(sym) == CLASS_FUNC) {
06172 fprintf (Asm_File, "\t%s\t", AS_TYPE);
06173 EMT_Write_Qualified_Name (Asm_File, sym);
06174 fprintf (Asm_File, ", %s\n", AS_TYPE_FUNC);
06175 }
06176 }
06177 scn_ofst += address_size;
06178 }
06179 return scn_ofst;
06180 }
06181
06182
06183
06184
06185 static Elf64_Word
06186 Write_Symiplt (
06187 ST * sym,
06188 Elf64_Sxword sym_ofst,
06189 INT scn_idx,
06190 Elf64_Word scn_ofst,
06191 INT32 repeat)
06192 {
06193 INT32 i;
06194 ST *basesym;
06195 INT64 base_ofst = 0;
06196 pSCNINFO scn = em_scn[scn_idx].scninfo;
06197 INT address_size = ((Use_32_Bit_Pointers) ? 4 : 8);
06198
06199 address_size = (address_size << 1);
06200
06201 if (Trace_Init)
06202 {
06203 #pragma mips_frequency_hint NEVER
06204 Trace_Init_Loc (scn_idx, scn_ofst, repeat);
06205 fprintf ( TFile, "SYMIPLT " );
06206 fprintf ( TFile, "%s %+lld\n", ST_name(sym), (INT64)sym_ofst );
06207 }
06208
06209 if (!Has_Base_Block(sym))
06210 {
06211 Allocate_Object(sym);
06212
06213 Is_True(!Has_Base_Block(sym) || Is_Global_Symbol(Base_Symbol(sym)),
06214 ("Write_Symiplt: too late to allocate object on stack"));
06215 }
06216
06217
06218
06219 basesym = sym;
06220 if (Use_Separate_PU_Section (current_pu, basesym))
06221
06222 basesym = PU_base;
06223 base_ofst += sym_ofst;
06224
06225 if (Object_Code && repeat != 0)
06226 {
06227 if (Use_32_Bit_Pointers)
06228 Em_Add_New_Content (CK_GADDR_32, scn_ofst, 4*repeat, 0, scn);
06229 else
06230 Em_Add_New_Content (CK_GADDR_64, scn_ofst, 8*repeat, 0, scn);
06231 }
06232
06233 if (Object_Code)
06234 Em_Add_Address_To_Scn (scn, EMT_Put_Elf_Symbol (basesym), base_ofst, 1);
06235
06236 if (Assembly)
06237 {
06238
06239 fprintf (Asm_File, "\tdata16.ua\t");
06240
06241 FmtAssert (ST_class(sym) == CLASS_FUNC && AS_IPLT,
06242 ("IPLT entry must correspond to symbol with CLASS_FUNC!"));
06243
06244 fprintf (Asm_File, " %s(", AS_IPLT);
06245 EMT_Write_Qualified_Name (Asm_File, sym);
06246 fprintf (Asm_File, " %+lld)\n", (INT64)sym_ofst);
06247 }
06248 scn_ofst += address_size;
06249 return scn_ofst;
06250 }
06251 #else // TARG_IA64
06252
06253
06254
06255
06256
06257
06258
06259
06260
06261 static Elf64_Word
06262 Write_Symbol (
06263 ST * sym,
06264 Elf64_Sxword sym_ofst,
06265 INT scn_idx,
06266 Elf64_Word scn_ofst,
06267 INT32 repeat)
06268 {
06269 INT32 i;
06270 ST *basesym;
06271 INT64 base_ofst = 0;
06272 pSCNINFO scn = em_scn[scn_idx].scninfo;
06273 INT address_size = ((Use_32_Bit_Pointers) ? 4 : 8);
06274
06275 if ( Trace_Init ) {
06276 #pragma mips_frequency_hint NEVER
06277 Trace_Init_Loc (scn_idx, scn_ofst, repeat);
06278 fprintf ( TFile, "SYM " );
06279 fprintf ( TFile, "%s %+lld\n", ST_name(sym), (INT64) sym_ofst );
06280 }
06281
06282
06283 if (!Has_Base_Block(sym)) {
06284 Allocate_Object(sym);
06285
06286 Is_True(!Has_Base_Block(sym) || Is_Global_Symbol(Base_Symbol(sym)),
06287 ("Write_Symbol: too late to allocate object on stack"));
06288 }
06289
06290
06291
06292
06293
06294 if (ST_sclass(sym) == SCLASS_TEXT && !Has_Base_Block(sym)) {
06295 INT32 padding;
06296 padding = repeat * address_size;
06297 if (Assembly && padding > 0) {
06298 #ifdef TARG_MIPS
06299 if (CG_emit_non_gas_syntax)
06300 fprintf(Asm_File, "\t%s %lld\n", ".space", (INT64)padding);
06301 else
06302 #endif
06303 ASM_DIR_ZERO(Asm_File, padding);
06304 }
06305 if (Object_Code) {
06306 Em_Add_Zeros_To_Scn (scn, padding, 1);
06307 }
06308 scn_ofst += padding;
06309 return scn_ofst;
06310 }
06311
06312
06313
06314 basesym = sym;
06315 if (Has_Base_Block(sym) && ST_is_export_local(sym) && ST_class(sym) != CLASS_FUNC) {
06316 Base_Symbol_And_Offset (sym, &basesym, &base_ofst);
06317 }
06318 if (Use_Separate_PU_Section (current_pu, basesym)) {
06319
06320 basesym = PU_base;
06321 }
06322 base_ofst += sym_ofst;
06323
06324 if (Object_Code && repeat != 0) {
06325 if (Use_32_Bit_Pointers) {
06326 Em_Add_New_Content (CK_SADDR_32, scn_ofst, 4*repeat, 0, scn);
06327 }
06328 else {
06329 Em_Add_New_Content (CK_SADDR_64, scn_ofst, 8*repeat, 0, scn);
06330 }
06331 }
06332
06333 for ( i = 0; i < repeat; i++ ) {
06334
06335 if (Object_Code) {
06336 if (ST_sclass(sym) == SCLASS_EH_REGION_SUPP) {
06337 Em_Add_Displacement_To_Scn (scn, EMT_Put_Elf_Symbol (basesym),
06338 base_ofst, 1);
06339 } else {
06340 Em_Add_Address_To_Scn (scn, EMT_Put_Elf_Symbol (basesym),
06341 base_ofst, 1);
06342 }
06343 }
06344 const char *fptr = AS_FPTR;
06345 if (Assembly) {
06346 #ifdef TARG_MIPS
06347 if (CG_emit_non_gas_syntax)
06348 fprintf(Asm_File, "\t%s\t", Use_32_Bit_Pointers ? ".word" : ".dword");
06349 else
06350 #endif
06351 fprintf (Asm_File, "\t%s\t",
06352 (scn_ofst % address_size) == 0 ?
06353 AS_ADDRESS : AS_ADDRESS_UNALIGNED);
06354 if (ST_class(sym) == CLASS_CONST) {
06355 EMT_Write_Qualified_Name (Asm_File, basesym);
06356 fprintf (Asm_File, " %+lld\n", base_ofst);
06357 }
06358 else if (ST_class(sym) == CLASS_FUNC && fptr && ! Get_Trace(TP_EMIT,0x2000)) {
06359 fprintf (Asm_File, " %s(", fptr);
06360 EMT_Write_Qualified_Name (Asm_File, sym);
06361 fprintf (Asm_File, " %+lld)\n", (INT64) sym_ofst);
06362 }
06363 else {
06364 EMT_Write_Qualified_Name (Asm_File, sym);
06365 fprintf (Asm_File, " %+lld\n", (INT64) sym_ofst);
06366 }
06367 if (ST_class(sym) == CLASS_FUNC
06368 #if defined(BUILD_OS_DARWIN)
06369 && 0
06370 #endif
06371 #ifdef TARG_MIPS
06372 && !CG_emit_non_gas_syntax
06373 #endif
06374 ) {
06375 fprintf (Asm_File, "\t%s\t", AS_TYPE);
06376 EMT_Write_Qualified_Name (Asm_File, sym);
06377 fprintf (Asm_File, ", %s\n", AS_TYPE_FUNC);
06378 }
06379 }
06380 scn_ofst += address_size;
06381 }
06382 return scn_ofst;
06383 }
06384 #endif // TARG_IA64
06385
06386
06387
06388
06389
06390
06391
06392
06393
06394 static Elf64_Word
06395 Write_Label (
06396 LABEL_IDX lab,
06397 Elf64_Sxword lab_ofst,
06398 INT scn_idx,
06399 Elf64_Word scn_ofst,
06400 INT32 repeat,
06401 INT32 flags,
06402 mTYPE_ID mtype )
06403 {
06404 INT32 i;
06405 ST *basesym;
06406 Elf64_Sxword base_ofst = 0;
06407 pSCNINFO scn = em_scn[scn_idx].scninfo;
06408 INT address_size = ((Use_32_Bit_Pointers) ? 4 : 8);
06409
06410 if ( Trace_Init ) {
06411 #pragma mips_frequency_hint NEVER
06412 Trace_Init_Loc (scn_idx, scn_ofst, repeat);
06413 fprintf ( TFile, "LAB (%d) ", (INT)lab );
06414 fprintf ( TFile, "%s %+lld\n", LABEL_name(lab), (INT64)lab_ofst );
06415 }
06416
06417 #ifdef TODO
06418
06419
06420
06421
06422
06423
06424
06425 if (!Has_Base_Block(sym)) {
06426 INT32 padding;
06427 padding = repeat * address_size;
06428 if (Assembly && padding > 0) {
06429 #ifdef TARG_MIPS
06430 if (CG_emit_non_gas_syntax)
06431 fprintf(Asm_File, "\t%s %lld\n", ".space", (INT64)padding);
06432 else
06433 #endif
06434 ASM_DIR_ZERO(Asm_File, padding);
06435 }
06436 if (Object_Code) {
06437 Em_Add_Zeros_To_Scn (scn, padding, 1);
06438 }
06439 scn_ofst += padding;
06440 return scn_ofst;
06441 }
06442 #endif
06443
06444
06445
06446 FmtAssert (Get_Label_BB(lab), ("label %d doesn't have defining bb?", lab));
06447 basesym = BB_cold(Get_Label_BB(lab)) ? cold_base : text_base;
06448 if (Use_Separate_PU_Section (current_pu, basesym)) {
06449
06450 basesym = PU_base;
06451 }
06452 base_ofst = Get_Label_Offset(lab) + lab_ofst;
06453
06454 if (Object_Code && repeat != 0) {
06455 if (Use_32_Bit_Pointers) {
06456 Em_Add_New_Content (CK_SADDR_32, scn_ofst, 4*repeat, 0, scn);
06457 }
06458 else {
06459 Em_Add_New_Content (CK_SADDR_64, scn_ofst, 8*repeat, 0, scn);
06460 }
06461 }
06462
06463 for ( i = 0; i < repeat; i++ ) {
06464 if (Assembly) {
06465
06466 if ( flags == INITVLABELFLAGS_UNUSED ) {
06467 #ifdef TARG_MIPS
06468 if (CG_emit_non_gas_syntax)
06469 fprintf(Asm_File, "\t%s\t", Use_32_Bit_Pointers ? ".word" : ".dword");
06470 else
06471 #endif
06472 fprintf (Asm_File, "\t%s\t",
06473 (scn_ofst % address_size) == 0 ?
06474 AS_ADDRESS : AS_ADDRESS_UNALIGNED);
06475
06476 fputs (LABEL_name(lab), Asm_File);
06477 if (lab_ofst != 0)
06478 fprintf (Asm_File, " %+lld", (INT64)lab_ofst);
06479 fprintf (Asm_File, "\n");
06480 }
06481 else {
06482 if ( flags == INITVLABELFLAGS_VALUES_FIRST ) {
06483 Is_True( mtype != MTYPE_UNKNOWN, ("bad mtype for label value") );
06484 INT size = MTYPE_byte_size(mtype);
06485 const char* as_size = NULL;
06486 switch (mtype) {
06487 case MTYPE_I1:
06488 as_size = AS_BYTE;
06489 break;
06490 case MTYPE_I2:
06491 as_size = (scn_ofst % size) == 0 ? AS_HALF : AS_HALF_UNALIGNED;
06492 break;
06493 case MTYPE_I4:
06494 as_size = (scn_ofst % size) == 0 ? AS_WORD : AS_WORD_UNALIGNED;
06495 break;
06496 case MTYPE_I8:
06497 as_size = (scn_ofst % size) == 0 ? AS_DWORD : AS_DWORD_UNALIGNED;
06498 break;
06499 default:
06500 FmtAssert(FALSE, ("bad mtype for label value"));
06501 }
06502 fprintf (Asm_File, "\t%s\t", as_size);
06503 }
06504 if ( flags == INITVLABELFLAGS_VALUES_PLUS ) {
06505 fputs ("+", Asm_File);
06506 }
06507 if ( flags == INITVLABELFLAGS_VALUES_MINUS ||
06508 flags == INITVLABELFLAGS_VALUES_LAST ) {
06509 fputs ("-", Asm_File);
06510 }
06511 fputs (LABEL_name(lab), Asm_File);
06512 if ( flags == INITVLABELFLAGS_VALUES_LAST ) {
06513 fprintf (Asm_File, "\n");
06514 }
06515 }
06516 }
06517 if (Object_Code) {
06518 Em_Add_Address_To_Scn (scn, EMT_Put_Elf_Symbol (basesym), base_ofst, 1);
06519 }
06520 scn_ofst += address_size;
06521 }
06522 return scn_ofst;
06523 }
06524
06525 static Elf64_Word
06526 Write_Symdiff (
06527 LABEL_IDX lab1,
06528 ST_IDX sym2idx,
06529 INT scn_idx,
06530 Elf64_Word scn_ofst,
06531 INT32 repeat,
06532 INT size
06533 #ifdef TARG_IA64
06534 , bool beh = false)
06535 #else
06536 #ifdef KEY
06537 , bool etable = 0
06538 #endif // KEY
06539 )
06540 #endif
06541 {
06542 INT32 i;
06543 ST *basesym1;
06544 ST *basesym2;
06545 INT64 base1_ofst = 0;
06546 INT64 base2_ofst = 0;
06547 pSCNINFO scn = em_scn[scn_idx].scninfo;
06548 ST *sym2 = &St_Table[sym2idx];
06549 INT32 val;
06550
06551 if ( Trace_Init ) {
06552 #pragma mips_frequency_hint NEVER
06553 Trace_Init_Loc (scn_idx, scn_ofst, repeat);
06554 fprintf ( TFile, "SYMDIFF " );
06555 fprintf ( TFile, "%s - %s\n", LABEL_name(lab1), ST_name(sym2));
06556 }
06557
06558
06559 Is_True (lab1, ("cgemit: Symdiff lab1 is null"));
06560 Is_True (sym2, ("cgemit: Symdiff sym2 is null"));
06561 Is_True (Has_Base_Block(sym2), ("cgemit: Symdiff sym2 not allocated"));
06562
06563 basesym1 = BB_cold(Get_Label_BB(lab1)) ? cold_base : text_base;
06564 base1_ofst = Get_Label_Offset(lab1);
06565 Base_Symbol_And_Offset (sym2, &basesym2, &base2_ofst);
06566 if (Use_Separate_PU_Section(current_pu,basesym2)) {
06567
06568 basesym2 = PU_base;
06569 }
06570 Is_True (basesym1 == basesym2, ("cgemit: Symdiff bases not same"));
06571 val = base1_ofst - base2_ofst;
06572 if (val < 0) val = 0;
06573 if (size == 2) {
06574 if (val > INT16_MAX) {
06575 DevWarn("symdiff value not 16-bits; will try recompiling with -TENV:long_eh_offsets");
06576 Early_Terminate (RC_OVERFLOW_ERROR);
06577 }
06578 val = val << 16;
06579 }
06580
06581 for ( i = 0; i < repeat; i++ ) {
06582 if (Assembly) {
06583 #ifdef TARG_IA64
06584 if (beh)
06585 fprintf(Asm_File, "\t.uleb128\t");
06586 else
06587 fprintf (Asm_File, "\t%s\t", (size == 2 ? AS_HALF : AS_WORD));
06588 fprintf(Asm_File, "%s", LABEL_name(lab1));
06589 fprintf (Asm_File, "-");
06590 #else
06591 #ifdef KEY
06592 if (etable)
06593 fputs ("\t.uleb128\t", Asm_File);
06594 else
06595 #endif // KEY
06596 fprintf (Asm_File, "\t%s\t", (size == 2 ? AS_HALF : AS_WORD));
06597 fputs (LABEL_name(lab1), Asm_File);
06598 fputc ('-', Asm_File);
06599 #endif // TARG_IA64
06600 EMT_Write_Qualified_Name (Asm_File, sym2);
06601 fputc ('\n', Asm_File);
06602 }
06603 if (Object_Code) {
06604 Em_Add_Bytes_To_Scn (scn, (char *) &val, size, 1);
06605 }
06606 scn_ofst += size;
06607 }
06608 return scn_ofst;
06609 }
06610
06611 #ifdef KEY
06612 #include <map>
06613 std::map<const ST*, const ST*> st_to_pic_st;
06614
06615 static Elf64_Word
06616 Emit_PIC_version (ST * st, Elf64_Word scn_ofst)
06617 {
06618 if (st_to_pic_st.find (st) == st_to_pic_st.end())
06619 {
06620 ST * pic_st = New_ST (GLOBAL_SYMTAB);
06621 STR_IDX name = Save_Str2 ("DW.ref.", ST_name (st));
06622 ST_Init(pic_st, name, CLASS_VAR, SCLASS_DGLOBAL, EXPORT_HIDDEN, MTYPE_TO_TY_array[MTYPE_U8]);
06623 Set_ST_is_weak_symbol (pic_st);
06624 Set_ST_is_initialized (pic_st);
06625 ST_ATTR_IDX st_attr_idx;
06626 ST_ATTR& st_attr = New_ST_ATTR (GLOBAL_SYMTAB, st_attr_idx);
06627 ST_ATTR_Init (st_attr, ST_st_idx (pic_st), ST_ATTR_SECTION_NAME, Save_Str2 (".gnu.linkonce.d.", ST_name (pic_st)));
06628
06629 INITV_IDX iv = New_INITV();
06630 INITV_Init_Symoff (iv, st, 0, 1);
06631 New_INITO (ST_st_idx (pic_st), iv);
06632
06633 Assign_ST_To_Named_Section (pic_st, ST_ATTR_section_name (st_attr));
06634 st_to_pic_st [st] = pic_st;
06635 }
06636
06637 fprintf (Asm_File, "\t.long\tDW.ref.%s-.\n", ST_name (st));
06638 return scn_ofst + 4;
06639 }
06640 #endif
06641
06642
06643
06644
06645
06646
06647
06648
06649
06650
06651 static Elf64_Word
06652 #ifndef TARG_IA64
06653 Write_INITV (INITV_IDX invidx, INT scn_idx, Elf64_Word scn_ofst, bool etable=0, int format=0)
06654 #else
06655 Write_INITV (INITV_IDX invidx, INT scn_idx, Elf64_Word scn_ofst)
06656 #endif // KEY
06657 {
06658 INT32 i;
06659 INITV_IDX ninv;
06660 INITV inv = Initv_Table[invidx];
06661 LABEL_IDX lab;
06662 TCON tcon;
06663 ST *st;
06664 pSCNINFO scn = em_scn[scn_idx].scninfo;
06665
06666 #ifndef TARG_IA64
06667 static bool emit_typeinfo=false;
06668 #endif
06669
06670 #if defined(TARG_SL)
06671 Elf64_Word prev_scn_ofst;
06672 Elf64_Word skip_space;
06673 #define V2BUF_SKIP_SPACE 16 // we still need to handle other vbuf type
06674 #define V4BUF_SKIP_SPACE 48
06675 #define vector_line_num 16
06676 #endif // TARG_SL
06677
06678 switch ( INITV_kind(inv) ) {
06679 case INITVKIND_ZERO:
06680 tcon = Host_To_Targ (INITV_mtype (inv), 0);
06681 #if defined(TARG_SL)
06682 if (!emit_typeinfo)
06683 {
06684 prev_scn_ofst = scn_ofst;
06685 scn_ofst = Write_TCON (&tcon, scn_idx, scn_ofst, INITV_repeat2 (inv),
06686 etable, format);
06687
06688 if(prev_scn_ofst
06689 && (ST_in_v2buf(em_scn[scn_idx].sym)
06690 || ST_in_v4buf(em_scn[scn_idx].sym)))
06691 {
06692
06693 skip_space = (ST_in_v2buf(em_scn[scn_idx].sym)) ?
06694 V2BUF_SKIP_SPACE : V4BUF_SKIP_SPACE;
06695
06696 if(!((prev_scn_ofst+1) % vector_line_num)) {
06697 ASM_DIR_SKIP(Asm_File, skip_space);
06698 scn_ofst += skip_space;
06699 }
06700 }
06701 }
06702 #else
06703 #if !defined(TARG_IA64)
06704 if (!emit_typeinfo)
06705 scn_ofst = Write_TCON (&tcon, scn_idx, scn_ofst, INITV_repeat2 (inv),
06706 etable, format);
06707 #ifdef TARG_X8664
06708 else if (Gen_PIC_Call_Shared || Gen_PIC_Shared)
06709 {
06710 fputs ("\t.long\t0\n", Asm_File);
06711 scn_ofst += 4;
06712 }
06713 #endif
06714 else
06715 #endif // TARG_IA64
06716 scn_ofst = Write_TCON (&tcon, scn_idx, scn_ofst, INITV_repeat2 (inv));
06717 #endif // TARG_SL
06718 break;
06719
06720 case INITVKIND_ONE:
06721 tcon = Host_To_Targ (INITV_mtype (inv), 1);
06722 #if defined(TARG_SL)
06723 prev_scn_ofst = scn_ofst;
06724 scn_ofst = Write_TCON (&tcon, scn_idx, scn_ofst, INITV_repeat2 (inv),
06725 etable, format);
06726
06727 if(prev_scn_ofst
06728 && (ST_in_v2buf(em_scn[scn_idx].sym)
06729 || ST_in_v4buf(em_scn[scn_idx].sym)))
06730 {
06731
06732 skip_space = (ST_in_v2buf(em_scn[scn_idx].sym)) ?
06733 V2BUF_SKIP_SPACE : V4BUF_SKIP_SPACE;
06734
06735 if(!((prev_scn_ofst+1) % vector_line_num)) {
06736 ASM_DIR_SKIP(Asm_File, skip_space);
06737 scn_ofst += skip_space;
06738 }
06739 }
06740 #else
06741 scn_ofst = Write_TCON (&tcon, scn_idx, scn_ofst, INITV_repeat2 (inv)
06742 #ifndef TARG_IA64
06743 , etable, format
06744 #endif
06745 );
06746 #endif // TARG_SL
06747 break;
06748 case INITVKIND_VAL:
06749 #ifdef TARG_SL
06750 prev_scn_ofst = scn_ofst;
06751
06752 scn_ofst = Write_TCON (&INITV_tc_val(inv), scn_idx, scn_ofst,
06753 INITV_repeat2(inv), etable, format);
06754
06755 if(prev_scn_ofst
06756 && (ST_in_v2buf(em_scn[scn_idx].sym)
06757 || ST_in_v4buf(em_scn[scn_idx].sym)))
06758 {
06759
06760 skip_space = (ST_in_v2buf(em_scn[scn_idx].sym)) ?
06761 V2BUF_SKIP_SPACE : V4BUF_SKIP_SPACE;
06762
06763 if(!((prev_scn_ofst+1) % vector_line_num)) {
06764 ASM_DIR_SKIP(Asm_File, skip_space);
06765 scn_ofst += skip_space;
06766 }
06767 }
06768 #else
06769 scn_ofst = Write_TCON (&INITV_tc_val(inv), scn_idx, scn_ofst,
06770 INITV_repeat2(inv)
06771 #ifndef TARG_IA64
06772 , etable, format
06773 #endif
06774 );
06775 #endif // TARG_SL
06776 break;
06777
06778 #ifdef TARG_IA64
06779 case INITVKIND_SYMIPLT:
06780 st = &St_Table[INITV_st(inv)];
06781 scn_ofst = Write_Symiplt (st, INITV_ofst(inv), scn_idx, scn_ofst, INITV_repeat1(inv));
06782 break;
06783 #endif
06784
06785 case INITVKIND_SYMOFF:
06786 st = &St_Table[INITV_st(inv)];
06787 #ifdef TARG_X8664
06788 if ((Gen_PIC_Call_Shared || Gen_PIC_Shared) && emit_typeinfo)
06789 {
06790 scn_ofst = Emit_PIC_version (st, scn_ofst);
06791 break;
06792 }
06793 #endif
06794 switch (ST_sclass(st)) {
06795 case SCLASS_AUTO:
06796 {
06797 tcon = Host_To_Targ(MTYPE_I4, Offset_from_FP(st));
06798 scn_ofst = Write_TCON (&tcon, scn_idx, scn_ofst, INITV_repeat1(inv));
06799 break;
06800 }
06801
06802 case SCLASS_FORMAL:
06803 {
06804 ST * base = ST_base(st);
06805 INT ofst = Offset_from_FP(base) + ST_ofst(st);
06806 tcon = Host_To_Targ(MTYPE_I4, ofst);
06807 scn_ofst = Write_TCON (&tcon, scn_idx, scn_ofst, INITV_repeat1(inv));
06808 break;
06809 }
06810
06811 default:
06812 #ifdef TARG_IA64
06813 scn_ofst = Write_Symoff ( st, INITV_ofst(inv),
06814 #else
06815 scn_ofst = Write_Symbol ( st, INITV_ofst(inv),
06816 #endif
06817 scn_idx, scn_ofst, INITV_repeat1(inv));
06818 break;
06819 }
06820 break;
06821
06822 case INITVKIND_LABEL:
06823 lab = INITV_lab(inv);
06824 #ifndef TARG_IA64
06825 if (etable)
06826 {
06827 scn_ofst = Handle_EH_Region_Length (lab, scn_idx, scn_ofst);
06828 break;
06829 }
06830 #endif
06831 scn_ofst = Write_Label (lab, 0, scn_idx, scn_ofst, INITV_repeat1(inv), INITV_lab_flags(inv), INITV_lab_mtype(inv));
06832 break;
06833 case INITVKIND_SYMDIFF:
06834 scn_ofst = Write_Symdiff ( INITV_lab1(inv), INITV_st2(inv),
06835 scn_idx, scn_ofst, INITV_repeat1(inv), 4
06836 #ifndef TARG_IA64
06837 , etable
06838 #endif
06839 );
06840 break;
06841 case INITVKIND_SYMDIFF16:
06842 scn_ofst = Write_Symdiff ( INITV_lab1(inv), INITV_st2(inv),
06843 scn_idx, scn_ofst, INITV_repeat1(inv), 2
06844 #ifndef TARG_IA64
06845 , etable
06846 #endif
06847 );
06848 break;
06849
06850 case INITVKIND_BLOCK:
06851 #ifndef TARG_IA64
06852 if (INITV_flags(inv) == INITVFLAGS_TYPEINFO)
06853 emit_typeinfo = true;
06854 #endif
06855 for (i = 0; i < INITV_repeat1(inv); i++) {
06856 for (ninv = INITV_blk(inv); ninv; ninv = INITV_next(ninv)) {
06857 scn_ofst = Write_INITV (ninv, scn_idx, scn_ofst
06858 #ifndef TARG_IA64
06859 , etable, format
06860
06861 #endif
06862 );
06863 }
06864 }
06865 #ifndef TARG_IA64
06866 if (emit_typeinfo)
06867 emit_typeinfo = false;
06868 #endif
06869 break;
06870
06871 case INITVKIND_PAD:
06872 if (Assembly && (INITV_pad(inv)*INITV_repeat1(inv) > 0)) {
06873 #ifdef TARG_MIPS
06874 if (CG_emit_non_gas_syntax)
06875 fprintf(Asm_File, "\t%s %lld\n", ".space",
06876 (INT64)(INITV_pad(inv) * INITV_repeat1(inv)));
06877 else
06878 #endif
06879 #ifdef TARG_SL
06880 {
06881 #define vector_line_size 16
06882 INT64 pad_adjustment = 0;
06883
06884 if(ST_in_v2buf(em_scn[scn_idx].sym) || ST_in_v4buf(em_scn[scn_idx].sym)) {
06885 INT64 sec_align = ST_in_v2buf(em_scn[scn_idx].sym) ? 32 : 64;
06886 pad_adjustment = (scn_ofst % vector_line_size + INITV_pad(inv)) \
06887 / vector_line_size * (sec_align-vector_line_size);
06888 scn_ofst += pad_adjustment;
06889 }
06890
06891 ASM_DIR_ZERO(Asm_File, (INITV_pad(inv) * INITV_repeat1(inv) + pad_adjustment));
06892 }
06893 #else
06894 ASM_DIR_ZERO(Asm_File, INITV_pad(inv) * INITV_repeat1(inv));
06895 #endif // TARG_SL
06896 }
06897 if (Object_Code) {
06898 Em_Add_Zeros_To_Scn (scn, INITV_pad(inv) * INITV_repeat1(inv), 1);
06899 }
06900 scn_ofst += INITV_pad(inv) * INITV_repeat1(inv);
06901 break;
06902
06903 default:
06904 break;
06905 }
06906 return scn_ofst;
06907 }
06908
06909 #ifdef TARG_IA64
06910 static int
06911 sizeof_signed_leb128 (int value)
06912 {
06913 char buff[ENCODE_SPACE_NEEDED];
06914 int size;
06915 int res = _dwarf_pro_encode_signed_leb128_nm (value, &size, buff, sizeof(buff));
06916 FmtAssert (res == DW_DLV_OK, ("Encoding for exception table failed"));
06917 return size;
06918 }
06919
06920 static Elf64_Word
06921 EH_Write_Lab_Diff (
06922 const char* lab1,
06923 const char* lab2,
06924 INT scn_idx,
06925 Elf64_Word scn_ofst)
06926 {
06927 fprintf(Asm_File, "\t.uleb128\t%s-%s\n", lab2, lab1);
06928 return scn_ofst + 4;
06929 }
06930
06931
06932 static Elf64_Word
06933 EH_Write_Sym_Diff (
06934 INITV_IDX inv,
06935 INT scn_idx,
06936 Elf64_Word scn_ofst)
06937 {
06938 return Write_Symdiff (INITV_lab1(inv), INITV_st2(inv), scn_idx, scn_ofst, 1,
06939 INITVKIND_SYMDIFF == INITV_kind(inv) ? 4 :2, true);
06940 }
06941
06942 static Elf64_Word
06943 EH_Write_Integer_const (
06944 int sym,
06945 INT scn_idx,
06946 Elf64_Word scn_ofst,
06947 bool bsigned)
06948 {
06949
06950
06951
06952
06953
06954 if (bsigned) {
06955 if (sym < 0 && sym > -129) {
06956 char c = (char)sym;
06957 unsigned char cc = *(unsigned char*)&c;
06958 cc &= 0x7f;
06959 fprintf(Asm_File, "\tdata1\t0x%2x\n", cc);
06960 }
06961 else
06962 fprintf(Asm_File, "\t.sleb128\t0x%x\n", sym);
06963 }
06964 else
06965 fprintf(Asm_File, "\t.uleb128\t0x%x\n", sym);
06966 return scn_ofst + sizeof_signed_leb128(sym);
06967 }
06968
06969 static Elf64_Word
06970 EH_Write_Integer (
06971 INITV_IDX inv,
06972 INT scn_idx,
06973 Elf64_Word scn_ofst,
06974 bool bsigned)
06975 {
06976 int sym = 0;
06977 if (INITVKIND_ZERO == INITV_kind(inv))
06978 sym = 0;
06979 else if (INITVKIND_ONE == INITV_kind(inv))
06980 sym = 1;
06981 else
06982 sym = TCON_ival(INITV_tc_val(inv));
06983 return EH_Write_Integer_const(sym, scn_idx, scn_ofst, bsigned);
06984 }
06985
06986 static void
06987 INITV_Init_Integer_2(INITV_IDX inv, TYPE_ID mtype, INT64 val, UINT16 repeat)
06988 {
06989 if (val == 0)
06990 INITV_Set_ZERO (Initv_Table[inv], mtype, repeat);
06991 else {
06992 TCON tc = Host_To_Targ (mtype, val);
06993 INITV_Set_VAL (Initv_Table[inv], Enter_tcon(tc), repeat);
06994 }
06995 }
06996
06997 static void
06998 Check_Initv(INITV_IDX idx, FILE* fp)
06999 {
07000 if (idx == 0) return;
07001 fprintf(fp, "idx = %d, type = %d, val = %d\n", (int)idx, (int)INITV_kind(idx),
07002 (INITV_kind(idx) == INITVKIND_VAL ? TCON_ival(INITV_tc_val(idx)) : -1));
07003 FmtAssert(INITVKIND_UNK != INITV_kind(idx), ("INITV.kind = UNKNOWN\n"));
07004 if (INITVKIND_BLOCK == INITV_kind(idx))
07005 Check_Initv(INITV_blk(idx), fp);
07006 Check_Initv(INITV_next(idx), fp);
07007 }
07008
07009 static void
07010 Write_LSDA_INITO (ST* st, INITO* ino, INT scn_idx, Elf64_Xword scn_ofst)
07011 {
07012 char* sym_name = ST_name(st);
07013 FmtAssert(INITO_st(ino) == st, ("Write_LSDA_INITO.st and inito are not paired.\n"));
07014 FmtAssert(sym_name != NULL &&
07015 strncmp(sym_name, ".range_table.", strlen(".range_table.")) == 0,
07016 ("Write_LSDA_INITO.ST name = %s\n", sym_name ? sym_name : "<null>"));
07017
07018
07019
07020
07021
07022
07023
07024
07025
07026
07027
07028
07029
07030 INITV_IDX inv_blk = INITO_val(*ino);
07031 FmtAssert(INITVKIND_BLOCK == INITV_kind(inv_blk), ("RangeTable.Initv1.kind != BLOCK\n"));
07032 INITV_IDX first = INITV_blk(inv_blk);
07033 INITV_IDX act_inv = (INITV_IDX)TCON_uval(INITV_tc_val(first));
07034 INITV_IDX type_inv = (INITV_IDX)TCON_uval(INITV_tc_val(act_inv));
07035 INITV_IDX eh_spec_inv = (INITV_IDX)TCON_uval(INITV_tc_val(type_inv));
07036
07037 #ifdef OSP_OPT
07038
07039
07040 if (INITV_next(first) == act_inv)
07041 return;
07042 #endif
07043
07044 static int nRangeTable = 0;
07045 nRangeTable++;
07046 char begin_lab[30], end_lab[30];
07047 INITV_IDX inv = INITV_next(first);
07048 #define LSDA_HANDLER_START "thu_LFE_"
07049 #define LSDA_START "thu_LSDA_"
07050 #define LSDA_TT_START "thu_LSDA_TT_Start_"
07051 #define LSDA_TT_END "thu_LSDA_TT_End_"
07052 #define LSDA_CS_START "thu_LSDA_CS_Start_"
07053 #define LSDA_CS_END "thu_LSDA_CS_End_"
07054
07055 fprintf(Asm_File, ".%s%d:\n", LSDA_HANDLER_START, nRangeTable);
07056 fprintf(Asm_File, "\t.personality\t__gxx_personality_v0#\n");
07057 fprintf(Asm_File, "\t.handlerdata\n");
07058 fprintf(Asm_File, "\t.align\t8\n");
07059 fprintf(Asm_File, ".%s%d:\n", LSDA_START, nRangeTable);
07060
07061
07062 INITV_Init_Integer_2(first, MTYPE_I1, 0xff, 1);
07063 scn_ofst = Write_INITV (first, scn_idx, scn_ofst);
07064
07065
07066 INITV_Init_Integer_2(first, MTYPE_I1, 0xb4, 1);
07067 scn_ofst = Write_INITV (first, scn_idx, scn_ofst);
07068
07069
07070 sprintf(begin_lab, ".%s%d", LSDA_TT_START, nRangeTable);
07071 sprintf(end_lab, ".%s%d", LSDA_TT_END, nRangeTable);
07072 scn_ofst = EH_Write_Lab_Diff(begin_lab, end_lab, scn_idx, scn_ofst);
07073 fprintf(Asm_File, "%s:\n", begin_lab);
07074
07075
07076 INITV_Init_Integer_2(first, MTYPE_I1, 0x1, 1);
07077 scn_ofst = Write_INITV (first, scn_idx, scn_ofst);
07078
07079
07080 sprintf(begin_lab, ".%s%d", LSDA_CS_START, nRangeTable);
07081 sprintf(end_lab, ".%s%d", LSDA_CS_END, nRangeTable);
07082 scn_ofst = EH_Write_Lab_Diff(begin_lab, end_lab, scn_idx, scn_ofst);
07083 fprintf(Asm_File, "%s:\n", begin_lab);
07084
07085
07086 INITV_Init_Integer(first, MTYPE_U4, act_inv, 1);
07087 Set_INITV_next(first, inv);
07088
07089
07090 for(;inv && inv != act_inv; inv = INITV_next(inv)) {
07091 INITV_IDX prev_inv;
07092
07093
07094 FmtAssert(INITVKIND_SYMDIFF == INITV_kind(inv) ||
07095 INITVKIND_SYMDIFF16 == INITV_kind(inv), ("CS_Start.kind != SymDiff"));
07096 scn_ofst = EH_Write_Sym_Diff(inv, scn_idx, scn_ofst);
07097
07098 inv = INITV_next(inv);
07099 prev_inv = inv;
07100 inv = INITV_next(inv);
07101
07102 scn_ofst = EH_Write_Lab_Diff(LABEL_name(INITV_lab(prev_inv)),
07103 LABEL_name(INITV_lab(inv)), scn_idx, scn_ofst);
07104
07105 inv = INITV_next(inv);
07106
07107 if (INITVKIND_ZERO != INITV_kind(inv)) {
07108 FmtAssert(INITVKIND_SYMDIFF == INITV_kind(inv) ||
07109 INITVKIND_SYMDIFF16 == INITV_kind(inv), ("CS_Start.kind != SymDiff"));
07110 scn_ofst = EH_Write_Sym_Diff(inv, scn_idx, scn_ofst);
07111 }
07112 else {
07113 scn_ofst = EH_Write_Integer(inv, scn_idx, scn_ofst, false);
07114 }
07115
07116 inv = INITV_next(inv);
07117
07118 scn_ofst = EH_Write_Integer(inv, scn_idx, scn_ofst, false);
07119 }
07120
07121
07122 sprintf(end_lab, ".%s%d", LSDA_CS_END, nRangeTable);
07123 fprintf(Asm_File, "%s:\n", end_lab);
07124
07125
07126 inv = INITV_next(act_inv);
07127 for(; inv && inv != type_inv; inv = INITV_next(inv)) {
07128
07129 scn_ofst = EH_Write_Integer(inv, scn_idx, scn_ofst, true);
07130
07131 inv = INITV_next(inv);
07132
07133 scn_ofst = EH_Write_Integer(inv, scn_idx, scn_ofst, true);
07134 }
07135
07136
07137
07138 fprintf(Asm_File, "\t.align\t8\n");
07139 inv = INITV_next(type_inv);
07140 for(; inv && inv != eh_spec_inv; inv = INITV_next(inv)) {
07141 ST_IDX type_st_idx = 0;
07142 if (INITVKIND_ZERO != INITV_kind(inv))
07143 type_st_idx = TCON_uval(INITV_tc_val(inv));
07144 if (type_st_idx == 0)
07145 fprintf(Asm_File, "\tdata8.ua\t0\n");
07146 else {
07147
07148 fprintf(Asm_File, "\tdata8.ua\t@gprel(DW.ref.%s#)\n", ST_name(&St_Table[type_st_idx]));
07149
07150
07151 }
07152 }
07153
07154
07155 sprintf(end_lab, ".%s%d", LSDA_TT_END, nRangeTable);
07156 fprintf(Asm_File, "%s:\n", end_lab);
07157
07158
07159 inv = INITV_next(eh_spec_inv);
07160 for(; inv; inv = INITV_next(inv)) {
07161 scn_ofst = EH_Write_Integer(inv, scn_idx, scn_ofst, false);
07162 }
07163
07164
07165 #undef LSDA_HANDLER_START
07166 #undef LSDA_START
07167 #undef LSDA_TT_START
07168 #undef LSDA_TT_END
07169 #undef LSDA_CS_START
07170 #undef LSDA_CS_END
07171 }
07172
07173 #else // TARG_IA64
07174 #ifdef KEY
07175 static Elf64_Xword
07176 Generate_Exception_Table_Header (INT scn_idx,
07177 Elf64_Xword scn_ofst,
07178 LABEL_IDX *);
07179 #endif // KEY
07180 #endif // TARG_IA64
07181
07182 static void
07183 Write_INITO (
07184 INITO* inop,
07185 INT scn_idx,
07186 Elf64_Xword scn_ofst)
07187 {
07188 pSCNINFO scn = em_scn[scn_idx].scninfo;
07189 Elf64_Xword inito_ofst;
07190 ST *sym;
07191 ST *base;
07192 INITO ino = *inop;
07193
07194 if ( Trace_Init ) {
07195 #pragma mips_frequency_hint NEVER
07196 Trace_Init_Loc (scn_idx, scn_ofst, 0);
07197 fprintf ( TFile, "INITO: " );
07198 Print_INITO (ino);
07199 }
07200
07201 Base_Symbol_And_Offset(INITO_st(ino), &base, (INT64*)&inito_ofst);
07202
07203 if (inito_ofst > scn_ofst) {
07204 if (Assembly) {
07205 #ifdef TARG_MIPS
07206 if (CG_emit_non_gas_syntax)
07207 fprintf(Asm_File, "\t%s %lld\n", ".space",
07208 (INT64)(inito_ofst - scn_ofst));
07209 else
07210 #endif
07211 ASM_DIR_ZERO(Asm_File, (INT32)(inito_ofst - scn_ofst));
07212 }
07213 if (Object_Code) {
07214 Em_Add_Zeros_To_Scn ( scn, inito_ofst - scn_ofst, 1 );
07215 }
07216 scn_ofst = inito_ofst;
07217 } else {
07218 FmtAssert ( inito_ofst >= scn_ofst,
07219 ("Write_INITO: DATA overlap 1, inito ofst @ %lld, scn ofst @ %lld",
07220 inito_ofst, scn_ofst));
07221 }
07222
07223 sym = INITO_st(ino);
07224 if (Assembly) {
07225 char *name = ST_name(sym);
07226 if (name != NULL && *name != 0) {
07227 #if defined(TARG_SL)
07228 if(ST_in_v2buf(sym))
07229 Print_Label (Asm_File, sym, (TY_size(ST_type(sym))<<1));
07230 else if(ST_in_v4buf(sym))
07231 Print_Label (Asm_File, sym, (TY_size(ST_type(sym))<<2));
07232 else
07233 Print_Label (Asm_File, sym, TY_size(ST_type(sym)));
07234 #else
07235 Print_Label (Asm_File, sym, TY_size(ST_type(sym)));
07236 #endif // TARG_SL
07237 }
07238 }
07239 if (Object_Code && ! ST_is_export_local(sym)) {
07240 EMT_Put_Elf_Symbol (sym);
07241 }
07242
07243
07244
07245
07246 if ( INITO_val(ino) == (INITO_IDX) NULL ) {
07247 if ( ST_class(sym) == CLASS_CONST ) {
07248 scn_ofst = Write_TCON (&ST_tcon_val(sym), scn_idx, scn_ofst, 1);
07249 }
07250 } else {
07251 INITV_IDX inv;
07252 #ifndef TARG_IA64
07253 char *name = ST_name (sym);
07254 bool range_table = (name != NULL) &&
07255 (!strncmp (".range_table.", name,strlen(".range_table."))) &&
07256 (ST_sclass (sym) == SCLASS_EH_REGION);
07257 LABEL_IDX labels[2];
07258 if (range_table)
07259 {
07260 exception_table_id++;
07261 scn_ofst = Generate_Exception_Table_Header (scn_idx, scn_ofst, labels);
07262 }
07263 bool action_table_started = false;
07264 bool type_label_emitted = false;
07265 #endif // KEY
07266 FOREACH_INITV (INITO_val(ino), inv) {
07267 #ifndef TARG_IA64
07268 if (range_table && !action_table_started &&
07269 (INITV_flags (Initv_Table[inv]) == INITVFLAGS_ACTION_REC))
07270 {
07271 action_table_started = true;
07272 fprintf ( Asm_File, "%s:\n", LABEL_name(labels[0]));
07273 }
07274 if (range_table && !type_label_emitted &&
07275 INITV_flags(Initv_Table[inv]) == INITVFLAGS_EH_SPEC)
07276 {
07277 type_label_emitted = true;
07278 fprintf ( Asm_File, "%s:\n", LABEL_name(labels[1]));
07279 }
07280 scn_ofst = Write_INITV (inv, scn_idx, scn_ofst, range_table,
07281 range_table ? INITV_flags (Initv_Table