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_decode_gen.cxx 00038 // 00039 // Generate an interface for decoding instructions. 00040 // 00042 // 00043 00044 #include <stddef.h> 00045 #include <stdlib.h> 00046 #include <stdarg.h> 00047 #include <string.h> 00048 #include <stdio.h> 00049 #include <assert.h> 00050 #include <alloca.h> 00051 00052 #include <list> 00053 00054 using namespace std; 00055 00056 #include "topcode.h" 00057 #include "gen_util.h" 00058 #include "isa_decode_gen.h" 00059 00060 typedef enum { INST_STATE, UNIT_STATE } STATE_TYPE; 00061 00062 typedef enum { 00063 VISIT_UNVISITED, 00064 VISIT_GEN_DATA, 00065 VISIT_GEN_CODE 00066 } VISIT_KIND; 00067 00068 /* This struct is used to hold the information that describes 00069 * a state. The information is dependent on whether or not the 00070 * state is a final state or not. 00071 * 00072 * Final states are described completely by a topcode. 00073 * 00074 * Intermediate states, have one or more transitions to new states, 00075 * and a bitfield description of an instruction being decoded, 00076 * that determines which transition is taken. 00077 */ 00078 struct state { 00079 bool is_final; 00080 VISIT_KIND visit; 00081 union { 00082 TOP final; // final state 00083 struct { // intermediate state 00084 const char *tag; 00085 int idx; 00086 int pos; 00087 int width; 00088 STATE *transition; 00089 STATE_TYPE stype; 00090 int casenum; 00091 } i; 00092 } u; 00093 }; 00094 00095 static STATE initial_state; 00096 static list <STATE> all_states; 00097 00098 static const char * const interface[] = { 00099 "/* ====================================================================", 00100 " * ====================================================================", 00101 " *", 00102 " * Description:", 00103 " *", 00104 " * Utilities for decoding binary instructions. The following", 00105 " * are exported:", 00106 " *", 00107 " * TOP ISA_Decode_Inst(const ISA_PACK_INST *pinst, ISA_EXEC_UNIT unit)", 00108 " * Decode the instruction pointed to by <pinst> in execution unit", 00109 " * <unit> and return its opcode by function return value.", 00110 " *", 00111 " * ====================================================================", 00112 " * ====================================================================", 00113 " */", 00114 NULL 00115 }; 00116 00117 00119 void ISA_Decode_Begin(const char * /* name */) 00121 // See interface description. 00123 { 00124 } 00125 00127 STATE Create_Unit_State(const char *tag, int pos, int width) 00129 // See interface description. 00131 { 00132 int i; 00133 STATE state = new struct state; 00134 state->is_final = false; 00135 state->visit = VISIT_UNVISITED; 00136 state->u.i.tag = tag; 00137 state->u.i.idx = 0; 00138 state->u.i.pos = pos; 00139 state->u.i.width = width; 00140 state->u.i.transition = new STATE[1 << width]; 00141 for (i = 0; i < (1 << width); ++i) state->u.i.transition[i] = NULL; 00142 state->u.i.stype = UNIT_STATE; 00143 all_states.push_back(state); 00144 return state; 00145 } 00146 00148 STATE Create_Inst_State(const char *tag, int idx, int pos, int width) 00150 // See interface description. 00152 { 00153 int i; 00154 STATE state = new struct state; 00155 state->is_final = false; 00156 state->visit = VISIT_UNVISITED; 00157 state->u.i.tag = tag; 00158 state->u.i.idx = idx; 00159 state->u.i.pos = pos; 00160 state->u.i.width = width; 00161 state->u.i.transition = new STATE[1 << width]; 00162 for (i = 0; i < (1 << width); ++i) state->u.i.transition[i] = NULL; 00163 state->u.i.stype = INST_STATE; 00164 all_states.push_back(state); 00165 return state; 00166 } 00167 00169 void Transitions(STATE state, ...) 00171 // See interface description. 00173 { 00174 int n; 00175 va_list ap; 00176 STATE transition; 00177 00178 if (state->is_final) { 00179 fprintf(stderr, "### Error: can't specify transistions for a final state\n"); 00180 exit(EXIT_FAILURE); 00181 } 00182 00183 va_start(ap, state); 00184 while ((n = va_arg(ap, int)) != END_TRANSITIONS) { 00185 if (n < 0 || n >= (1 << state->u.i.width)) { 00186 fprintf(stderr, "### Error: transition %d of %s is out-of-range\n", 00187 n, state->u.i.tag); 00188 exit(EXIT_FAILURE); 00189 } 00190 if (state->u.i.transition[n]) { 00191 fprintf(stderr, "### Error: transition %d of %s multiply specified\n", 00192 n, state->u.i.tag); 00193 exit(EXIT_FAILURE); 00194 } 00195 transition = va_arg(ap, STATE); 00196 if ((unsigned long)transition < TOP_count) { 00197 fprintf(stderr, "### Error: transition %d of %s looks like it should be Final()\n", 00198 n, state->u.i.tag); 00199 exit(EXIT_FAILURE); 00200 } 00201 state->u.i.transition[n] = transition; 00202 } 00203 va_end(ap); 00204 } 00205 00207 void Initial_State(STATE state) 00209 // See interface description. 00211 { 00212 initial_state = state; 00213 } 00214 00216 STATE Final(TOP topcode) 00218 // See interface description. 00220 { 00221 STATE state = new struct state; 00222 state->is_final = true; 00223 state->u.final = topcode; 00224 all_states.push_back(state); 00225 return state; 00226 } 00227 00229 static int Compare_NonFinals(const void *p1, const void *p2) 00231 // 00233 { 00234 STATE s1 = *(STATE *)p1; 00235 STATE s2 = *(STATE *)p2; 00236 00237 return strcmp(s1->u.i.tag, s2->u.i.tag); 00238 } 00239 00241 static void Visit_State(STATE state, FILE *f, VISIT_KIND vk) 00243 // Visit <state> and the states it leads to and perform the 00244 // actions necessary for the kind of visitation specified by <vk>. 00246 { 00247 static int indent; 00248 int i; 00249 int ntrans; 00250 int max_top; 00251 STATE *nonfinals; 00252 int n_nonfinals; 00253 00254 assert(!state->is_final); 00255 00256 /* If we've been here, then for data, just return so we 00257 * don't generate the same data twice. For code, we emit 00258 * the whole thing again. Alternatively we could have 00259 * generated a label on the first state and then just 00260 * goto it here. 00261 */ 00262 if (state->visit == vk && vk == VISIT_GEN_DATA) return; 00263 state->visit = vk; 00264 00265 indent += 2; 00266 ntrans = 1 << state->u.i.width; 00267 00268 nonfinals = (STATE *)alloca(sizeof(struct state) * ntrans); 00269 n_nonfinals = 0; 00270 for (i = 0; i < ntrans; ++i) { 00271 STATE newstate = state->u.i.transition[i]; 00272 if (newstate) { 00273 if (!newstate->is_final) { 00274 nonfinals[n_nonfinals++] = newstate; 00275 } else { 00276 newstate->visit = vk; // only used for unused state detection 00277 } 00278 } 00279 } 00280 qsort(nonfinals, n_nonfinals, sizeof(STATE *), Compare_NonFinals); 00281 00282 if (vk == VISIT_GEN_CODE) { 00283 fprintf(f, "%*sopc = (", indent, ""); 00284 if (state->u.i.stype == INST_STATE) { 00285 fprintf(f, "pinst[%d]", state->u.i.idx); 00286 } else { 00287 fprintf(f, "unit"); 00288 } 00289 fprintf(f, " >> %d) & 0x%x;\n", state->u.i.pos, ntrans - 1); 00290 00291 fprintf(f, "%*stop = state_%s_tab[opc];\n", indent, "", state->u.i.tag); 00292 if (n_nonfinals) fprintf(f, "%*sswitch (top) {\n", indent, ""); 00293 } 00294 00295 max_top = TOP_UNDEFINED; 00296 for (i = 0; i < n_nonfinals; ++i) { 00297 STATE newstate = nonfinals[i]; 00298 ++max_top; 00299 newstate->u.i.casenum = max_top; 00300 if (vk == VISIT_GEN_CODE) { 00301 fprintf(f, "%*scase %3d: /* %s */\n", 00302 indent, "", 00303 max_top, 00304 newstate->u.i.tag); 00305 } 00306 if ( i + 1 == n_nonfinals 00307 || strcmp(newstate->u.i.tag, nonfinals[i+1]->u.i.tag)) 00308 { 00309 Visit_State(newstate, f, vk); 00310 if (vk == VISIT_GEN_CODE) fprintf(f, "%*sbreak;\n", indent + 2, ""); 00311 } 00312 } 00313 00314 if (vk == VISIT_GEN_DATA) { 00315 int col; 00316 const char *top_type; 00317 if (max_top < 256) { 00318 top_type = "mUINT8"; 00319 } else if (max_top < 65536) { 00320 top_type = "mUINT16"; 00321 } else { 00322 top_type = "mUINT32"; 00323 } 00324 fprintf(f, "\nstatic const %s state_%s_tab[%d] = {", 00325 top_type, 00326 state->u.i.tag, 00327 ntrans); 00328 col = 8; 00329 for (i = 0; i < ntrans; ++i) { 00330 STATE newstate = state->u.i.transition[i]; 00331 if (col == 8) { 00332 fprintf(f, "\n "); 00333 col = 0; 00334 } 00335 if (newstate == NULL) { 00336 fprintf(f, " %4d,", TOP_UNDEFINED); 00337 } else if (newstate->is_final) { 00338 fprintf(f, " %4d,", newstate->u.final); 00339 } else { 00340 fprintf(f, " %4d,", newstate->u.i.casenum); 00341 } 00342 00343 ++col; 00344 } 00345 00346 fprintf(f, "\n};\n"); 00347 } else if (vk == VISIT_GEN_CODE) { 00348 if (n_nonfinals) fprintf(f, "%*s}\n", indent, ""); 00349 } 00350 indent -= 2; 00351 } 00352 00354 void ISA_Decode_End(void) 00356 // See interface description. 00358 { 00359 list <STATE>::iterator state_iter; 00360 char buf[1000]; 00361 #define FNAME "targ_isa_decode" 00362 sprintf (buf, "%s.h", FNAME); 00363 FILE* hfile = fopen(buf, "w"); 00364 sprintf (buf, "%s.c", FNAME); 00365 FILE* cfile = fopen(buf, "w"); 00366 sprintf (buf, "%s.Exported", FNAME); 00367 FILE* efile = fopen(buf, "w"); 00368 00369 fprintf(cfile, "#include \"topcode.h\"\n" 00370 "#include \"targ_isa_bundle.h\"\n" 00371 "#include \"targ_isa_pack.h\"\n" 00372 "#include \"%s.h\"\n\n", FNAME); 00373 00374 sprintf (buf, "%s", FNAME); 00375 Emit_Header (hfile, buf, interface); 00376 fprintf(hfile, "#include \"topcode.h\"\n" 00377 "#include \"targ_isa_bundle.h\"\n" 00378 "#include \"targ_isa_pack.h\"\n"); 00379 00380 if (initial_state == NULL) { 00381 fprintf(stderr, "### Error: no initial decode state specified\n"); 00382 exit(EXIT_FAILURE); 00383 } 00384 00385 Visit_State(initial_state, cfile, VISIT_GEN_DATA); 00386 00387 fprintf(efile, "ISA_Decode_Inst\n"); 00388 00389 fprintf(hfile, "\nextern TOP ISA_Decode_Inst(const ISA_PACK_INST *pinst, ISA_EXEC_UNIT unit);\n"); 00390 00391 fprintf(cfile, "\nTOP ISA_Decode_Inst(const ISA_PACK_INST *pinst, ISA_EXEC_UNIT unit)\n" 00392 "{\n" 00393 " INT top;\n" 00394 " INT opc;\n"); 00395 Visit_State(initial_state, cfile, VISIT_GEN_CODE); 00396 fprintf(cfile, " return (TOP)top;\n" 00397 "}\n"); 00398 00399 for (state_iter = all_states.begin(); 00400 state_iter != all_states.end(); 00401 ++state_iter) 00402 { 00403 STATE state = *state_iter; 00404 if (state->visit == VISIT_UNVISITED) { 00405 if (state->is_final) { 00406 fprintf(stderr, "### Warning: final state \"%s\" is unused\n", 00407 TOP_Name(state->u.final)); 00408 } else { 00409 fprintf(stderr, "### Warning: intermediate state \"%s\" is unused\n", 00410 state->u.i.tag); 00411 } 00412 } 00413 } 00414 00415 Emit_Footer (hfile); 00416 }