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 // isa_pseudo_gen.cxx 00038 // 00039 // Generate an interface for pseudo instructions. 00040 // 00042 // 00043 00044 #include <cstddef> 00045 #include <cstdlib> 00046 #include <cstdarg> 00047 #include <cstdio> 00048 #include <cassert> 00049 #include <cstring> 00050 #include <alloca.h> 00051 00052 #include <vector> 00053 #include <list> 00054 00055 using namespace std; 00056 00057 #include "topcode.h" 00058 #include "gen_util.h" 00059 #include "targ_isa_operands.h" 00060 #include "isa_pseudo_gen.h" 00061 00062 #define MAX_REQUIRE 10 00063 #define MAX_MAP (ISA_OPERAND_max_results + ISA_OPERAND_max_operands) 00064 00065 typedef enum { 00066 UNKNOWN_DIRECTION, 00067 MACHINE_TO_PSEUDO, 00068 PSEUDO_TO_MACHINE 00069 } DIRECTION; 00070 00071 typedef struct pseudo_op { 00072 DIRECTION dir; 00073 TOP to_opc; 00074 TOP from_opc; 00075 int index; 00076 int nrequire; 00077 int require[MAX_REQUIRE+1]; 00078 int nmap; 00079 int map[2][MAX_MAP+1]; 00080 } PSEUDO_OP_INFO; 00081 00082 static int num_pseudos; 00083 static list <PSEUDO_OP_INFO *> pseudos; 00084 static PSEUDO_OP_INFO *cur_pseudo; 00085 static int max_require; 00086 static int max_map; 00087 00088 typedef enum expr_kind { 00089 EXPR_BOOL, 00090 EXPR_ARG_LVALUE, 00091 EXPR_ARG_RVALUE 00092 } EXPR_KIND; 00093 00094 typedef struct expr { 00095 struct expr *next; 00096 EXPR_KIND kind; 00097 char s[1]; // must be last 00098 } EXPR; 00099 00100 static EXPR exprs; 00101 static EXPR *last_expr = &exprs; 00102 00103 static const char * const interface[] = { 00104 "/* ====================================================================", 00105 " * ====================================================================", 00106 " *", 00107 " * Description:", 00108 " *", 00109 " * Utilities for pseudo instructions. The following are exported:", 00110 " *", 00111 " * typedef (enum) ISA_PSEUDO_DIRECTION", 00112 " * Specifies the direction of a machine/pseudo instruction", 00113 " * translation:", 00114 " *", 00115 " * ISA_PSEUDO_to_pseudo -- translate from machine to pseudo instruction", 00116 " * ISA_PSEUDO_to_machine -- translate from pseudo to machine instruction", 00117 " *", 00118 " * TOP ISA_PSEUDO_Translate(TOP opc,", 00119 " * INT64 *r,", 00120 " * INT64 *o,", 00121 " * ISA_PSEUDO_DIRECTION dir)", 00122 " * Translate the instruction with opcode <opc>, results", 00123 " * array <r> and operands array <o>. The direction of the", 00124 " * translation is controlled by <dir>. If there is a translation", 00125 " * return the translated topcode by function return value, and", 00126 " * the possibly modified operands and results by the <o> and <r>", 00127 " * arrays. If there is no translation, return <opc> by function", 00128 " * value, with unmodified operands and results. If an internal", 00129 " * error is detected, TOP_UNDEFINED is returned rather than", 00130 " * asserting.", 00131 " *", 00132 " * ====================================================================", 00133 " * ====================================================================", 00134 " */", 00135 NULL 00136 }; 00137 00139 void ISA_Pseudo_Begin(const char * /* name */) 00141 // See interface description. 00143 { 00144 } 00145 00147 static int save_expr(const char *s, EXPR_KIND kind) 00148 { 00150 // Save a unique copy of <s> for the expression kind <kind> and 00151 // return it's identifier, which is a integer (it's really the 00152 // nth string of kind <kind> in the list of all expressions. 00154 EXPR *e; 00155 int i = 1; 00156 for (e = exprs.next; e; e = e->next) { 00157 if (kind == e->kind) { 00158 if (strcmp(s, e->s) == 0) return i; 00159 ++i; 00160 } 00161 } 00162 e = (EXPR *)malloc(sizeof(EXPR) + strlen(s)); 00163 e->next = NULL; 00164 e->kind = kind; 00165 strcpy(e->s, s); 00166 last_expr->next = e; 00167 last_expr = e; 00168 return i; 00169 } 00170 00171 00173 void Machine_To_Pseudo(TOP pseudo, TOP machine) 00175 // See interface description. 00177 { 00178 cur_pseudo = new PSEUDO_OP_INFO; 00179 pseudos.push_back(cur_pseudo); 00180 bzero(cur_pseudo, sizeof(PSEUDO_OP_INFO)); 00181 cur_pseudo->from_opc = machine; 00182 cur_pseudo->to_opc = pseudo; 00183 cur_pseudo->dir = MACHINE_TO_PSEUDO; 00184 num_pseudos++; 00185 } 00186 00187 00189 void Pseudo_To_Machine(TOP machine, TOP pseudo) 00191 // See interface description. 00193 { 00194 cur_pseudo = new PSEUDO_OP_INFO; 00195 pseudos.push_back(cur_pseudo); 00196 bzero(cur_pseudo, sizeof(PSEUDO_OP_INFO)); 00197 cur_pseudo->from_opc = pseudo; 00198 cur_pseudo->to_opc = machine; 00199 cur_pseudo->dir = PSEUDO_TO_MACHINE; 00200 num_pseudos++; 00201 } 00202 00203 00205 void Require(const char *bool_expr) 00207 // See interface description. 00209 { 00210 if (cur_pseudo == NULL) { 00211 fprintf(stderr, "### Error: must specify a translation prior to " 00212 "Require(\"%s\")\n", 00213 bool_expr); 00214 exit(EXIT_FAILURE); 00215 } 00216 if (cur_pseudo->dir != MACHINE_TO_PSEUDO) { 00217 fprintf(stderr, "### Error: Require() only valid for machine-to-pseudo " 00218 "op translations\n"); 00219 exit(EXIT_FAILURE); 00220 } 00221 00222 int idx = cur_pseudo->nrequire; 00223 if (idx == MAX_REQUIRE) { 00224 fprintf(stderr, "too many requirements for pseudo %s\n", 00225 TOP_Name(cur_pseudo->to_opc)); 00226 exit(EXIT_FAILURE); 00227 } 00228 cur_pseudo->require[idx] = save_expr(bool_expr, EXPR_BOOL); 00229 cur_pseudo->nrequire = ++idx; 00230 if (idx > max_require) max_require = idx; 00231 } 00232 00233 00235 void Map_Arg(const char *lvalue, const char *expr) 00237 // See interface description. 00239 { 00240 if (cur_pseudo == NULL) { 00241 fprintf(stderr, "### Error: must specify a translation prior to " 00242 "Map_Arg(\"%s\", \"%s\")\n", 00243 lvalue, expr); 00244 exit(EXIT_FAILURE); 00245 } 00246 if (strcmp(lvalue, expr) != 0) { 00247 int idx = cur_pseudo->nmap; 00248 if (idx == MAX_MAP) { 00249 fprintf(stderr, "too many arg mappings for pseudo %s\n", 00250 TOP_Name(cur_pseudo->to_opc)); 00251 exit(EXIT_FAILURE); 00252 } 00253 cur_pseudo->map[0][idx] = save_expr(lvalue, EXPR_ARG_LVALUE); 00254 cur_pseudo->map[1][idx] = save_expr(expr, EXPR_ARG_RVALUE); 00255 cur_pseudo->nmap = ++idx; 00256 if (idx > max_map) max_map = idx; 00257 } 00258 } 00259 00260 00262 static int compare_pseudos(const void *p1, const void *p2) 00264 // qsort comparison function for sorting pseudos. 00266 { 00267 PSEUDO_OP_INFO *ps1 = *(PSEUDO_OP_INFO **)p1; 00268 PSEUDO_OP_INFO *ps2 = *(PSEUDO_OP_INFO **)p2; 00269 00270 /* Sort so pseudo-to-machine translations come first. 00271 */ 00272 if (ps1->dir != ps2->dir) { 00273 if (ps1->dir == PSEUDO_TO_MACHINE) return -1; 00274 return 1; 00275 } 00276 00277 /* Sort so that machine-to-pseudo translations are grouped together 00278 * by "from" opcode; if same opcode then sort according to number 00279 * of operands required to match such that pseudos with larger number 00280 * of matches required come first. 00281 */ 00282 int cmp = ps1->from_opc - ps2->from_opc; 00283 if (cmp == 0) cmp = ps2->nrequire - ps1->nrequire; 00284 return cmp; 00285 } 00286 00287 00289 static void verify_machine_to_pseudo(PSEUDO_OP_INFO **vec, int i) 00291 // vec[i] is the first of a sequence of one or more machine-to-pseudo 00292 // translations for the same "from" opcode. Verify that there aren't 00293 // duplicate translations. 00295 { 00296 int j; 00297 int k; 00298 int n; 00299 TOP from_opc = vec[i]->from_opc; 00300 for (j = i; j < num_pseudos && vec[j]->from_opc == from_opc; ++j) { 00301 for (k = j + 1; k < num_pseudos && vec[k]->from_opc == from_opc; ++k) { 00302 if (vec[j]->nrequire != vec[k]->nrequire) break; 00303 00304 for (n = 0; n < vec[j]->nrequire; ++n) { 00305 if (vec[j]->require[n] != vec[k]->require[n]) goto next_k; 00306 } 00307 00308 fprintf(stderr, "### Error: duplicate machine-to-pseudo translations " 00309 "for %s (to %s and %s)\n", 00310 TOP_Name(vec[j]->from_opc), 00311 TOP_Name(vec[j]->to_opc), 00312 TOP_Name(vec[k]->to_opc)); 00313 exit(EXIT_FAILURE); 00314 /*NOTREACHED*/ 00315 00316 next_k: 00317 ; 00318 } 00319 } 00320 } 00321 00322 00324 void order_pseudos(int *machine_to_pseudo_index, int *pseudo_to_machine_index) 00326 // 00328 { 00329 int i; 00330 list <PSEUDO_OP_INFO *>::iterator ps_iter; 00331 PSEUDO_OP_INFO **vec = (PSEUDO_OP_INFO **)alloca(sizeof(PSEUDO_OP_INFO *) * num_pseudos); 00332 00333 for (i = 0; i < TOP_count; ++i) { 00334 machine_to_pseudo_index[i] = num_pseudos; 00335 pseudo_to_machine_index[i] = num_pseudos; 00336 } 00337 00338 for (i = 0, ps_iter = pseudos.begin(); 00339 ps_iter != pseudos.end(); 00340 ++i, ++ps_iter) 00341 { 00342 vec[i] = *ps_iter; 00343 } 00344 qsort(vec, num_pseudos, sizeof(PSEUDO_OP_INFO *), compare_pseudos); 00345 pseudos.clear(); 00346 for (i = 0; i < num_pseudos; ++i) { 00347 PSEUDO_OP_INFO *ps = vec[i]; 00348 ps->index = i; 00349 pseudos.push_back(ps); 00350 00351 switch (ps->dir) { 00352 case MACHINE_TO_PSEUDO: 00353 if (machine_to_pseudo_index[(int)ps->from_opc] == num_pseudos) { 00354 machine_to_pseudo_index[(int)ps->from_opc] = i; 00355 verify_machine_to_pseudo(vec, i); 00356 } 00357 break; 00358 case PSEUDO_TO_MACHINE: 00359 if (pseudo_to_machine_index[(int)ps->from_opc] != num_pseudos) { 00360 fprintf(stderr, "### Error: multiple pseudo-to-machine translations for %s\n", 00361 TOP_Name(ps->from_opc)); 00362 exit(EXIT_FAILURE); 00363 /*NOTREACHED*/ 00364 } 00365 pseudo_to_machine_index[(int)ps->from_opc] = i; 00366 break; 00367 default: 00368 fprintf(stderr, "### Error: unexpected DIRECTION (%d)\n", ps->dir); 00369 exit(EXIT_FAILURE); 00370 /*NOTREACHED*/ 00371 } 00372 } 00373 } 00374 00375 00377 void ISA_Pseudo_End(void) 00379 // See interface description. 00381 { 00382 DIRECTION last_dir = UNKNOWN_DIRECTION; 00383 int machine_to_pseudo_index[TOP_count]; 00384 int pseudo_to_machine_index[TOP_count]; 00385 list <PSEUDO_OP_INFO *>::iterator ps_iter; 00386 int i; 00387 EXPR *e; 00388 char buf[1000]; 00389 #define FNAME "targ_isa_pseudo" 00390 sprintf (buf, "%s.h", FNAME); 00391 FILE* hfile = fopen(buf, "w"); 00392 sprintf (buf, "%s.c", FNAME); 00393 FILE* cfile = fopen(buf, "w"); 00394 sprintf (buf, "%s.Exported", FNAME); 00395 FILE* efile = fopen(buf, "w"); 00396 00397 fprintf(cfile, "#include \"topcode.h\"\n" 00398 "#include \"%s.h\"\n\n", FNAME); 00399 00400 sprintf (buf, "%s", FNAME); 00401 Emit_Header (hfile, buf, interface); 00402 fprintf(hfile, "#include \"topcode.h\"\n"); 00403 00404 order_pseudos(machine_to_pseudo_index, pseudo_to_machine_index); 00405 00406 ++max_require; // allow for terminator 00407 ++max_map; // allow for terminator 00408 00409 fprintf(cfile, "typedef struct {\n" 00410 " mTOP to_opc;\n" 00411 " mTOP from_opc;\n" 00412 " mUINT8 require[%d];\n" 00413 " mUINT8 map[%d][2];\n" 00414 "} PSEUDO;\n", 00415 max_require, 00416 max_map); 00417 00418 fprintf(cfile, "\nstatic const PSEUDO pseudos[%d] = {\n", num_pseudos + 1); 00419 for (ps_iter = pseudos.begin(); 00420 ps_iter != pseudos.end(); 00421 ++ps_iter) 00422 { 00423 PSEUDO_OP_INFO *info = *ps_iter; 00424 if (last_dir != info->dir) { 00425 fprintf(cfile, "\n /* %s */\n\n", 00426 info->dir == MACHINE_TO_PSEUDO 00427 ? "machine => pseudo" : "pseudo => machine"); 00428 last_dir = info->dir; 00429 } 00430 fprintf(cfile, " /* %2d: %s => %s */\n", 00431 info->index, 00432 TOP_Name((TOP)info->from_opc), 00433 TOP_Name((TOP)info->to_opc)); 00434 fprintf(cfile, " { %3d, %3d, {", 00435 info->to_opc, 00436 info->from_opc); 00437 for (i = 0; i < max_require; ++i) { 00438 fprintf(cfile, " %d,", (i < info->nrequire) ? info->require[i] : 0); 00439 } 00440 fprintf(cfile, " }, {"); 00441 for (i = 0; i < max_map; ++i) { 00442 fprintf(cfile, " {%d, %d},", 00443 (i < info->nmap) ? info->map[0][i] : 0, 00444 (i < info->nmap) ? info->map[1][i] : 0); 00445 } 00446 fprintf(cfile, " } },\n"); 00447 } 00448 fprintf(cfile, " /* %2d: TOP_UNDEFINED => TOP_UNDEFINED */\n", 00449 num_pseudos); 00450 fprintf(cfile, " { %3d, %3d, { 0 }, { {0, 0} }}\n", 00451 TOP_UNDEFINED, 00452 TOP_UNDEFINED); 00453 fprintf(cfile, "};\n"); 00454 00455 fprintf(cfile, "\nstatic const mUINT8 pseudo_index[%d][2] = {\n", TOP_count); 00456 for (i = 0; i < TOP_count; ++i) { 00457 fprintf(cfile, " { %2d, %2d }, /* %-9s */\n", 00458 machine_to_pseudo_index[i], 00459 pseudo_to_machine_index[i], 00460 TOP_Name((TOP)i)); 00461 } 00462 fprintf(cfile, "};\n"); 00463 00464 fprintf(hfile, "\ntypedef enum {\n" 00465 " ISA_PSEUDO_to_pseudo = 0,\n" 00466 " ISA_PSEUDO_to_machine = 1\n" 00467 "} ISA_PSEUDO_DIRECTION;\n"); 00468 00469 fprintf(hfile, "\nextern TOP ISA_PSEUDO_Translate(TOP opc,\n" 00470 " INT64 *r,\n" 00471 " INT64 *o,\n" 00472 " ISA_PSEUDO_DIRECTION dir);\n"); 00473 00474 fprintf(efile, "ISA_PSEUDO_Translate\n"); 00475 00476 fprintf(cfile, "\n" 00477 "#define OPND(n) (o[(n)])\n" 00478 "#define RESULT(n) (r[(n)])\n"); 00479 00480 fprintf(cfile, "\nTOP ISA_PSEUDO_Translate(TOP opc, INT64 *r, INT64 *o, ISA_PSEUDO_DIRECTION dir)\n" 00481 "{\n" 00482 " int i;\n" 00483 " int j;\n" 00484 " int n;\n" 00485 " int arg[%d];\n" 00486 " const INT idx = pseudo_index[(INT)opc][dir];\n" 00487 " const PSEUDO *pop = pseudos + idx;\n" 00488 "\n" 00489 " if (pop->from_opc != opc) return opc;\n" 00490 "\n" 00491 " if (dir == ISA_PSEUDO_to_pseudo) {\n" 00492 " do {\n" 00493 " for (i = 0;; ++i) {\n" 00494 " BOOL val;\n" 00495 " n = pop->require[i];\n" 00496 " switch (n) {\n" 00497 " case 0:\n" 00498 " goto xlate_pseudo;\n", 00499 max_map - 1); 00500 for (e = exprs.next, i = 1; e; e = e->next) { 00501 if (e->kind == EXPR_BOOL) { 00502 fprintf(cfile, " case %d:\n", i); 00503 fprintf(cfile, " val = (%s);\n", e->s); 00504 fprintf(cfile, " break;\n"); 00505 ++i; 00506 } 00507 } 00508 fprintf(cfile, " default:\n" 00509 " return TOP_UNDEFINED;\n" 00510 " }\n" 00511 " if (!val) break;\n" 00512 " }\n" 00513 " } while ((++pop)->from_opc == opc);\n" 00514 " return opc;\n" 00515 " }\n" 00516 "\n" 00517 "xlate_pseudo:\n"); 00518 if (max_map > 1) { 00519 fprintf(cfile, " for (j = 0, i = 0; (n = pop->map[i][1]); ++j, ++i) {\n" 00520 " switch (n) {\n"); 00521 for (e = exprs.next, i = 1; e; e = e->next) { 00522 if (e->kind == EXPR_ARG_RVALUE) { 00523 fprintf(cfile, " case %d:\n", i); 00524 fprintf(cfile, " arg[j] = (%s);\n", e->s); 00525 fprintf(cfile, " break;\n"); 00526 ++i; 00527 } 00528 } 00529 fprintf(cfile, " default:\n" 00530 " return TOP_UNDEFINED;\n" 00531 " }\n" 00532 " }\n" 00533 " for (j = 0, i = 0; (n = pop->map[i][0]); ++j, ++i) {\n" 00534 " switch (n) {\n"); 00535 for (e = exprs.next, i = 1; e; e = e->next) { 00536 if (e->kind == EXPR_ARG_LVALUE) { 00537 fprintf(cfile, " case %d:\n", i); 00538 fprintf(cfile, " (%s) = arg[j];\n", e->s); 00539 fprintf(cfile, " break;\n"); 00540 ++i; 00541 } 00542 } 00543 fprintf(cfile, " default:\n" 00544 " return TOP_UNDEFINED;\n" 00545 " }\n" 00546 " }\n"); 00547 } else { 00548 fprintf(cfile, " ;\n"); 00549 } 00550 fprintf(cfile, " return (TOP)pop->to_opc;\n" 00551 "}\n"); 00552 00553 Emit_Footer (hfile); 00554 }