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
00038
00039
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
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 struct state {
00079 bool is_final;
00080 VISIT_KIND visit;
00081 union {
00082 TOP final;
00083 struct {
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 * )
00121
00123 {
00124 }
00125
00127 STATE Create_Unit_State(const char *tag, int pos, int width)
00129
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
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
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
00211 {
00212 initial_state = state;
00213 }
00214
00216 STATE Final(TOP topcode)
00218
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
00244
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
00257
00258
00259
00260
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;
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
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 }