00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00042
00043
00044
00046
00047
00048
00049
00050
00051
00052 #include <stddef.h>
00053 #include <stdlib.h>
00054 #include <stdarg.h>
00055 #include <string.h>
00056 #include <stdio.h>
00057 #include <assert.h>
00058 #include <alloca.h>
00059 #include <list>
00060 #include "topcode.h"
00061 #include "gen_util.h"
00062 #include "isa_decode_gen.h"
00063
00064 typedef enum { INST_STATE, UNIT_STATE } STATE_TYPE;
00065
00066 typedef enum {
00067 VISIT_UNVISITED,
00068 VISIT_GEN_DATA,
00069 VISIT_GEN_CODE
00070 } VISIT_KIND;
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 struct state {
00083 bool is_final;
00084 VISIT_KIND visit;
00085 union {
00086 TOP final;
00087 struct {
00088 const char *tag;
00089 int idx;
00090 int pos;
00091 int width;
00092 STATE *transition;
00093 STATE_TYPE stype;
00094 int casenum;
00095 } i;
00096 } u;
00097 };
00098
00099 static STATE initial_state;
00100 static std::list<STATE> all_states;
00101
00102 static const char * const interface[] = {
00103 "/* ====================================================================",
00104 " * ====================================================================",
00105 " *",
00106 " * Description:",
00107 " *",
00108 " * Utilities for decoding binary instructions. The following",
00109 " * are exported:",
00110 " *",
00111 " * TOP ISA_Decode_Inst(const ISA_PACK_INST *pinst, ISA_EXEC_UNIT unit)",
00112 " * Decode the instruction pointed to by <pinst> in execution unit",
00113 " * <unit> and return its opcode by function return value.",
00114 " *",
00115 " * ====================================================================",
00116 " * ====================================================================",
00117 " */",
00118 NULL
00119 };
00120
00121
00123 void ISA_Decode_Begin(const char * )
00125
00127 {
00128 }
00129
00131 STATE Create_Unit_State(const char *tag, int pos, int width)
00133
00135 {
00136 int i;
00137 STATE state = new struct state;
00138 state->is_final = false;
00139 state->visit = VISIT_UNVISITED;
00140 state->u.i.tag = tag;
00141 state->u.i.idx = 0;
00142 state->u.i.pos = pos;
00143 state->u.i.width = width;
00144 state->u.i.transition = new STATE[1 << width];
00145 for (i = 0; i < (1 << width); ++i) state->u.i.transition[i] = NULL;
00146 state->u.i.stype = UNIT_STATE;
00147 all_states.push_back(state);
00148 return state;
00149 }
00150
00152 STATE Create_Inst_State(const char *tag, int idx, int pos, int width)
00154
00156 {
00157 int i;
00158 STATE state = new struct state;
00159 state->is_final = false;
00160 state->visit = VISIT_UNVISITED;
00161 state->u.i.tag = tag;
00162 state->u.i.idx = idx;
00163 state->u.i.pos = pos;
00164 state->u.i.width = width;
00165 state->u.i.transition = new STATE[1 << width];
00166 for (i = 0; i < (1 << width); ++i) state->u.i.transition[i] = NULL;
00167 state->u.i.stype = INST_STATE;
00168 all_states.push_back(state);
00169 return state;
00170 }
00171
00173 void Transitions(STATE state, ...)
00175
00177 {
00178 int n;
00179 va_list ap;
00180 STATE transition;
00181
00182 if (state->is_final) {
00183 fprintf(stderr, "### Error: can't specify transistions for a final state\n");
00184 exit(EXIT_FAILURE);
00185 }
00186
00187 va_start(ap, state);
00188 while ((n = va_arg(ap, int)) != END_TRANSITIONS) {
00189 if (n < 0 || n >= (1 << state->u.i.width)) {
00190 fprintf(stderr, "### Error: transition %d of %s is out-of-range\n",
00191 n, state->u.i.tag);
00192 exit(EXIT_FAILURE);
00193 }
00194 if (state->u.i.transition[n]) {
00195 fprintf(stderr, "### Error: transition %d of %s multiply specified\n",
00196 n, state->u.i.tag);
00197 exit(EXIT_FAILURE);
00198 }
00199 transition = va_arg(ap, STATE);
00200 if ((unsigned long)transition < TOP_count) {
00201 fprintf(stderr, "### Error: transition %d of %s looks like it should be Final()\n",
00202 n, state->u.i.tag);
00203 exit(EXIT_FAILURE);
00204 }
00205 state->u.i.transition[n] = transition;
00206 }
00207 va_end(ap);
00208 }
00209
00211 void Initial_State(STATE state)
00213
00215 {
00216 initial_state = state;
00217 }
00218
00220 STATE Final(TOP topcode)
00222
00224 {
00225 STATE state = new struct state;
00226 state->is_final = true;
00227 state->u.final = topcode;
00228 all_states.push_back(state);
00229 return state;
00230 }
00231
00233 static int Compare_NonFinals(const void *p1, const void *p2)
00235
00237 {
00238 STATE s1 = *(STATE *)p1;
00239 STATE s2 = *(STATE *)p2;
00240
00241 return strcmp(s1->u.i.tag, s2->u.i.tag);
00242 }
00243
00245 static void Visit_State(STATE state, FILE *f, VISIT_KIND vk)
00247
00248
00250 {
00251 static int indent;
00252 int i;
00253 int ntrans;
00254 int max_top;
00255 STATE *nonfinals;
00256 int n_nonfinals;
00257
00258 assert(!state->is_final);
00259
00260
00261
00262
00263
00264
00265
00266 if (state->visit == vk && vk == VISIT_GEN_DATA) return;
00267 state->visit = vk;
00268
00269 indent += 2;
00270 ntrans = 1 << state->u.i.width;
00271
00272 nonfinals = (STATE *)alloca(sizeof(struct state) * ntrans);
00273 n_nonfinals = 0;
00274 for (i = 0; i < ntrans; ++i) {
00275 STATE newstate = state->u.i.transition[i];
00276 if (newstate) {
00277 if (!newstate->is_final) {
00278 nonfinals[n_nonfinals++] = newstate;
00279 } else {
00280 newstate->visit = vk;
00281 }
00282 }
00283 }
00284 qsort(nonfinals, n_nonfinals, sizeof(STATE *), Compare_NonFinals);
00285
00286 if (vk == VISIT_GEN_CODE) {
00287 fprintf(f, "%*sopc = (", indent, "");
00288 if (state->u.i.stype == INST_STATE) {
00289 fprintf(f, "pinst[%d]", state->u.i.idx);
00290 } else {
00291 fprintf(f, "unit");
00292 }
00293 fprintf(f, " >> %d) & 0x%x;\n", state->u.i.pos, ntrans - 1);
00294
00295 fprintf(f, "%*stop = state_%s_tab[opc];\n", indent, "", state->u.i.tag);
00296 if (n_nonfinals) fprintf(f, "%*sswitch (top) {\n", indent, "");
00297 }
00298
00299 max_top = TOP_UNDEFINED;
00300 for (i = 0; i < n_nonfinals; ++i) {
00301 STATE newstate = nonfinals[i];
00302 ++max_top;
00303 newstate->u.i.casenum = max_top;
00304 if (vk == VISIT_GEN_CODE) {
00305 fprintf(f, "%*scase %3d: /* %s */\n",
00306 indent, "",
00307 max_top,
00308 newstate->u.i.tag);
00309 }
00310 if ( i + 1 == n_nonfinals
00311 || strcmp(newstate->u.i.tag, nonfinals[i+1]->u.i.tag))
00312 {
00313 Visit_State(newstate, f, vk);
00314 if (vk == VISIT_GEN_CODE) fprintf(f, "%*sbreak;\n", indent + 2, "");
00315 }
00316 }
00317
00318 if (vk == VISIT_GEN_DATA) {
00319 int col;
00320 const char *top_type;
00321 if (max_top < 256) {
00322 top_type = "mUINT8";
00323 } else if (max_top < 65536) {
00324 top_type = "mUINT16";
00325 } else {
00326 top_type = "mUINT32";
00327 }
00328 fprintf(f, "\nstatic const %s state_%s_tab[%d] = {",
00329 top_type,
00330 state->u.i.tag,
00331 ntrans);
00332 col = 8;
00333 for (i = 0; i < ntrans; ++i) {
00334 STATE newstate = state->u.i.transition[i];
00335 if (col == 8) {
00336 fprintf(f, "\n ");
00337 col = 0;
00338 }
00339 if (newstate == NULL) {
00340 fprintf(f, " %4d,", TOP_UNDEFINED);
00341 } else if (newstate->is_final) {
00342 fprintf(f, " %4d,", newstate->u.final);
00343 } else {
00344 fprintf(f, " %4d,", newstate->u.i.casenum);
00345 }
00346
00347 ++col;
00348 }
00349
00350 fprintf(f, "\n};\n");
00351 } else if (vk == VISIT_GEN_CODE) {
00352 if (n_nonfinals) fprintf(f, "%*s}\n", indent, "");
00353 }
00354 indent -= 2;
00355 }
00356
00358 void ISA_Decode_End(void)
00360
00362 {
00363 std::list<STATE>::iterator state_iter;
00364 char buf[1000];
00365 #define FNAME "targ_isa_decode"
00366 sprintf (buf, "%s.h", FNAME);
00367 FILE* hfile = fopen(buf, "w");
00368 sprintf (buf, "%s.c", FNAME);
00369 FILE* cfile = fopen(buf, "w");
00370 sprintf (buf, "%s.Exported", FNAME);
00371 FILE* efile = fopen(buf, "w");
00372
00373 fprintf(cfile, "#include \"topcode.h\"\n"
00374 "#include \"targ_isa_bundle.h\"\n"
00375 "#include \"targ_isa_pack.h\"\n"
00376 "#include \"%s.h\"\n\n", FNAME);
00377
00378 sprintf (buf, "%s", FNAME);
00379 Emit_Header (hfile, buf, interface);
00380 fprintf(hfile, "#include \"topcode.h\"\n"
00381 "#include \"targ_isa_bundle.h\"\n"
00382 "#include \"targ_isa_pack.h\"\n");
00383
00384 if (initial_state == NULL) {
00385 fprintf(stderr, "### Error: no initial decode state specified\n");
00386 exit(EXIT_FAILURE);
00387 }
00388
00389 Visit_State(initial_state, cfile, VISIT_GEN_DATA);
00390
00391 fprintf(efile, "ISA_Decode_Inst\n");
00392
00393 fprintf(hfile, "\nextern TOP ISA_Decode_Inst(const ISA_PACK_INST *pinst, ISA_EXEC_UNIT unit);\n");
00394
00395 fprintf(cfile, "\nTOP ISA_Decode_Inst(const ISA_PACK_INST *pinst, ISA_EXEC_UNIT unit)\n"
00396 "{\n"
00397 " INT top;\n"
00398 " INT opc;\n");
00399 Visit_State(initial_state, cfile, VISIT_GEN_CODE);
00400 fprintf(cfile, " return (TOP)top;\n"
00401 "}\n");
00402
00403 for (state_iter = all_states.begin();
00404 state_iter != all_states.end();
00405 ++state_iter)
00406 {
00407 STATE state = *state_iter;
00408 if (state->visit == VISIT_UNVISITED) {
00409 if (state->is_final) {
00410 fprintf(stderr, "### Warning: final state \"%s\" is unused\n",
00411 TOP_Name(state->u.final));
00412 } else {
00413 fprintf(stderr, "### Warning: intermediate state \"%s\" is unused\n",
00414 state->u.i.tag);
00415 }
00416 }
00417 }
00418
00419 Emit_Footer (hfile);
00420 }