Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 /* ==================================================================== 00037 * ==================================================================== 00038 * 00039 * 00040 * Revision history: 00041 * 10-Feb-95 - Original Version 00042 * 00043 * Description: 00044 * 00045 * This file was originally part of targ_const.c. The CG-related routines 00046 * are moved into this file. 00047 * 00048 * Refer to targ_const.c for details of description. 00049 * ==================================================================== 00050 * ==================================================================== 00051 */ 00052 00053 #include <elf.h> 00054 #include <ctype.h> 00055 00056 #define USE_STANDARD_TYPES 1 00057 #include "defs.h" 00058 #include "targ_const.h" 00059 #include "targ_const_private.h" 00060 #include "erglob.h" /* EC_Inv_Mtype */ 00061 #include "errors.h" /* Is_True(), ErrMsg(), etc. */ 00062 #include "config_asm.h" /* ASM_CMNT, etc. */ 00063 00064 #ifndef QIKKI_BE 00065 #include "stab.h" /* TY */ 00066 #endif 00068 #define APPEND_TO_DBUF(a,b) a = Targ_Append_To_Dbuf(a,b) 00069 00070 00071 // has char that can't be printed in string directive 00072 static BOOL 00073 Has_Control_Char (char *str, INT len) 00074 { 00075 INT i; 00076 for (i = 0; i < len; ++i) { 00077 if (iscntrl(str[i])) 00078 return TRUE; 00079 if (str[i] == '"') 00080 return TRUE; 00081 if (str[i] == '\\') 00082 return TRUE; 00083 } 00084 return FALSE; 00085 } 00086 00087 /* ==================================================================== 00088 * 00089 * Targ_Emit_String 00090 * 00091 * This routine emits constant strings to the file fl. The string is 00092 * defined by a pointer (str) and a length (len). This routine must 00093 * *always* output assembler commands which will occupy *exactly* len 00094 * bytes in the .o file, since the caller is relying on that. If the 00095 * str[len-1] is not the null byte, then the caller must output one. 00096 * 00097 * loc is the offset from the appropriate symbol at which we begin 00098 * putting out characters. This is used for a comment in the output 00099 * .s file only, not for any real purpose. If loc is 0, the comment 00100 * is not written out (it has already been written out). 00101 * 00102 * ==================================================================== 00103 */ 00104 void 00105 Targ_Emit_String ( FILE *fl, char *str, INT32 len, INTSC loc ) 00106 { 00107 #define MAX_LEN 8 00108 INT ch, i; 00109 INT16 n_on_line = 0; 00110 char dbuf[(1+MAX_LEN)*4], *dptr; 00111 dptr = dbuf; 00112 00113 if (loc != 0) 00114 fprintf(fl, "\t%s offset %1ld\n", ASM_CMNT, loc); 00115 00116 // if simple string, print as such 00117 if (len < 80 && str[len-1] == '\0' && ! Has_Control_Char(str,len-1)) { 00118 fprintf(fl, "\tstringz \"%s\"\n", str); 00119 return; 00120 } 00121 for ( i=0; i<len; ++i ) { 00122 ch = str[i]; 00123 fprintf ( fl, n_on_line ? ", " : "\t%s\t", AS_BYTE ); 00124 fprintf ( fl, "0x%x", ch ); 00125 APPEND_TO_DBUF(dptr, ch); 00126 ++n_on_line; 00127 if ( n_on_line == MAX_LEN ) { 00128 *dptr = '\0'; 00129 fprintf(fl, "\t%s %s", ASM_CMNT, dbuf); 00130 dptr = dbuf; 00131 fprintf ( fl, "\n" ); 00132 n_on_line = 0; 00133 } 00134 } 00135 *dptr = '\0'; 00136 fprintf(fl, "\t%s %s", ASM_CMNT, dbuf); 00137 dptr = dbuf; 00138 fprintf(fl, "\n"); 00139 00140 #if TARGET_88000 || TARGET_spc00 00141 INT l, line_len, ch, i; 00142 00143 fprintf(fl, "\t%s loc %1d\n", ASM_CMNT, loc); 00144 #define MAX_LEN 60 00145 line_len = -1; 00146 for (i=0; i<len; i++) { 00147 ch = str[i] & 0xff; 00148 if (ch < ' ' || ch > '~' || ch == '\\' || ch == '"') 00149 l = 4; 00150 else 00151 l = 1; 00152 if (line_len > (MAX_LEN-l)) { 00153 fprintf(fl, "\"\n"); 00154 line_len = -1; 00155 } 00156 if (line_len < 0) { 00157 fprintf(fl, "\t%s\t\"", AS_STRING ); 00158 line_len = 0; 00159 } 00160 if (l == 4) 00161 fprintf(fl, "\\%03o", ch); 00162 else 00163 fprintf(fl, "%c", ch); 00164 line_len += l; 00165 } 00166 Is_True(line_len, ("Expecting non zero line_len")); 00167 if (line_len >= 0) 00168 fprintf(fl, "\"\n"); 00169 #endif /* TARGET_88000 || TARGET_spc00 */ 00170 } /* Targ_Emit_String */ 00171 00172 /* ==================================================================== 00173 * 00174 * Emit_Repeated_Constant 00175 * 00176 * Emit a simple numeric constant one or more times. 00177 * To conserve space we try to emit more than one value per directive. 00178 * 00179 * ==================================================================== 00180 */ 00181 00182 static void Emit_Repeated_Constant( 00183 FILE *fl, /* file which to write */ 00184 const char *dir, /* directive name */ 00185 INT64 val, /* value to be written */ 00186 INTSC rc, /* repeat count */ 00187 INTSC maxc) /* max count per directive */ 00188 { 00189 INTSC this_rc; 00190 do { 00191 INT i; 00192 this_rc = MIN(rc, maxc); 00193 fprintf(fl, "\t%s\t%lld", dir, val); 00194 for (i = 1; i < this_rc; ++i) fprintf(fl, ", %lld", val); 00195 fprintf(fl, "\n"); 00196 } while (rc -= this_rc); 00197 } 00198 00199 /* ==================================================================== 00200 * 00201 * Targ_Emit_Const 00202 * 00203 * Print routine to be used to print constants on the assembly file. 00204 * 00205 * NOTE: There is a parallel routine to this one that writes out TCONs 00206 * to elf sections. Any changes here should be reflected in the 00207 * Em_Targ_Emit_Const routine . 00208 * 00209 * ==================================================================== 00210 */ 00211 00212 void 00213 Targ_Emit_Const (FILE *fl, /* File to which to write */ 00214 TCON tc, /* Constant to be written */ 00215 BOOL add_null, /* whether to add null to strings */ 00216 INTSC rc, /* Repeat count */ 00217 INTSC loc ) /* Location (i.e. offset from some base) */ 00218 { 00219 Is_True ( rc > 0, ("Targ_Emit_Const: repeat count is %d", rc ) ); 00220 00221 /* loc only used here (in a comment in the output file) */ 00222 fprintf(fl, "\t%s offset %1ld\n", ASM_CMNT, loc); 00223 00224 /* Loop until the repeat count is exhausted. For simple constants we'll 00225 * optimize the emission, otherwise we just repeat the whole directive. 00226 */ 00227 while (rc) { 00228 switch (TCON_ty(tc)) { 00229 case MTYPE_I1: 00230 case MTYPE_U1: 00231 Emit_Repeated_Constant ( fl, AS_BYTE, TCON_v0(tc) & 0xff, rc, 10 ); 00232 rc = 0; 00233 break; 00234 00235 case MTYPE_I2: 00236 case MTYPE_U2: 00237 Emit_Repeated_Constant ( fl, 00238 ((loc % 2) == 0 ? AS_HALF : AS_HALF_UNALIGNED), 00239 TCON_v0(tc) & 0xffff, rc, 8 ); 00240 rc = 0; 00241 break; 00242 00243 case MTYPE_I4: 00244 case MTYPE_U4: 00245 Emit_Repeated_Constant ( fl, 00246 ((loc % 4) == 0 ? AS_WORD : AS_WORD_UNALIGNED), 00247 TCON_v0(tc), rc, 4 ); 00248 rc = 0; 00249 break; 00250 00251 case MTYPE_I8: 00252 case MTYPE_U8: 00253 Emit_Repeated_Constant ( fl, 00254 ((loc % 8) == 0 ? AS_DWORD : AS_DWORD_UNALIGNED), 00255 TCON_I8(tc), rc, 2 ); 00256 rc = 0; 00257 break; 00258 00259 case MTYPE_F4: { 00260 char *p = (char *) & TCON_R4(tc); 00261 fprintf ( fl, "\t%s\t\"", AS_STRING ); 00262 for (INT i = 0; i < sizeof(TCON_R4(tc)); i++) 00263 fprintf ( fl, "\\x%02x", *(p+i) ); 00264 fprintf(fl, "\"\t%s float %#g\n", ASM_CMNT, TCON_R4(tc) ); 00265 --rc; 00266 break; 00267 } 00268 00269 case MTYPE_C4: { 00270 INT i; 00271 char *p = (char *) & TCON_R4(tc); 00272 fprintf ( fl, "\t%s\t\"", AS_STRING ); 00273 for (i = 0; i < sizeof(TCON_R4(tc)); i++) 00274 fprintf ( fl, "\\x%02x", *(p+i) ); 00275 fprintf(fl, "\"\t%s complex float real part %#g\n", ASM_CMNT, TCON_R4(tc) ); 00276 00277 p = (char *) & TCON_IR4(tc); 00278 fprintf ( fl, "\t%s\t\"", AS_STRING ); 00279 for (i = 0; i < sizeof(TCON_IR4(tc)); i++) 00280 fprintf ( fl, "\\x%02x", *(p+i) ); 00281 fprintf(fl, "\"\t%s complex float imag part %#g\n", ASM_CMNT, TCON_IR4(tc) ); 00282 --rc; 00283 break; 00284 } 00285 00286 case MTYPE_F8: { 00287 char *p = (char *) & TCON_R8(tc); 00288 fprintf ( fl, "\t%s\t\"", AS_STRING ); 00289 for (INT i = 0; i < sizeof(TCON_R8(tc)); i++) 00290 fprintf ( fl, "\\x%02x", *(p+i) ); 00291 fprintf(fl, "\"\t%s double %#g\n", ASM_CMNT, TCON_R8(tc) ); 00292 --rc; 00293 break; 00294 } 00295 00296 case MTYPE_C8: { 00297 INT i; 00298 char *p = (char *) & TCON_R8(tc); 00299 fprintf ( fl, "\t%s\t\"", AS_STRING ); 00300 for (i = 0; i < sizeof(TCON_R8(tc)); i++) 00301 fprintf ( fl, "\\x%02x", *(p+i) ); 00302 fprintf(fl, "\"\t%s complex double real part %#g\n", ASM_CMNT, TCON_R8(tc) ); 00303 00304 p = (char *) & TCON_IR8(tc); 00305 fprintf ( fl, "\t%s\t\"", AS_STRING ); 00306 for (i = 0; i < sizeof(TCON_IR8(tc)); i++) 00307 fprintf ( fl, "\\x%02x", *(p+i) ); 00308 fprintf(fl, "\"\t%s complex double imag part %#g\n", ASM_CMNT, TCON_IR8(tc) ); 00309 --rc; 00310 break; 00311 } 00312 00313 case MTYPE_FQ: { 00314 char *p = (char *) & TCON_R16(tc); 00315 fprintf ( fl, "\t%s\t\"", AS_STRING ); 00316 for (INT i = 0; i < sizeof(TCON_R16(tc)); i++) 00317 fprintf ( fl, "\\x%02x", *(p+i) ); 00318 fprintf(fl, "\"\t%s quad %#lg\n", ASM_CMNT, TCON_R16(tc) ); 00319 --rc; 00320 break; 00321 } 00322 00323 case MTYPE_CQ: { 00324 INT i; 00325 char *p = (char *) & TCON_R16(tc); 00326 fprintf ( fl, "\t%s\t\"", AS_STRING ); 00327 for (i = 0; i < sizeof(TCON_R16(tc)); i++) 00328 fprintf ( fl, "\\x%02x", *(p+i) ); 00329 fprintf(fl, "\"\t%s complex quad real part %#lg\n", ASM_CMNT, TCON_R16(tc) ); 00330 00331 p = (char *) & TCON_IR16(tc); 00332 fprintf ( fl, "\t%s\t\"", AS_STRING ); 00333 for (i = 0; i < sizeof(TCON_IR16(tc)); i++) 00334 fprintf ( fl, "\\x%02x", *(p+i) ); 00335 fprintf(fl, "\"\t%s complex quad imag part %#lg\n", ASM_CMNT, TCON_IR16(tc) ); 00336 --rc; 00337 break; 00338 } 00339 00340 case MTYPE_STRING: { 00341 INTSC count; 00342 for (count=0; count<rc; ++count) { 00343 char *p = Index_to_char_array (TCON_cp(tc)); 00344 Targ_Emit_String ( fl, p, TCON_len(tc) + (add_null ? 1 : 0), 0 ); 00345 } 00346 rc = 0; 00347 break; 00348 } 00349 00350 default: 00351 ErrMsg ( EC_Inv_Mtype, Mtype_Name(TCON_ty(tc)), 00352 "Targ_Emit_Const" ); 00353 } 00354 } 00355 } /* Targ_Emit_Const */ 00356 00357 #if defined(BACK_END) || defined(QIKKI_BE) 00358 /* ==================================================================== 00359 * 00360 * Em_Targ_Emit_Const 00361 * 00362 * Write out constant to the section. 00363 * 00364 * ==================================================================== 00365 */ 00366 00367 #include <elf.h> 00368 #include "em_elf.h" 00369 00370 void 00371 Em_Targ_Emit_Const (void *scn, /* Section to which to write */ 00372 TCON tc, /* Constant to be written */ 00373 BOOL add_null, /* whether to add null to strings */ 00374 INTSC rc) /* Repeat count */ 00375 { 00376 INTSC count; 00377 pSCNINFO section = (pSCNINFO)scn; 00378 00379 Is_True ( rc > 0, ("Em_Targ_Emit_Const: repeat count is %d", rc ) ); 00380 00381 switch (TCON_ty(tc)) { 00382 case MTYPE_I1: 00383 case MTYPE_U1: 00384 for (count = 0; count < rc; count++) { 00385 mINT8 value = TCON_v0(tc); 00386 Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1); 00387 } 00388 break; 00389 00390 case MTYPE_I2: 00391 case MTYPE_U2: 00392 for (count = 0; count < rc; count++) { 00393 mINT16 value = TCON_v0(tc); 00394 Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1); 00395 } 00396 break; 00397 00398 case MTYPE_I4: 00399 case MTYPE_U4: 00400 for (count = 0; count < rc; count++) { 00401 mINT32 value = TCON_v0(tc); 00402 Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1); 00403 } 00404 break; 00405 00406 case MTYPE_I8: 00407 case MTYPE_U8: 00408 for (count = 0; count < rc; count++) { 00409 mUINT64 value = TCON_U8(tc); 00410 Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1); 00411 } 00412 break; 00413 00414 case MTYPE_F4: 00415 for (count = 0; count < rc; count++) { 00416 float value = TCON_R4(tc); 00417 Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1); 00418 } 00419 break; 00420 00421 case MTYPE_C4: 00422 for (count = 0; count < rc; count++) { 00423 float value = TCON_R4(tc); 00424 Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1); 00425 value = TCON_IR4(tc); 00426 Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1); 00427 } 00428 break; 00429 00430 case MTYPE_F8: 00431 for (count = 0; count < rc; count++) { 00432 double value = TCON_R8(tc); 00433 Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1); 00434 } 00435 break; 00436 00437 case MTYPE_C8: 00438 for (count = 0; count < rc; count++) { 00439 double value = TCON_R8(tc); 00440 Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1); 00441 value = TCON_IR8(tc); 00442 Em_Add_Bytes_To_Scn (section, (char *) &value, sizeof(value), 1); 00443 } 00444 break; 00445 00446 case MTYPE_FQ: 00447 for (count = 0; count < rc; count++) { 00448 double *pvalue = &(TCON_R8(tc)); 00449 Em_Add_Bytes_To_Scn (section, (char *) pvalue, sizeof(double), 1); 00450 Em_Add_Bytes_To_Scn (section, (char *) (pvalue+1), sizeof(double), 1); 00451 } 00452 break; 00453 00454 case MTYPE_CQ: 00455 for (count = 0; count < rc; count++) { 00456 double *pvalue = &(TCON_R8(tc)); 00457 Em_Add_Bytes_To_Scn (section, (char *) pvalue, sizeof(double), 1); 00458 Em_Add_Bytes_To_Scn (section, (char *) (pvalue+1), sizeof(double), 1); 00459 pvalue = &(TCON_IR8(tc)); 00460 Em_Add_Bytes_To_Scn (section, (char *) pvalue, sizeof(double), 1); 00461 Em_Add_Bytes_To_Scn (section, (char *) (pvalue+1), sizeof(double), 1); 00462 } 00463 break; 00464 00465 case MTYPE_STRING: 00466 for (count = 0; count < rc; count++) { 00467 Em_Add_Bytes_To_Scn (section, 00468 Index_to_char_array (TCON_cp(tc)), 00469 TCON_len(tc) + (add_null ? 1 : 0), 00470 1); 00471 } 00472 break; 00473 00474 default: 00475 Is_True ( FALSE, ( "Targ_Emit_Const can not handle type %s", 00476 Mtype_Name(TCON_ty(tc)) ) ); 00477 } 00478 } /* Em_Targ_Emit_Const */ 00479 #endif /* BACK_END */ 00480 00481 #if !defined(MONGOOSE_BE) && !defined(QIKKI_BE) 00482 void 00483 Targ_Emit_Space( FILE *fl, INT len, INT loc) 00484 { 00485 fprintf(fl, "\t%s %1d\t%s %1d\n", AS_SPACE, len, ASM_CMNT, loc); 00486 } 00487 00488 void 00489 Targ_Emit_Cmt(fl, str) 00490 FILE *fl; 00491 char *str; 00492 { 00493 fprintf(fl, "\t%s %s\n", ASM_CMNT, str); 00494 } 00495 00496 /*---------------------------------------------------------------------- 00497 * Print on the file 'fl' the length of the dimension described 00498 * as going from 'tree_lower' to 'tree_upper'. This can only be 00499 * done correctly at compile-time when both 'tree_lower' and 00500 * 'tree_upper' are NDs for constants (maybe even integer 00501 * constants?). If they are not both integer constants, just print 00502 * a default dimension of '1'. 00503 *--------------------------------------------------------------------*/ 00504 void 00505 Targ_Emit_Dim (FILE *fl, TY *ty, INT dim) 00506 { 00507 #if TODO_MONGOOSE 00508 INT32 coff_dim = 1; /* default value */ 00509 ND *tree_lower; 00510 ND *tree_upper; 00511 00512 Is_True(TY_kind(ty) == KIND_ARRAY, ("Non-array in Targ_Emit_Dim")); 00513 Is_True(dim >= 0 && dim < TY_AR_ndims(ty), 00514 ("Illegal dimension %d in Targ_Emit_Dim", dim)); 00515 00516 tree_lower = TY_AR_fbnd(ty,dim); 00517 tree_upper = TY_AR_tbnd(ty,dim); 00518 if ( (tree_upper != NULL) && (tree_lower != NULL) ) { 00519 TCON tc_upper, tc_lower; 00520 if ( (Is_Const(tree_upper,&tc_upper) == MTYPE_I4) && 00521 (Is_Const(tree_lower,&tc_lower) == MTYPE_I4) ) { 00522 INT32 upper_bound = TCON_v0(tc_upper); 00523 INT32 lower_bound = TCON_v0(tc_lower); 00524 coff_dim = upper_bound - lower_bound + 1; 00525 } 00526 } 00527 00528 fprintf ( fl, "%d", coff_dim ); 00529 #endif /* TODO_MONGOOSE */ 00530 } /* Targ_Emit_Dim */ 00531 #endif /* !defined(MONGOOSE_BE) && !defined(QIKKI_BE) */