• Main Page
  • Modules
  • Data Types
  • Files

osprey/be/cg/cgemit.cxx

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2006. QLogic Corporation. All Rights Reserved.
00003  */
00004 
00005 /*
00006  * Copyright 2002, 2003, 2004, 2005, 2006 PathScale, Inc.  All Rights Reserved.
00007  */
00008 
00009 /*
00010 
00011   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00012 
00013   This program is free software; you can redistribute it and/or modify it
00014   under the terms of version 2 of the GNU General Public License as
00015   published by the Free Software Foundation.
00016 
00017   This program is distributed in the hope that it would be useful, but
00018   WITHOUT ANY WARRANTY; without even the implied warranty of
00019   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00020 
00021   Further, this software is distributed without any warranty that it is
00022   free of the rightful claim of any third person regarding infringement 
00023   or the like.  Any license provided herein, whether implied or 
00024   otherwise, applies only to this software file.  Patent licenses, if 
00025   any, provided herein do not apply to combinations of this program with 
00026   other software, or any other product whatsoever.  
00027 
00028   You should have received a copy of the GNU General Public License along
00029   with this program; if not, write the Free Software Foundation, Inc., 59
00030   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00031 
00032   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00033   Mountain View, CA 94043, or:
00034 
00035   http://www.sgi.com
00036 
00037   For further information regarding this notice, see:
00038 
00039   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00040 
00041 */
00042 
00043 
00044 /* ====================================================================
00045  *
00046  * Module: cgemit.c
00047  * $Revision: 1.1.1.1 $
00048  * $Date: 2005/10/21 19:00:00 $
00049  * $Author: marcel $
00050  * $Source: /proj/osprey/CVS/open64/osprey1.0/be/cg/cgemit.cxx,v $
00051  *
00052  * Description:
00053  *
00054  * Emit object code and/or assembly instructions from compiler.
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 /* Mac port */
00071 #include "dwarf_stuff.h"
00072 #endif /* KEY Mac port */
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 /* defined(BUILD_OS_DARWIN) */
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"  /* for Print_alias_info */
00108 #include "anl_driver.h"     /* for Anl_File_Path */
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"       /* for Alias_Manager */
00120 #include "const.h"
00121 #include "whirl2ops.h"      /* for Get_WN_From_Memory_OP */
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" // for current_pu_count
00164 #include "dwarf_stuff.h"
00165 extern "C" {
00166 #include "pro_encode_nm.h"
00167 }
00168 
00169 #ifdef KEY
00170 #include "config_lno.h" // for LNO_Run_Simd
00171 #include "config_opt.h" // for OPT_Cyg_Instrument
00172 #endif
00173 
00174 #ifdef TARG_SL
00175 #include "disp_instr.h"
00176 #endif
00177 
00178 #ifdef TARG_X8664
00179 #include "be_util.h"    // for Current_PU_Count
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  /* max size to be padded in a section */
00186 
00187 
00188 /* c++ mangled names can be any arbitrary length,
00189  * so this is just a first guess */ 
00190 #define LBUF_LEN  (OP_MAX_FIXED_OPNDS*1024)
00191 
00192 /* Instructions go into one of two ELF text sections depending on
00193  * whether the BB is in a hot or cold region. Hot BBs go into
00194  * ".text" (or ".text<pu-name>" for -TENV:section_for_each_function).
00195  * Cold BBs go into ".text.cold". As a result, numerous cgemit
00196  * routines need to track the PC of both sections, and 2 element
00197  * arrays are typically used. Here we define the indices for
00198  * the arrays, with the values chosen to coincide with the result
00199  * of BB_Is_Cold.
00200  */
00201 enum { IHOT=FALSE, ICOLD=TRUE };
00202 
00203 /* Overload BB flag <local_flag1> to indicate if a BB is cold or hot --
00204  * it's less overhead than BB_Is_Cold.
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;  // defined in wn_lower.cxx
00214 #endif
00215 
00216 /* ====================================================================
00217  *
00218  * Global data
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 // most targets emit data sections, but nvisa wants to emit variable decls
00249 #define EMIT_DATA_SECTIONS
00250 #endif
00251 
00252 static BOOL generate_dwarf = FALSE;
00253 static BOOL generate_elf_symbols = FALSE;
00254 
00255 /* Local phase trace flags: */
00256 static BOOL Trace_Init    = FALSE;  /* Data initialization trace */
00257 static BOOL Trace_Inst    = FALSE;  /* Noop-insertion trace */
00258 static BOOL Trace_Elf     = FALSE;  /* Miscellaneous ELF trace */
00259 static BOOL Trace_Longbr  = FALSE;  /* trace handling of long branches */
00260 
00261 BOOL Use_Page_Zero = FALSE;
00262 static BOOL Use_Prefetch = FALSE;
00263 
00264 
00265 // For dwarf output in assembly we need to keep track of the 
00266 // offset of the current instruction from a known label.
00267 // If Last_Label is LABEL_IDX_ZERO, it is assumed to be invalid.
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 /* NOTE: PCs are actually a bundle address and slot number pair. The 
00274  * slot number is in the low bits. 
00275  */
00276 static INT32 PC = 0;      /* PC for current text section */
00277 static INT32 text_PC = 0;   /* PC for hot text */
00278 static INT32 cold_PC = 0;   /* PC for cold text */
00279 
00280 static ST *PU_base = NULL;    /* base for current text section */
00281 static ST *text_base = NULL;    /* base for hot text section */
00282 static ST *cold_base = NULL;    /* base for cold text section */
00283 
00284 static pSCNINFO PU_section = NULL;  /* current text section */
00285 static pSCNINFO text_section = NULL;  /* hot text section */
00286 static pSCNINFO cold_section = NULL;  /* cold text section */
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; /* current rid id */
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 /* 0 index to em_scn will be null values */
00305 
00306 static ST *cur_section = NULL;
00307 
00308 static PU_IDX current_pu = 0;
00309 
00310 // put PU in separate elf text section?
00311 // (pu could be null if no PUs)
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  * For the elf indexes, we can reuse the temp field for local STs,
00322  * Need to map from ST's to the elf index for the ST.
00323  * So create array of index arrays, where the ST_level
00324  * gets you to the index array, and then the ST_index 
00325  * gets you to the elf index for that ST.
00326  */
00327 
00328 /*
00329  * Maximum nesting depth includes these scopes, in the deepest case:
00330  *  0 : not used
00331  *  1 : global scope
00332  *  2 : top-level PU
00333  *  3 : F90 internal procedure
00334  *  4 : MP PU from internal procedure
00335  *  5 : Fortran I/O in MP PU
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; // text 1: hot 2: cold 3
00348 #endif
00349 
00350 #if defined(BUILD_OS_DARWIN)
00351 /*
00352  * Emit ".section" directive, mapping names onto the syntax that the Darwin
00353  * assember expects to see after the token ".section", and suppressing the
00354  * ".bss" directive entirely since Darwin doesn't support it
00355  * base   Symbol for section
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  * Transform an external symbol name by prepending an underscore (the usual
00367  * case), or synthesizing the jump-target label used to implement an indirect
00368  * call via a stub, or synthesizing the label used to implement a non-lazy
00369  * pointer to an external symbol.
00370  *
00371  * name   symbol name as it would appear in C source (e.g. "x")
00372  * which  (optional) how to transform name
00373  * returns  pointer to static underscorify_buffer containing the transformed
00374  *    name
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   /* Don't mess with symbols like ".rodata" */
00382   if (*name == '.') {
00383     return name;
00384   }
00385 
00386   unsigned name_len = strlen(name);
00387   const char *pattern = "%s"; /* Just in case */
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  * Generate __IMPORT,__jump_table entry for symbol name the first time we
00410  * need it; or generate __IMPORT,__pointers entry for symbol "name" the
00411  * first time we need it
00412  * name   symbol name as it would appear in C source
00413  * which  which kind of entry to generate
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 /* Return log base 2 of an integer (use for .align on systems which expect
00446  * the argument to be the log of the alignment) */
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  * Darwin doesn't permit direct manipulation of the ".bss" section via
00459  * directives like ".section", ".org", ".skip", ".align". The only access
00460  * is via the ".lcomm" directive. So in Process_Bss_Data(), we make a list
00461  * of the symbols that are supposed to be in ".bss", computing the maximum
00462  * offset (size, actually) and alignment. At the end of compilation, we
00463  * emit ".lcomm .bss,<size>,<alignment>" followed by a
00464  * ".set <name>,.bss+<offset>" for each symbol.
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 // Modeled upon EMT_Write_Qualified_Name()
00496 vstring &
00497 darwin_bss::qualified_name(vstring &v, ST *st) {
00498   // No name (can only be referred to as ".bss+offset")
00499   if (0 == ST_name(st) || 0 == *(ST_name(st))) {
00500     return v;
00501   }
00502   vstr_concat(v, underscorify(ST_name(st)));
00503   // This name is already unique, don't change it.
00504   if (!strncmp (ST_name(st), ".range_table.", strlen(".range_table."))) {
00505     return v;
00506   }
00507   // See comment in EMT_Write_Qualified_Name
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  * sym    .bss symbol 
00524  * accum_size Input: size of .bss prior to this symbol. Output: size
00525  *    following this symbol
00526  * maxalign Input: Maximum alignment required prior to this symbol.
00527  *    Output: Maximum alignment following this symbol. Optional
00528  * returns  Offset from .bss to this particular symbol
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  * Add a symbol to the list of ".bss" symbols which we must revisit at the
00546  * end of compilation
00547  * sym    Symbol in ".bss" section
00548  */
00549 void
00550 darwin_bss::remember_bss_symbol(ST *sym) {
00551   /* TBD: Might need other stuff from Print_Label? */
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  * After seeing the entire list of .bss symbols from all calls to
00561  * Process_Bss_Data(), emit a ".lcomm .bss" directive to reserve space for all
00562  * of them, and then emit ".set" directives to define each one as an offset
00563  * from the beginning of ".lcomm".
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 /* defined(BUILD_OS_DARWIN) */
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     /* for the size take the #st's + extra space for new symbols */
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     /* # globals has grown, so realloc. */
00595     /* we realloc even if close and not yet overflowed,
00596      * because may alloc new symbols as part of cg. */
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     /* need to clear the values in case leftover 
00614      * from previous uplevel */
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 /* Determine if the symbol has a base of gp */
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     /* already created */
00667     return;
00668   }
00669   if (last_scn >= (max_scn-1)) {
00670     /* allocate new block of sections */
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   /* hack for .text section */
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         // align all text-like section in SL1
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;  /* save symbol for later reference */
00705   /* assume st is CLASS_BLOCK */
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     /* initialize elf data buffer. */
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     /* set dummy value just so don't redo this */
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   /* full-split symbols have names of form "full_.offset"
00783    * we need to extract the offset and pass that in value field.
00784    * An alternative would be to search type structure for
00785    * matching fields, but this is probably faster.
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++;       /* skip the period */
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  * Instruction-PC utilities.
00824  *
00825  * On architectures that support bundling, we use a PC representation
00826  * that enables us to point at instructions within the bundle.
00827  * We accomplish this by using the low bits of the bundle address
00828  * (which are normally zero because of alignment constraints) to
00829  * hold the instruction offset, i.e. slot number, within the bundle.
00830  *
00831  * The following utility routines provide for updating and accessing
00832  * the composite PC values.
00833  *
00834  ***********************************************************************
00835  */
00836 
00837 
00838 /* Given a composite PC, return the bundle address component.
00839  */
00840 inline INT32 PC_Bundle(INT32 pc)
00841 {
00842   return pc & ~(INST_BYTES - 1);
00843 }
00844 
00845 /* Given a composite PC, return the slot number component.
00846  */
00847 inline INT32 PC_Slot(INT32 pc)
00848 {
00849   return pc & (INST_BYTES - 1);
00850 }
00851 
00852 /* Increment a composite PC by 1. The slot number is incremented, 
00853  * and if it overflows, the bundle address is adjusted as well.
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 /* Same as PC_Incr except the increment is an arbitrary constant.
00867  */
00868 inline INT32 PC_Incr_N(INT32 pc, UINT32 incr)
00869 {
00870 #if defined(TARG_SL)
00871   pc = pc + (2*incr); // for SL, incr are in half words
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 /* defined(BUILD_OS_DARWIN) */
00887   fputs(ST_name(st), f);
00888 #endif /* defined(BUILD_OS_DARWIN) */
00889 #if defined(KEY) && !defined(TARG_NVISA)
00890 // This name is already unique, don't change it.
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     // local var, but being written out.
00896     // so add suffix to help .s file distinguish names.
00897     // assume that statics in mult. pu's will 
00898     // get moved to global symtab, so don't need pu-num
00899                 if (ST_level(st) == GLOBAL_SYMTAB) {
00900 #ifdef KEY
00901                     // bug 14517, OSP 490
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 /* print the internal, hidden or protected attributes if present */
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   // Bug 1275 and 4351
00970   // Always emit the function type
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 // Mach-O as 1.38 doesn't support .type
00980 #endif /* defined(BUILD_OS_DARWIN) */
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   /* if size is given, then emit value for asm */
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 /* defined(BUILD_OS_DARWIN) */
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   // use base common
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) /* .comm alignment arg not allowed */
01036     fprintf ( pfile, ", %" LL_FORMAT "d\n", TY_size(ST_type(st)));
01037 #else /* defined(BUILD_OS_DARWIN) */
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 /* defined(BUILD_OS_DARWIN) */
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     // this is needed so that we don't emit commons more than once
01051     if (!generate_elf_symbols) Set_ST_elf_index(st, 1);
01052   }
01053 #ifdef KEY
01054   else {
01055     // Emit symbol even though type size is 0, in order to avoid undefined
01056     // symbol in C++.  Bug 3739.
01057     //
01058     // For ipa's symtab.I, can't use PU_src_lang(Get_Current_PU()) to check for
01059     // C++ because the PU isn't defined.  So, add the 1 byte for all languages.
01060     // Bug 3923.
01061     fprintf ( pfile, "\t%s\t", AS_COM);
01062     EMT_Write_Qualified_Name(pfile, st);
01063 #if defined(BUILD_OS_DARWIN) /* .comm alignment arg not allowed */
01064     fputs (", 1\n", pfile);
01065 #else /* defined(BUILD_OS_DARWIN) */
01066     fputs (", 1, 1\n", pfile);
01067 #endif /* defined(BUILD_OS_DARWIN) */
01068   }
01069 #endif
01070 }
01071 
01072 
01073 /* ====================================================================
01074  *
01075  * EMT_Put_Elf_Symbol
01076  *
01077  * Add a symbol to the ELF symbol table if it hasn't been added already.
01078  * ====================================================================
01079  */
01080 
01081 #if defined(BUILD_OS_DARWIN)
01082 /*
01083  * sym      symbol to add
01084  * which    (optional) if present and not DO_UNDERSCORE, then this
01085  *      symbol must be accessed indirectly to permit dynamic
01086  *      linking on Darwin
01087  */
01088 mINT32 EMT_Put_Elf_Symbol (ST *sym, darwin_indirect_t which)
01089 #else /* defined(BUILD_OS_DARWIN) */
01090 mINT32 EMT_Put_Elf_Symbol (ST *sym)
01091 #endif /* defined(BUILD_OS_DARWIN) */
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   /* check if symbol is already there. */
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   // if only .s file, then just do dummy mark that we have
01119   // seen this symbol and emitted any type info for it.
01120   if (ST_class(sym) == CLASS_FUNC
01121 #if defined(BUILD_OS_DARWIN)
01122       && 0 // Mach-O as 1.38 doesn't support .type
01123 #endif /* defined(BUILD_OS_DARWIN) */
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   /* set the symbol binding. */
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   // check if base is new section symbol that is not initialized yet
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   // ipa can cause it to be based on global extern,
01171   // in which case treat it as an extern
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);  // only valid for VARs
01180       switch (sclass) {
01181   case SCLASS_FSTATIC:
01182 #ifdef TARG_NVISA
01183   // need to create symbol info for pstatics, similar to fstatic,
01184   // so that debug info will find it (not assigned to bss section
01185   // like other targets do).
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         /* Indirect calls use jump table instead */
01213         if (DO_UNDERSCORE != which) {
01214     fprintf(Asm_File, "\t%s\t%s\n", AS_GLOBAL,
01215       underscorify(ST_name(sym)));
01216         }
01217 #else /* defined(BUILD_OS_DARWIN) */
01218         fprintf(Asm_File, "\t%s\t%s\n", AS_GLOBAL, ST_name(sym));
01219 #endif /* defined(BUILD_OS_DARWIN) */
01220       }
01221     break;
01222   case SCLASS_COMMON:
01223     if (sym != base_st && ST_sclass(base_st) == SCLASS_COMMON) {
01224     // use base common
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;  /* sym section index */
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   // treat formals as commons
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   /* emit it even though it's an unknown local (C++) */
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       /* Indirect calls use jump table instead */
01287       if (DO_UNDERSCORE != which) {
01288         fprintf(Asm_File, "\t%s\t%s\n", AS_GLOBAL,
01289     underscorify(ST_name(sym)));
01290       }
01291 #else /* defined(BUILD_OS_DARWIN) */
01292       fprintf(Asm_File, "\t%s\t%s\n", AS_GLOBAL, ST_name(sym));
01293 #endif /* defined(BUILD_OS_DARWIN) */
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       // may be global binding (IPA global extern symbols)
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   /* if not emitted yet, can wait till somebody refers to it */
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   /* if not emitted yet, can wait till somebody refers to it */
01339   return;
01340   Em_Set_Symbol_Binding (symindex, STB_WEAK);
01341 }
01342 
01343 
01344 // if TN is symbol TN, add info about it to comment buffer
01345 static void
01346 put_TN_comment (TN *t, BOOL add_name, vstring *comment)
01347 {
01348   if (!add_name) return;  // don't duplicate name
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  * r_apply_l_const
01378  *
01379  * Format the given constant TN's "value" into the given buffer.
01380  * Return whether the symbol name should be added to comments.
01381  *
01382  * ====================================================================
01383  */
01384 
01385 static BOOL
01386 r_apply_l_const (
01387   OP *op,   /* OP with constant operand */
01388   INT opidx,    /* OP index of constant TN of some sort */
01389   vstring *buf)   /* A buffer to format it into */
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   /* special case for stack symbols */
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 /* defined(BUILD_OS_DARWIN) */
01456     st = TN_var(t);
01457     // call put_symbol so that we emit .type info, once per symbol
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       /* Darwin dynamic linking requires that we emit an indirect call
01465        * through a jump table. System and C library functions are supported
01466        * only via dynamic linking. Since we can't know whether a function
01467        * outside this compilation is available via static linking, we must
01468        * assume that it might require dynamic linking. */
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   /* Need other instructions as well? */
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 /* defined(BUILD_OS_DARWIN) */
01483       (void) EMT_Put_Elf_Symbol (st);
01484 #endif /* defined(BUILD_OS_DARWIN) */
01485     }
01486 #ifdef TARG_NVISA
01487     if (ST_class(st) == CLASS_CONST) {
01488       // want to emit fp constants as literal operands
01489       if (MTYPE_is_float(ST_mtype(st))) {
01490   *buf = vstr_concat(*buf, Targ_Print (NULL, STC_val(st)));
01491   // print as hex in instruction, so print-user-readable form in comment
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   // use base if referring to current pu or local data
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     /* use PU text section rather than generic one */
01514     st = PU_base;
01515       }
01516   hexfmt = TRUE;
01517   print_TN_offset = TRUE;
01518   // add name to comments in case was confused by gp_disp.
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 /* defined(BUILD_OS_DARWIN) */
01527   *buf = vstr_concat(*buf, ST_name(st));
01528 #endif /* defined(BUILD_OS_DARWIN) */
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   // don't use "." cause that can have varying meaning
01540   // when have multiple instruction slots.
01541   // Instead just do label+offset.
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       // nvisa uses this for cc enum, wants to always use string name
01567       // (ideally should extend targ-info to specify this).
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;  /* because value used instead */
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 /* TARG_X8664 */
01595     
01596     print_TN_offset = FALSE;  /* because value used instead */
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  * print_prefetch_info(char *comment, WN *wn)
01616  *   add prefetch info comments to the assembler listing.
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  * r_assemble_list
01641  *
01642  * Emit a pseudo-assembly listing for the given OP.
01643  *
01644  * ====================================================================
01645  */
01646 
01647 static void r_assemble_list (
01648   OP *op,   /* The operation being listed */
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 // un-ifdef this when gas can handle tags inside explicit bundle
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);  // start of operand string
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) // in case rot-regs overlap output regs
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     // need end-of-string between each operand
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);  // start of operand string
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) // in case rot-regs overlap output regs
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'); // increment vstr length
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   /* Add target PU name as comment for normal call and tail call OPs.
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    /*Add value profile comment "val_prof[id, exec_count]"*/
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  * Verify_Operand
01886  *
01887  * Verify that the specified operand is valid for the particular
01888  * instruction operand.
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 /* TARG_X8664 */
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  * Verify_Instruction
02000  *
02001  * Verify that the specified OP contains valid information for
02002  * the instruction it represents.
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   // ??? check for valid topcode?
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     // Don't complain if jnp appears in a BB without a compare OP.  This is
02035     // because Expand_Ordered_Select_Compare can generate a compare followed by
02036     // 2 conditional branches, the second of which is jnp.
02037     FmtAssert(prev != NULL || OP_code(op) == TOP_jnp,
02038         ("set_rflags op is missing") );
02039   }
02040 
02041   /* Make sure the index register is not %rsp. */
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); // can only verify fixed results
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); // can only verify fixed operands
02070   }
02071   for (i = 0; i < opnds; ++i) {
02072     Verify_Operand(oinfo, op, i, FALSE);
02073   }
02074 
02075 #ifdef KEY
02076   // Check for unique operand and result registers.
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  * r_assemble_binary
02098  *
02099  * Generate an instruction word(s) for the given OP.
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   // get the target address 
02119   val = Get_Label_Offset(TN_label(t)) + TN_offset(t);
02120 
02121   // get pc-relative offset if necessary
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   // get the target address 
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     /* use PU text section rather than generic one */
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      * Put in addend instead of in instruction,
02194      * and put gprel in rela section.
02195      * This can happen for large common or array/struct in 
02196      * gprel section.  Because it is gprel, IPA is guaranteeing
02197      * that the final offset will fit in 16 bits.
02198      * Usually, when val is small, 
02199      * we put val in instruction and use .rel.
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       //Do nothing
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) // in case rot-regs overlap output regs
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) // in case rot-regs overlap output regs
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   /* Intialize checking code for block. */
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) && // How can we clean up at level 0? (see pv #769596)
02325       !OP_has_implicit_interactions(def_op) && 
02326       !OP_cond_def(def_op) && 
02327       !OP_cond_def(op) &&
02328       OP_results(def_op) == 1 && // a hack for multi-result ops
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) {  /* only print to .t file */
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) {  /* only print to .t file */
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) {  /* only print to .t file */
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) {  /* only print to .t file */
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   /* Make sure we're not emitting mov.[ds] of integer values. */
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) {  /* only print to .t file */
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 //Bug 11034: implement dymanic allocation of pu tables to
02416 //various information for dwarf
02417 //********************************************************
02418 static INT32 num_pus = 64; /*initialized as 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){ // allocate memory 
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++){ //initialization
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 /* Write out the 'op' into the object file and/or into the assembly file.
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   // Determine if OP is the first OP in the BB.  Cannot rely on
02509   // "BB_first_op(bb) == op" because Assemble_Simulated_OP does not update
02510   // BB_first_op when it expands the first BB OP into the current OP.
02511   // Bug 14305.
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     // Replace uses of entry_name with uses of ST_name, since inserting
02523     // new elements into StrTab can realloc it and this pointer would be
02524     // invalid: bug 4222
02525     // char* entry_name;
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; // reinitialize
02537   pu_entry_count ++;
02538       }
02539       else if (PU_ftn_lang(Get_Current_PU())) {
02540   pu_entries ++;
02541   pu_entry_count ++;
02542       }
02543       //bug 11034 : dynamic allocation and reallocation if necessary
02544       if(!dw_pu_tables_allocated){ // this should not happen
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) // not enough entry in the tables
02549           double_dwarf_pu_tables(); // double the size of 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           /* EXTRA_NAME_LEN */ 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           /* EXTRA_NAME_LEN */ 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           /* EXTRA_NAME_LEN */ 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       // Bug 2929 - The exact position of the last Callee Saved Register
02597       // spill does not matter. So, we could emit the csr label immediately
02598       // after adjustsp label (this order is important). The positions of
02599       // the callee saved register(s) on the stack will be emitted in the 
02600       // concerned dwarf sections using this csr label. At higher optimization
02601       // levels, the adjustsp and csr saves can be moved around by EBO and this
02602       // is a work-around.
02603       if (Cgdwarf_Num_Callee_Saved_Regs()) { 
02604   buf = (char *)alloca(strlen(ST_name(entry_sym)) + 
02605              /* EXTRA_NAME_LEN */ 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     // Does this make Cg_Dwarf_First_Op_After_Preamble_End redundant?
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     /* expand double to two singles */
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       /* lwc1 $f_even, ST_offset(base) */
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       /* lwc1 $f_odd, 4 + ST_offset(base) */
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       /* Set the opcode back to ldc1 */
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       /* swc1 $f_even, ST_offset(base) */
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       /* swc1 $f_odd, 4+ST_offset(base) */
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       /* Set the opcode back to ldc1 */
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       /* mov_s $f_even, $f_even */
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       /* mov_s $f_odd, $f_odd */
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       /* Set the opcode back to mov_d */
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       /* mov_f_s $f_even, $f_even */
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       /* mov_f_s $f_even, $f_even */
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       /* Set the opcode back to movf_d */
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       /* movt_s $f_odd, $f_odd */
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       /* mov_s $f_even, $f_even */
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       /* Set the opcode back to mov_d */
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     // If the frame length is zero then spadjust would have been deleted
02776     // So, we need to generate another psuedo label here and attach it after 
02777     // the movespbp instruction.
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           /* EXTRA_NAME_LEN */ 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       // if we need to use entry_name here, we must use ST_name instead
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   // Bug 4204 - move the ctrl register setup after the preamble. This 
02798   // causes the debug information generated to let the debugger to stop
02799   // at the right spot for the main entry function. Otherwise, the parameters
02800   // would be displayed incorrectly. 
02801   if (adjustsp_instr) {
02802     // Assumption: REGION_First_BB is the first BB in the PU. If in future,
02803     // we start having multiple regions in a PU here, we need to change the 
02804     // following. 
02805     // In such a scenario, we should need to change many of the occurrences
02806     // of REGION_First_BB above.
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     /* May need to add information about this call (or tail call) site */
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 /* don't do this till decide on format of EK_SWITCH */
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   // hack to keep track of last label and offset for assembly dwarf (suneel)
02853   // If the current op is a TOP_asm, mark the Last_Label as invalid.
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     // Bug 2468 - can not update offset/PC for x86 target (variable length)
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   // Assume 'from' appears 5 times in 'in' to start with and later reallocate
02877   // memory if need be. Due to the context, this is more efficient than finding
02878   // out the number of occurrences of 'from' in 'in'.
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; // By default, substitutions ought to happen.
02888 
02889   strcpy(buf, ""); // initialize
02890   strcpy(tmp, ""); // initialize
02891   strcat(in, "\0");
02892   while ((p = strstr(in, from)) != NULL) {
02893 
02894     leftover = p + strlen(from);
02895 
02896     // Bug 7825 happened because in the earlier implementation, we used to 
02897     // replace the 'from' instance by 'to' even if the 'from' instance happened
02898     // to be a prefix of a larger instance of the token class that the incoming 
02899     // 'from' belonged to. 
02900     //
02901     // With the 2.x GCC series, the maximum number of operands permissible in
02902     // an asm() statement was 10, and as no pattern in %0 through %9 share a 
02903     // common prefix, this scheme worked just fine. Since the GCC 3.x series, 
02904     // asm() statements can have up to 30 operands. So, this scheme would no 
02905     // longer work: wrong substitutions happenned.
02906     // (e.g. %10 -> <'to' for 'from' %1>0 (Note trailing '0')).
02907     //
02908     // Using strstr(3) to skim over the 'in' (asm template) is fine, but does 
02909     // not suffice as the basis upon which to substitute 'from' by 'to' - we 
02910     // needed to ascertain that the 'from' instance happens to be a maximal 
02911     // instance of token class:
02912     //
02913     // %<number>
02914     //
02915     // Note: From the GCC 3.3.5 User Manual, we have the following excerpt:
02916     //
02917     // "As of GCC version 3.1, it is also possible to specify input and output 
02918     //  operands using symbolic names which can be referenced within the 
02919     //  assembler code."
02920     //
02921     // However, no two instances of the token class: %[<identifier>] can have a
02922     // common-prefix, so we are fine implementing our check for when the asm() 
02923     // operands are referred to per the older scheme viz. in a numbered manner.
02924     //
02925     // Note: It might seem like iterating the operand list in the descending
02926     // order of operands is a plausible workaround, but that might not be the
02927     // only context in which this function is invoked. The kludge would be exposed
02928     // when a single invocation involving a single numbered operand that shares a 
02929     // common prefix with another numbered operand in the operand list occurs.
02930     // So we rather do the right thing and fix things in the proper place.
02931     //
02932     // Hence the following code to implement a "maximal-munch" when we find that
02933     // the 'from' pattern is a numbered operand reference. (Admittedly, we're 
02934     // making this function specific to substituting references to operands in 
02935     // assembler templates, but then the other option would be to specify a
02936     // pattern (via regex(3)) for 'from' and that's adding dependencies and
02937     // complicating matters).
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       // We've ensured that 'from' is a numbered operand reference possibly with
02947       // a modifier. (See Bug 3141 Additional Comment #7 for a more extensive 
02948       // list of modifiers in an operand reference that are possible in an asm()
02949       // assembler template but are not documented in the GCC User Manual).
02950 
02951       // That we have a 'from' instance in 'in' and that 'in' is '\0' 
02952       // terminated, implies that 'p + 2' is a valid address. Hence:
02953 
02954       q = p + 2;
02955 
02956       // Now scan ahead from this point onwards ensuring that we are within 
02957       // bounds (i.e. we have'nt yet hit '\0') cand a partially constructed 
02958       // number or identifier continues to be formed. 
02959       // Note that this weak check is is O.K. as long as 'from' is syntactically
02960       // well defined.
02961 
02962       while (*q != '\0' && (isdigit(*q) || isalpha(*q))) q++;
02963 
02964       // We already have proof that 'p' points to a prefix of 'from' in 'in'.
02965       // If the number of characters we've marched past 'p' upto 'q' above
02966       // non-inclusively, equals the length of 'from' - it's an exact match
02967       // and we allow the substitution to take place. Else, we want to 
02968       // prohibit the substitution.
02969 
02970       if ((q - p) == strlen(from)) 
02971         substitute = 1;
02972       else 
02973         substitute = 0;
02974 
02975     }
02976     else substitute = 1; // Preserve prior behaviour.
02977 
02978     strncpy(tmp, in, strlen(in) - strlen(p));
02979     tmp[strlen(in) - strlen(p)] = '\0'; // terminate the string
02980     strcat(buf, tmp);
02981     if (substitute)
02982       strcat(buf, to);
02983     else
02984       strcat(buf, from); // Because we are going to resume at '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 /* KEY */
03023 
03024 #ifdef TARG_X8664
03025 static const char* int_reg_names[5][16] = {
03026   /* BYTE_REG: low 8-bit */
03027   { "%al", "%bl", "%bpl", "%spl", "%dil", "%sil", "%dl", "%cl",
03028     "%r8b",  "%r9b",  "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" },
03029   /* BYTE_REG: high 8-bit */
03030   { "%ah", "%bh", "%bph", "%sph", "%dih", "%sih", "%dh", "%ch",
03031     /* The following is a filler. There is no "high"  for these registers */
03032     "%r8b",  "%r9b",  "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" },
03033   /* WORD_REG: 16-bit */
03034   { "%ax", "%bx", "%bp", "%sp", "%di", "%si", "%dx", "%cx",
03035     "%r8w",  "%r9w",  "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" },
03036   /* DWORD_REG: 32-bit */
03037   { "%eax", "%ebx", "%ebp", "%esp", "%edi", "%esi", "%edx", "%ecx",
03038     "%r8d",  "%r9d",  "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" },
03039   /* QWORD_REG: 64-bit */
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,  /* for memory opnd */
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) // in case rot-regs overlap output regs
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     // Rename an integer register based on the size of the variable.
03071     if (cl == ISA_REGISTER_CLASS_integer) {
03072        name = (char*) CGTARG_Modified_Asm_Opnd_Name('r', tn, name);
03073     }
03074     // Check if you need to modify st0/st1 into parenthesised format.
03075     // Save a function call to strcmp(3).
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       // ISA_REGISTER_CLASS_integer class renaming has happened above, 
03093       // so we just deal with the other classes out here. 
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     // symbols are not really laid out in memory yet, so ignore base_ofst
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)) + /* EXTRA_NAME_LEN */ 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 /* bug 14399 */ && !strcmp (name, ".rodata")) {
03153         // This is the address of a string constant, treat it similar
03154         // to a numeric constant. (bug 14390)
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     // -Wformat will warn about I64 in sprintf (why?),
03195     // so hack this case and just print low 32bits
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   // SiCortex 3443: Handle %z<num> constraint assuming no special meaning
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   // Replace any %x<num> constraint with the immediate value written in hex
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     // Bug 3141: Support the 'y' modifier in operand references within
03260     //           the asm template.
03261     // Note that we only modify %st0 into %st(0) [and %st1 into %st(1)];
03262     // so, we need to check for %st too (Which is what %y is about anyways).
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   // OSP_315
03270   // Replace any %c<num> constraint with the constant string
03271   if (strstr(asm_string, "%c") && TN_is_symbol(tn) ) {
03272     char replace[5];
03273     sprintf(replace, "%%c%d", position);
03274     // Since the name may be sym+offset(%rip), 
03275     // we need to get rid of characters after '('
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 = '('; // restore the name
03283     }
03284     else {
03285       asm_string = Replace_Substring(asm_string, replace, name);
03286     }
03287   } // end of osp_315
03288 
03289   // Replace any %c<num> constraint with the immediate value
03290   // Replace any %n<num> constraint with the negated immediate value
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       // Drop the '$' in name.  Bug 7406.
03296       asm_string = Replace_Substring(asm_string, replace, name+1);
03297     }
03298     if (strstr(asm_string, "%n")) {
03299       // Bug 3141: One of the problems found was that we did not support
03300       // %n<num> in the asm() assembler template.
03301       // The assembler downstream handles compile-time constant expressions as 
03302       // immediates in instructions, so we are fine just prefixing a '-' to the 
03303       // immediate value in 'name'.
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       // OSP_323, with "%P", we ignore the first character '$'
03316       asm_string = Replace_Substring(asm_string, replace, name+1);
03317     }
03318   }
03319   // Follow the zero dialect_number implementation as in 
03320   // gcc/final.c:output_asm_insn and handle {, } and | operators
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   // Handle modifier between % and the operand number, such as %b0, %h0.  The
03355   // modifier controls how the register or instruction name is printed.
03356   {
03357     // Need to test bugs 504, 2455, 3141 
03358     // if any change is made in this function.
03359    
03360     // Handle x86 style asm operand constraints after all regular constraints.
03361     // This avoids replacing same register names multiple times.
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     // Handle any %b constraint
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     // Handle any %h constraint
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     // Handle any %w constraint
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     // Handle any %k constraint
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     // Handle any %q constraint
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     // Handle any %z modifier instance.
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   //beginning of quadword
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));// 4 is sizeof intruction op
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      // check mvfc ra and jp.lnk/jr.lnk   
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));// 4 is sizeof intruction op
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   // analysis asm_string
03506   int words = 0;
03507   char *p = (char *)asm_string;
03508   char *skip_string[3] = {"noreorder", "reorder", "set"};
03509   
03510    // must be expanded to 2 32-bit instructions
03511   typedef struct Macro_instr {
03512     char *str;
03513     UINT8 expand_num; // multiply of 16bit instruction
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         // skip "#define"
03520         if (!strncmp("#define", (const char *)(p), 7))
03521           break;
03522         p++;  //skip comment
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       // string without means
03544         p = p+1;
03545         continue;
03546       }
03547       // distinguish the instruction
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             // continue to next instruction
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   //#ifdef KEY
03658 
03659   // Bug 5009: ASM: need to check operand number
03660   UINT n, index_count;
03661   char *p, *q, c;
03662 
03663   p = asm_string;
03664 
03665   // In the following loop, we identify an operand reference based on the 
03666   // following syntax: %<single-character-modifier>?<number> 
03667   while(*p != '\0') {
03668 
03669     // In case the '%' is followed by another one, consume it and continue.
03670     if (*p == '%' && *(p + 1) == '%') {
03671       p += 2; 
03672       continue;
03673     }
03674     else if (*p == '%') {
03675       p++; // (Consume the '%').
03676       // In case there is a modifer, get past it, taking care not to overshoot
03677       if (*p != '\0' && !isdigit(*p)
03678 #ifdef KEY // bug 11651
03679           && *p != 'r' && *p != 'R'
03680 #endif
03681          ) p++;
03682       // Save the start location and scan ahead, looking for a number.
03683       q = p;
03684       while (*p != '\0' && isdigit(*p)) p++;
03685       // If we got an operand reference, warn if it is not within permissible 
03686       // bounds for this asm() statement.
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           // Every time you change the text of any of the error message that's
03697           // going out - make sure the size of the message array is large 
03698           // enough!
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           // Emit the diagnostic.
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   // Bug 2486
03718   static INT asm_unique_number = 111; // each asm with a %= has a unique number
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 /* Assemble a simulated OP.
03792  */
03793 static void
03794 Assemble_Simulated_OP(OP *op, BB *bb)
03795 {
03796   /* ASM is an odd case so we handle it specially. It doesn't expand
03797    * into a series of OPs, but rather we just emit the asm string into
03798    * the assembly output.
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     // need special processing cause is variable sized
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       /* write out the instruction. */
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 /* Assemble the OPs in a BB a bundle at a time.
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; //used to count the cycle for the bb cbq
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     /* Gather up the OPs for the bundle.
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;   // these don't get emitted
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           // A type instruction, identify its property
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;  //No bundle exists with an M unit in slot 2
03954 
03955         // slot_mask |= OP_m_unit(op)? ISA_EXEC_PROPERTY_M_Unit : ISA_EXEC_PROPERTY_I_Unit;
03956         } else { slot_mask |= ISA_EXEC_Unit_Prop(OP_code(op)); }
03957           stop_mask = stop_mask << 1;
03958         }
03959 
03960         // IPFEC hacker on brp special case
03961         // brp can issue in B0, B1 and B2 while pro64 only model in B2
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 // remove this when gas can handle tags inside explicit bundle
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     // Emit the warning only when bundle formation phase is enabled (ON by
03985     // default).
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     /* Determine template.
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     // Emit the warning only when bundle formation phase is enabled (ON by
04004     // default).
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      // Print_BB(slot_op[0]->bb);
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     /* We now use bb cycles from machine model, so don't use stop bit to count */ 
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     /* Bundle prefix
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     /* Assemble the bundle.
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     /* Bundle suffix
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 /* Assemble the OPs in a BB an OP at a time.
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     // check mvtc and its consumer || mvfc ra and lnk : 
04122     // insert nop16 when needed
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;   // these don't get emitted
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  * Emit_Loop_Unrolling_Note
04158  *
04159  * Emit a loop unrolling note to the .s file, anl file, etc.
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  * Emit_Loop_Note
04207  *
04208  * Emit a loop note to the .s file, anl file, etc.
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     /* if (info) {
04237       WN *wn = LOOPINFO_wn(info);
04238       TN *trip_tn = LOOPINFO_trip_count_tn(info);
04239       BOOL constant_trip = trip_tn && TN_is_constant(trip_tn);
04240       INT depth = WN_loop_depth(wn);
04241       const char *estimated = constant_trip ? "" : "estimated ";
04242       INT64 trip_count = constant_trip ? TN_value(trip_tn) :
04243            (INT64)WN_loop_trip_est(wn);
04244       const char * const fmt =   anl_note
04245       ? " \"nesting depth: %d, %siterations: %lld\""
04246       : ", nesting depth: %d, %siterations: %lld";
04247 
04248       fprintf (file, fmt, depth, estimated, trip_count);
04249     } */
04250 
04251     //fprintf (file, "\n");
04252   } else if (anl_note) {
04253 
04254     /* Only interested in loop head messages for anl file
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  * Emit_Loop_Note
04300  *
04301  * Emit a loop note to the .s file, anl file, etc.
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     /* Only interested in loop head messages for anl file
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  * EMT_Assemble_BB
04398  *
04399  * Assemble the contents of the given BB.
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   /* DO NOT let a in-eh-range call be the last instruction in procedure
04439    * bug in Get_Unwind_Table in libstdc++ 
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   /* if swp , count the cycle of this BB */
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         //output cycle count of the BB cbq
04469         fprintf(Asm_File,"// BB:%d cycle count: %d\n",BB_id(bb),BB_cycle(bb));
04470      }
04471   }   
04472   
04473   /* List labels attached to BB: */
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   // hack to keep track of last label and offset for assembly dwarf (suneel)
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     // bug 2191
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     /* same, so do nothing */
04542   }
04543   else if (current_rid > 0) {
04544     /* changing regions */
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;  /* pretend not a region */
04554     }
04555     else {
04556         current_rid = RID_id(rid);
04557     }
04558   }
04559   else if (RID_id(rid) > 0 && !RID_is_glue_code(rid)) {
04560     /* beginning a region */
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   /* ending a region */
04568   fprintf (Asm_File, "%s END REGION %d\n", ASM_CMNT_LINE, current_rid);
04569   current_rid = 0;  /* no rid */
04570     }
04571   }
04572   if ( BB_entry(bb) ) {
04573 #ifndef KEY
04574     // replace uses of entry_name with ST_name(entry_sym)
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     // replace uses of entry_name with ST_name(entry_sym)
04586     entry_name = ST_name(entry_sym);
04587 #endif
04588 
04589 // #ifdef KEY
04590 #ifndef TARG_IA64
04591     if (strcmp(ST_name(entry_sym), Cur_PU_Name) != 0 &&
04592         PU_ftn_lang(Get_Current_PU())) { // PU entry
04593       char *buf;
04594       LABEL *label;
04595       buf = (char *)alloca(strlen(ST_name(entry_sym)) + /* EXTRA_NAME_LEN */ 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     /* Set an initial line number so that if the first inst in the BB
04606      * has no srcpos, then we'll be ok.
04607      */
04608     if (entry_srcpos) Cg_Dwarf_Add_Line_Entry (PC, entry_srcpos);
04609 
04610     if ( ST_is_not_used(entry_sym)) {
04611       // don't emit alt-entry if marked as not-used
04612   DevWarn("CG reached entry marked as unused; will ignore it (%s)\n", 
04613     ST_name(entry_sym)); // KEY
04614     }
04615     else {
04616       Set_ST_ofst(entry_sym, PC);
04617       if (strcmp( Cur_PU_Name, ST_name(entry_sym) ) != 0) /* KEY */{ 
04618     // alt-entry
04619           if ( Assembly ) {
04620       fprintf ( Asm_File, "\t%s\t%s\n", AS_AENT, ST_name(entry_sym)); // KEY
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   // I'm not sure whether to merge it or not.
04641   /* List labels attached to BB: */
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       // bug 14483: It's not clear why we need to avoid emitting labels
04652       // for ASM bbs, other than reducing the size of the assembly file.
04653       // So the code below is disabled. If we really need this optimization,
04654       // the rest of CG should say which labels are actually required,
04655       // and remove the rest.
04656 #if !defined (TARG_X8664)
04657       // We do not want to emit labels between consecutive asms.
04658       // And, we know each asm ends a BB.
04659 
04660       /* We need to emit label for bb that has a label used to mark the
04661    beginning or ending of an exception-handling region or exception handler.
04662    (bug#3068)
04663       */
04664       BOOL emit_label = TRUE;
04665       if( !BB_Has_Exc_Label(bb) ){
04666   if (/* Bug 3815 - this was probably added to avoid generating
04667        * too many asm labels. But we don't need to worry about 
04668        * it until we hit glibc kind of code. Avoid this under 
04669        * 0 optimization level when we can have code snippets like
04670        * jmp .Lt_0_19 followed by the BB labeled .Lt_0_19. 
04671        * I don't remember why we need to avoid generating extra labels 
04672        * in the first place.
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   // hack to keep track of last label and offset for assembly dwarf (suneel)
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       // fprintf ( Asm_File, "%s:\t%s 0x%llx\n", ST_name(st), ASM_CMNT, ST_ofst(st));
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   /* write out all the notes for this BB */
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 // Assumption: REGION_First_BB is the first BB in the PU. If in future,
04788 // we start having multiple regions in a PU here, we need to change the 
04789 // following. 
04790 // In such a scenario, we should need to change many of the occurrences
04791 // of REGION_First_BB above.
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 /* Routines to handle long branches. */
04826 
04827 /* The farthest distance, in bytes, we will look back for a BB without 
04828  * a fallthrough
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;  /* First long branch from this bb */
04838 } BB_INFO;
04839 
04840 static BB_INFO *bb_info;
04841 
04842 typedef struct longb_info {
04843   INT bbindex;
04844   INT32 longb_inum;   // relative pc of long-branch
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  * Find_Stub_BB
04863  *
04864  * Given a long branch, look at the already created stubs and determine
04865  * if we can just branch to one of them. To avoid some sticky problems,
04866  * we only consider stubs that are in the same direction as the
04867  * ultimate target is from this branch.
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   /* Search for a BB in the fudge zone that does not fall through to
04911    * its successor. If we find one, we insert there and we don't have to
04912    * worry about keeping anyone from falling through to the inserted
04913    * BB. The search is done in such a way as to always check the
04914    * first candidate BB even if it is outside of the fudge zone
04915    * (which would happen it its size was >= FUDGE_ZONE). We do this
04916    * because this is where we will insert the stub and we still want
04917    * to know if a branch around the stub is necessary.
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       /* BB_prev(bb_info[idx].bb_ptr) is expected never to be NULL,
04927        * but there's really no choice of what to do if it
04928        * is. Therefore rather than assert, we go ahead and check for
04929        * it, doing the right thing if we happen to find NULL.
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       /* BB_prev(bb_info[idx].bb_ptr) is expected never to be NULL,
04946        * but there's really no choice of what to do if it
04947        * is. Therefore rather than assert, we go ahead and check for
04948        * it, doing the right thing if we happen to find NULL.
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     /* No blocks were found in the fudge zone where we could avoid
04965      * placing a branch around the stub. So insert the stub as far
04966      * away as possible and insert a branch around the stub
04967      * BB to avoid falling through to it.
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     /* Set branch_around_bb's frequency to the frequency of the edge
04994      * from its predecessor to its successor.
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     /* The following is somewhat inefficient, considering that to do
05012      * part of the work, we could simply go through the appropriate
05013      * lists and update the BBLIST_item fields in the relevant BBLIST
05014      * nodes. But it's better to stick to the common interface.
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   /* recompute the addresses of all labels in the procedure. */
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 /* Takes a pointer to the bb_info array, the array length, and the
05110  * index of the (unique) element that could be out of place. Restores
05111  * the sort by bb_inum.
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   /* If we wanted to be really fancy, the following loop would be
05127    * binary search.
05128    */
05129   for ( ;
05130        i < n_bb_info &&
05131        bb_info[bbindex].bb_inum > bb_info[i].bb_inum;
05132        ++i) ;
05133   /* If we need to move the bbindex'th element upward, its destination
05134    * is just to the left of i.
05135    *
05136    * If we don't need to move upward, i == bbindex + 1.
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   /* Now the bbindex'th element's destination is just to the left of
05146    * i, regardless of anything else.
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   /* Adjust the bb_inum of those entries pushed upward by inserting
05187    * the stub BB.
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  * Compare_Long_Branches
05199  *
05200  * qsort comparison function for sorting long branches.  The goal of the 
05201  * sort is to group all branches with the same target together, with the 
05202  * branches spanning the largest distance coming first. In addition, the 
05203  * top level sorting critera is the direction of the branch. All forward
05204  * branches come first.
05205  *
05206  * ====================================================================
05207  */
05208 static INT
05209 Compare_Long_Branches(const void *p1, const void *p2)
05210 {
05211   /* qsort claims to sort things in ascending order, but in reality
05212    * it is sorting based on how this comparison function classifies
05213    * the relationship. Define some constants that make that clear.
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     /* one forward and one backward branch
05229      */
05230     return dist1 < 0 ? sort_1_after_2 : sort_1_before_2;
05231   } else if (dist1 < 0) {
05232     /* two backward branches
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     /* two forward branches
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  * Sort_Long_Branches
05260  *
05261  * Sort long branches to help streamline things when we have multiple
05262  * long branches to the same target. See Compare_Long_Branches for
05263  * description of the sorted order.
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   /* Get the linked list into a vector we can sort.
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   /* Re-create the linked list from the sorted vector.
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  * Print_Long_Branches
05299  *
05300  * Print the info for the long branches to the trace file.
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   // for branch predicts with one or more pc-relative operands,
05381   // if the target is too far away to fit in the instruction
05382   // then since not needed for correctness, just replace with a nop.
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         // replace brp with nop
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         // now make a specific nop (if has multiple nops)
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;  // so op->next is correct
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       /* Get the probability that the long branch is taken.
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       /* If there is an existing stub that branches to the final target,
05486        * then change this long branch to branch to it and we've fixed
05487        * it without addding any additional code.
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       /* Keep track of how many instruction words we add for this stub.
05507        */
05508       stub_inst_words = num_longb_inst_words;
05509       stub_bb = Create_Stub_BB (longb_list, &stub_loc, fwd_branch);
05510 
05511       /* Keep track of the location of this stub so that we might be
05512        * able to branch to it from another long branch. Note that
05513        * since the long branches are sorted by target, we delete
05514        * the list if the final target is different -- this speeds up
05515        * the searching in Find_Stub_BB. (Note that we could do some
05516        * better memory management and recycle the list members).
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       /* Set the frequency of the new BB.
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       /* Are the following two lines right? */
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       /* If the above two lines are right, the following line should
05550        * be OK, too, and something like it is required now that we
05551        * update successor and predecessor edges.
05552        */
05553       bb_info[longb_list->bbindex].bb_ptr = stub_bb;
05554 
05555       /* Now we have a problem. bb_info[longb_list->bbindex].bb_inum
05556        * refers to the position of the BB with the original long
05557        * branch in it, but longb_list->* and
05558        * bb_info[longb_list->bbindex].bb_ptr refer to the new
05559        * (potentially long) branch. This is bad because bb_inum is the
05560        * criterion used to decide whether to place a new stub, but if
05561        * the criterion is met, the stub gets placed according to
05562        * bb_ptr. The final insult is added by the fact that the
05563        * bb_info entries are sorted by bb_inum, so we can't just
05564        * update bb_inum to reflect the position of the (new,
05565        * potentially long) branch and have everything just work.
05566        *
05567        * We take the low-performance solution, and hope we don't get
05568        * hurt too bad: Figure out the bb_inum of the new potentially
05569        * long branch, and grimpse the bb_info array up or down to put
05570        * the updated bb_info record in the right place. Argh. Shoulda
05571        * used the Standard Template Library for bb_info, and then this
05572        * would all be transparent and fast...
05573        *
05574        * Issues: Should we update longb_list->longb_inum? I don't
05575        *         think so, since it doesn't get used.
05576        *         What to do about the fact that bb_inum fields aren't
05577        *         updated to reflect the insertion of the stub_bb's
05578        *         instructions? Should we update it as we shift the
05579        *         bb_info array?
05580        *
05581        * There remains a slight incorrectness in that even though
05582        * BB_Info_Maintain_Sort updates the bb_inum for each BB
05583        * containing a long branch to reflect the stub insertion, we do
05584        * not update the longb_inum fields of the longb_list
05585        * entries. This can lead to the user having to manually set
05586        * longbranch_limit. Ugh.
05587        *
05588        * To counter this problem, we should redefine the longb_inum
05589        * field to be an offset (in bytes) from the beginning of
05590        * the BB. Then the updating of the bb_inum fields will take
05591        * care of us, and calculations that once involved
05592        * longb_list->longb_inum will now involve
05593        * bb_info[longb_list->bb_ptr].bb_inum + longb_list->longb_inum.
05594        */
05595       bb_info[longb_list->bbindex].bb_inum = stub_loc;
05596 
05597       /* Add the new instructions so we can count their length
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       /* Adjust the start address of the stubs in case they moved.
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 /* Check if <pred> is a branch to <succ> that skips the first instruction
05654  * in the <succ>. This typically happens after filling the branch delay
05655  * slot with the first instruction in the target basic block.
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     // ignore dummy op.
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  * Check if bb should be aligned, 
05695  * and return number of instructions it should be aligned with.
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;   /* not zero so can divide */
05703   float noskip_freq = 0.01;
05704   INT targ_alignment;
05705   INT num_of_ops = 0;     /* zero to begin with */
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   // don't do alignment bb now
05714   return 0;
05715 #endif
05716   /*
05717    * Align loops for best processor efficiency.
05718    * Originally checked if bb_loophead, but now just
05719    * check frequency of block (in case doesn't look like proper loop,
05720    * but still has high-frequency).
05721    */
05722   if (OPT_Space)
05723     return 0; /* don't align */
05724   if (BB_freq(bb) <= 1.0)
05725     return 0; /* not frequent enough, so don't align */
05726   if (BB_prev(bb) == NULL) 
05727     return 0; /* nowhere to put nops */
05728 #ifdef TARG_IA64
05729   /* No padding if the first group in current bb contains only one bundle. */
05730         if (Num_of_OPs_in_First_Group(bb) <= ISA_MAX_SLOTS)
05731     return 0;
05732   /* don't want to add nops to previous bb 
05733    * unless current bb is loop head, or significantly more frequent. */
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   /* first check whether target is always label+4 */
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     /* mixture of skip and noskip branches, 
05755      * or just not frequent enough,
05756      * so don't align */
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; /* so word-sized */
05770   targpc /= INST_BYTES;   /* so word-sized */
05771   if (Get_Trace(TP_EMIT, 0x400)) {
05772     /* To do this right for R10K, 
05773      * need to check whether paths/bb-chains
05774      * cross cache lines.  An easier check, which is also
05775      * compatible with beast and tfp is to just do the
05776      * quad-word alignment, which guarantees at least that
05777      * the cache-line crossing will be quad-aligned.
05778      * So leave this off by default.
05779      */
05780     /* align to cache line size (16 words) */
05781     /* only do it if block would no longer cross cache line */
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 // When we have bundles, 'num' is the number of bundles, not
05802 // instructions.
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   /* If the issue window is two-bundle wide, we can clear the stop bit of bb's last op if it's set */
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     /* Choose an mfb type bundle for the nops. For we think it least likely brings hazards 
05815      * with its previous bundle and next bundle.
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                 /* 0x004010080 for Itanium */
05821 #else // TARG_IA64
05822 
05823     if (ISA_MAX_SLOTS > 1) {
05824       INT ibundle;
05825       UINT64 slot_mask;
05826 
05827       /* Choose a bundle for the nops. For now we just pick the first
05828        * bundle without a stop bit. We could chose more smartly based
05829        * on the previous contents of the BB.
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   // bug fix for OSP_139
05862   Set_OP_end_group(BB_last_op(bb));
05863 #endif
05864 }
05865 
05866 /* ====================================================================
05867  *
05868  * R_Resolve_Branches
05869  *
05870  * Assign addresses to all local labels. Fixup long branches.
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   /* check for T5 workarounds */
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     /* need prev bb to align */
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   // increment curpc by 'num' bundles
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     /* If there is no label, make one: */
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   // if large text size or has branch predicts (which are limited in size),
05932   // then check for long branches.
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  * Data Initialization
05954  *
05955  * ====================================================================
05956  * ====================================================================
05957  */
05958 
05959 static void
05960 Trace_Init_Loc ( INT scn_idx, Elf64_Xword scn_ofst, INT32 repeat)
05961 {
05962   /* Emit the section/offset/repeat as a line prefix -- the caller will
05963    * add context-specific information:
05964    */
05965 #ifdef TARG_IA64
05966   // bug fix for OSP_227
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 // because we have different EH implementation with pathscale-3.0 in cg.
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     // process exception region length
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     {// this is the 2nd label
06000   FmtAssert (first_label!=0,("EH table processing error"));
06001   scn_ofst = Write_Diff (first_label, l, scn_idx, scn_ofst);
06002   // reset
06003   first_label_seen = false;
06004   first_label = 0;
06005     }
06006     return scn_ofst;
06007 }
06008 #endif // !TARG_IA64
06009 
06010 /* ====================================================================
06011  *
06012  * Write_TCON
06013  *
06014  * Emit a TCON value to the assembly/object file.
06015  *
06016  * ====================================================================
06017  */
06018 
06019 static Elf64_Word
06020 Write_TCON (
06021   TCON  *tcon,    /* Constant to emit */
06022   INT scn_idx,    /* Section to emit it into */
06023   Elf64_Xword scn_ofst, /* Section offset to emit it at */
06024   INT32 repeat          /* Repeat count */
06025 #ifdef KEY
06026 #if !defined(TARG_IA64)
06027   , bool etable = 0
06028   , int format = 0
06029 #endif
06030 #endif // KEY
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  * Write_Symoff
06069  *
06070  * Emit a symoff value to the assembly/object file.
06071  *
06072  * ====================================================================
06073  */
06074 
06075 static Elf64_Word
06076 Write_Symoff (
06077   ST * sym,   /* Emit the address of this symbol */
06078   Elf64_Sxword sym_ofst,/*   ... plus this offset */
06079   INT scn_idx,    /* Section to emit it in */
06080   Elf64_Word scn_ofst,  /* Section offset to emit it at */
06081   INT32 repeat)   /* Repeat count */
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   /* make sure is allocated */
06098   if (!Has_Base_Block(sym)) {
06099   Allocate_Object(sym);
06100   /* if did allocate on local stack, that messes up frame length */
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   /* If the symbol is a local label that has not been assigned an address, it is
06106    * a label in a basic block that has been deleted. Emit zeros for this case 
06107    * instead of the address.
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   /* For local static symbols that do not have their own elf entry,
06123    * use the base symbol; funcs always have own elf entry. */
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   /* use PU text section rather than generic one */
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     // do object code first so base section initialized
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 // Create a IPLT entry instead of two FPTR entries 
06183 // for functions descriptor under IA-64 platform
06184 //
06185 static Elf64_Word
06186 Write_Symiplt (
06187   ST * sym,               /* Emit the address of this function disciptor */
06188   Elf64_Sxword sym_ofst,  /*   ... plus this offset */
06189   INT scn_idx,            /* Section to emit it in */
06190   Elf64_Word scn_ofst,    /* Section offset to emit it at */
06191   INT32 repeat)           /* Repeat count */
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   // The function descriptor on IA64 is of 128 bits = fptr + gp
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   /* make sure is allocated */
06209   if (!Has_Base_Block(sym))
06210   {
06211     Allocate_Object(sym);
06212     /* if did allocate on local stack, that messes up frame length */
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   /* For local static symbols that do not have their own elf entry,
06218    * use the base symbol; funcs always have own elf entry. */
06219   basesym = sym;
06220   if (Use_Separate_PU_Section (current_pu, basesym))
06221     /* use PU text section rather than generic one */
06222     basesym = PU_base;
06223   base_ofst += sym_ofst;
06224 
06225   if (Object_Code && repeat != 0)
06226   {
06227     if (Use_32_Bit_Pointers)  // GP-relative 32/64-bit addresses
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 // The function descriptor on IA64 needs 128 bits
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  * Write_Symbol
06255  *
06256  * Emit a symbol value to the assembly/object file.
06257  *
06258  * ====================================================================
06259  */
06260 
06261 static Elf64_Word
06262 Write_Symbol (
06263         ST * sym,/* Emit the address of this symbol */
06264         Elf64_Sxword sym_ofst,/*   ... plus this offset */
06265         INT scn_idx,/* Section to emit it in */
06266         Elf64_Word scn_ofst,/* Section offset to emit it at */
06267         INT32 repeat)/* Repeat count */
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   /* make sure is allocated */
06283   if (!Has_Base_Block(sym)) {
06284     Allocate_Object(sym);
06285     /* if did allocate on local stack, that messes up frame length */
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   /* If the symbol is a local label that has not been assigned an address, it is
06291    * a label in a basic block that has been deleted. Emit zeros for this case 
06292    * instead of the address.
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   /* For local static symbols that do not have their own elf entry,
06313    * use the base symbol; funcs always have own elf entry. */
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     /* use PU text section rather than generic one */
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     // do object code first so base section initialized
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 // Mach-O as 1.38 doesn't support .type
06370 #endif /* defined(BUILD_OS_DARWIN) */
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  * Write_Label
06388  *
06389  * Emit a label value to the assembly/object file.
06390  *
06391  * ====================================================================
06392  */
06393 
06394 static Elf64_Word
06395 Write_Label (
06396   LABEL_IDX lab,  /* Emit the address of this label */
06397   Elf64_Sxword lab_ofst,/*   ... plus this offset */
06398   INT scn_idx,    /* Section to emit it in */
06399   Elf64_Word scn_ofst,  /* Section offset to emit it at */
06400   INT32 repeat,   /* Repeat count */
06401   INT32 flags,          /* Label flag */
06402   mTYPE_ID mtype )      /* mTYPE_ID for label value */
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   // how to tell that label has been deleted?
06419   // for now, emit 0's.
06420 
06421   /* If the symbol is a local label that has not been assigned an address, it is
06422    * a label in a basic block that has been deleted. Emit zeros for this case 
06423    * instead of the address.
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   // Labels are local and do not have own elf entry, 
06445   // so use base symbol.
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   /* use PU text section rather than generic one */
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 { // for Label values
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, /* left symbol */
06528   ST_IDX sym2idx, /* right symbol */
06529   INT scn_idx,    /* Section to emit it in */
06530   Elf64_Word scn_ofst,  /* Section offset to emit it at */
06531   INT32 repeat,   /* Repeat count */
06532   INT size              /* 2 or 4 bytes */
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   /* symbols must have an address */
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   /* use PU text section rather than generic one */
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;  /* for Add_Bytes */
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 // Emit PIC version of a symbol, here, a typeinfo symbol
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  * Write_INITV
06645  *
06646  * Emit an initial value record to the assembly/object file.
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) // emit_typeinfo
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 // KEY
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       { // handle it differently
06790   scn_ofst = Emit_PIC_version (st, scn_ofst);
06791         break;
06792       }
06793 #endif
06794       switch (ST_sclass(st)) {
06795   case SCLASS_AUTO:
06796   { /* EH stack variable */
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   { /* EH this-pointer */
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 // we also modified Write_Symdiff
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    there seems problem with .sleb128 for as
06951    so we directly output data1 here
06952    for sym < -127, we have not implement it yet.
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   inito-> inv_blk -> list of INITVs (start with inv)
07020 
07021   [inv]                 -> mark where action table starts
07022   call-site-table-initvS
07023   [inv-action]          -> mark where type table starts
07024   action-table-initvS
07025   [cinv]                -> mark where eh-spec table starts
07026   single-type-table     
07027   eh-spec-table         
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   // Check_Initv(first, stdout);
07039   // if no corresponding call site information, doesn't emit at all 
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   // lpStart_encoding
07062   INITV_Init_Integer_2(first, MTYPE_I1, 0xff, 1);
07063   scn_ofst = Write_INITV (first, scn_idx, scn_ofst);
07064 
07065   // ttype_encoding
07066   INITV_Init_Integer_2(first, MTYPE_I1, 0xb4, 1);
07067   scn_ofst = Write_INITV (first, scn_idx, scn_ofst);
07068 
07069   // @type_start
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   // call_site_encoding
07076   INITV_Init_Integer_2(first, MTYPE_I1, 0x1, 1);
07077   scn_ofst = Write_INITV (first, scn_idx, scn_ofst);
07078 
07079   // call site length
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   // recover first
07086   INITV_Init_Integer(first, MTYPE_U4, act_inv, 1);
07087   Set_INITV_next(first, inv);
07088 
07089   // call-site table
07090   for(;inv && inv != act_inv; inv = INITV_next(inv)) {
07091     INITV_IDX prev_inv;
07092 
07093     // cs_start (SymDiff)
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     // cs_len (two labels)
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     // cs_lp
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     // cs_action
07118     scn_ofst = EH_Write_Integer(inv, scn_idx, scn_ofst, false);
07119   } // end call-site iteration
07120 
07121   // end of call site table
07122   sprintf(end_lab, ".%s%d", LSDA_CS_END, nRangeTable);
07123   fprintf(Asm_File, "%s:\n", end_lab);
07124 
07125   // action table
07126   inv = INITV_next(act_inv);
07127   for(; inv && inv != type_inv; inv = INITV_next(inv)) {
07128     // ar_filter
07129     scn_ofst = EH_Write_Integer(inv, scn_idx, scn_ofst, true);
07130 
07131     inv = INITV_next(inv);
07132     // ar_next      
07133     scn_ofst = EH_Write_Integer(inv, scn_idx, scn_ofst, true);
07134   }
07135   // end action table
07136 
07137   // single type table
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     //  if (Gen_PIC_Call_Shared || Gen_PIC_Shared)
07148         fprintf(Asm_File, "\tdata8.ua\t@gprel(DW.ref.%s#)\n", ST_name(&St_Table[type_st_idx]));
07149     //  else
07150     //    fprintf(Asm_File, "\tdata8.ua\t%s\n", ST_name(&St_Table[type_st_idx]));
07151     }
07152   }
07153 
07154   // end of single type table
07155   sprintf(end_lab, ".%s%d", LSDA_TT_END, nRangeTable);
07156   fprintf(Asm_File, "%s:\n", end_lab);
07157 
07158   // eh-spec table
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 /* Emit the initialized object to the object file */
07182 static void
07183 Write_INITO (
07184   INITO* inop,    /* Constant to emit */
07185   INT scn_idx,    /* Section to emit it into */
07186   Elf64_Xword scn_ofst) /* Section offset to emit it at */
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     /* If there's no initial value, this should be a constant symbol,
07244      * and the represented constant is the initial value:
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</