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 <cstddef>
00045 #include <cstdlib>
00046 #include <cstdarg>
00047 #include <cstdio>
00048 #include <cassert>
00049 #include <cstring>
00050
00051 #include <vector>
00052 #include <list>
00053
00054 using namespace std;
00055
00056 #include "topcode.h"
00057 #include "targ_isa_properties.h"
00058 #include "gen_util.h"
00059 #include "isa_print_gen.h"
00060
00061
00062
00063
00064
00065 #define MAX_OPNDS 6
00066 #define MAX_RESULTS 2
00067
00068
00069 typedef enum {
00070 END = 0,
00071 NAME = 1,
00072 OPND = 2,
00073 RESULT = OPND+MAX_OPNDS
00074 } COMP_TYPE;
00075
00076 #define MAX_LISTING_OPERANDS (RESULT+MAX_RESULTS)
00077
00078 struct isa_print_type {
00079 const char *name;
00080 const char *format_string;
00081 };
00082
00083 struct list_info {
00084 isa_print_type *type;
00085 unsigned char args;
00086 unsigned char arg[MAX_LISTING_OPERANDS];
00087 int index;
00088 bool have_name;
00089 };
00090
00091 typedef list_info *LISTING_INFO;
00092
00093
00094 struct op_pr {
00095 list_info *desc;
00096 struct op_pr *next;
00097 };
00098
00099 static list<LISTING_INFO> all_prints;
00100 static LISTING_INFO current_print_desc;
00101 static op_pr *op_prints[TOP_count+1];
00102 static list<op_pr*> op_prints_list;
00103 static int list_index;
00104 static const char *(*asmname)(TOP topcode);
00105 static bool top_specified[TOP_count];
00106
00107 static const char * const interface[] = {
00108 "/* ====================================================================",
00109 " * ====================================================================",
00110 " *",
00111 " * Description:",
00112 " *",
00113 " * A description of how to print the operands of ISA instructions",
00114 " * in ascii. The description exports the following:",
00115 " *",
00116 " * typedef (enum) ISA_PRINT_COMP",
00117 " * An enumeration of the instruction components to be printed.",
00118 " *",
00119 " * typedef (struct) ISA_PRINT_INFO",
00120 " * Describes how one particular instruction is printed.",
00121 " * The contents are private.",
00122 " *",
00123 " * const INT ISA_PRINT_COMP_MAX",
00124 " * The maximum number of components to be printed for any instruction.",
00125 " *",
00126 " * const ISA_PRINT_INFO *ISA_PRINT_Info(TOP topcode)",
00127 " * Returns a pointer to the printing description for the",
00128 " * instruction specified by 'topcode'.",
00129 " *",
00130 " * The instruction is printed by calling one of the printf routines",
00131 " * with the format string returned from ISA_PRINT_INFO_Format.",
00132 " * Additional printf arguments, necessitated by the format string,",
00133 " * are described by ISA_PRINT_INFO_Comp.",
00134 " *",
00135 " * INT ISA_PRINT_INFO_Comp(const ISA_PRINT_INFO *info, INT index)",
00136 " * Identifies a instruction component to be printed.",
00137 " *",
00138 " * 'index' specifies the component. The first component has index",
00139 " * 0; the end of the components is signalled by the return of",
00140 " * ISA_PRINT_COMP_end.",
00141 " *",
00142 " * const char *ISA_PRINT_INFO_Format(const ISA_PRINT_INFO *info)",
00143 " * The printf format string for printing the instruction",
00144 " * described by 'info'.",
00145 " *",
00146 " * const char *ISA_PRINT_AsmName(TOP topcode)",
00147 " * Returns the assembly language name for <topcode>.",
00148 " *",
00149 " * BOOL ISA_PRINT_Operand_Is_Part_Of_Name(TOP topcode, INT opindex)",
00150 " * Returns whether the operand is part of the full asm name.",
00151 " *",
00152 " * ====================================================================",
00153 " * ====================================================================",
00154 " */",
00155 NULL
00156 };
00157
00159 const char* Print_Name(int print_index)
00161 {
00162 static const char *comp_name[MAX_LISTING_OPERANDS];
00163 static bool initialized;
00164
00165 if (!initialized) {
00166 int i;
00167 for (i = 0; i < MAX_LISTING_OPERANDS; ++i) {
00168 char buf[80];
00169 if (i == END) {
00170 comp_name[i] = "ISA_PRINT_COMP_end";
00171 } else if (i == NAME) {
00172 comp_name[i] = "ISA_PRINT_COMP_name";
00173 } else if (i == OPND) {
00174 comp_name[i] = "ISA_PRINT_COMP_opnd";
00175 } else if (i > OPND && i < (OPND + MAX_OPNDS)) {
00176 sprintf(buf, "ISA_PRINT_COMP_opnd+%d", i - OPND);
00177 comp_name[i] = strdup(buf);
00178 } else if (i == RESULT) {
00179 comp_name[i] = "ISA_PRINT_COMP_result";
00180 } else {
00181 assert(i > RESULT && i < (RESULT + MAX_RESULTS));
00182 sprintf(buf, "ISA_PRINT_COMP_result+%d", i - RESULT);
00183 comp_name[i] = strdup(buf);
00184 }
00185 }
00186 initialized = true;
00187 }
00188
00189 return comp_name[print_index];
00190 }
00191
00193 void ISA_Print_Begin( const char* )
00195
00197 {
00198 }
00199
00201 ISA_PRINT_TYPE ISA_Print_Type_Create (
00202 const char* name,
00203 const char* format_string)
00205
00207 {
00208 LISTING_INFO result = new list_info;
00209 result->type = new isa_print_type;
00210 result->type->name = name;
00211 result->type->format_string = format_string;
00212 result->index = list_index;
00213 result->args = 0;
00214 result->have_name = false;
00215 current_print_desc = result;
00216 all_prints.push_back (current_print_desc);
00217 ++list_index;
00218 return result->type;
00219 }
00220
00222 void Instruction_Print_Group(ISA_PRINT_TYPE print_type, TOP top, ... )
00224
00226 {
00227 va_list ap;
00228 TOP opcode;
00229
00230 if (!current_print_desc->have_name) {
00231 fprintf(stderr, "### Warning: no instruction name specified for %s\n",
00232 current_print_desc->type->name);
00233
00234 }
00235 op_pr *op_print = new op_pr;
00236 op_prints_list.push_back(op_print);
00237 op_print->desc = current_print_desc;
00238 op_prints[(int)top] = op_print;
00239 top_specified[(int)top] = true;
00240
00241 va_start(ap, top);
00242 while ( (opcode = static_cast<TOP>(va_arg(ap,int))) != TOP_UNDEFINED ) {
00243 op_print = new op_pr;
00244 op_prints_list.push_back(op_print);
00245 op_print->desc = current_print_desc;
00246 op_prints[(int)opcode] = op_print;
00247 top_specified[(int)opcode] = true;
00248 }
00249 va_end(ap);
00250 }
00251
00253 void Name (void)
00255
00257 {
00258 if (current_print_desc->args == MAX_LISTING_OPERANDS) {
00259 fprintf(stderr, "### Error: too many listing operands for %s\n",
00260 current_print_desc->type->name);
00261 exit(EXIT_FAILURE);
00262 }
00263 current_print_desc->arg[current_print_desc->args] = NAME;
00264 current_print_desc->args++;
00265 current_print_desc->have_name = true;
00266 }
00267
00269 void Operand (int operand_index)
00271
00273 {
00274 if (operand_index >= MAX_OPNDS) {
00275 fprintf(stderr, "### Error: operand index (%d) exceeds %d\n",
00276 operand_index, MAX_OPNDS-1);
00277 exit(EXIT_FAILURE);
00278 }
00279 if (current_print_desc->args == MAX_LISTING_OPERANDS) {
00280 fprintf(stderr, "### Error: too many listing operands for %s\n",
00281 current_print_desc->type->name);
00282 exit(EXIT_FAILURE);
00283 }
00284 current_print_desc->arg[current_print_desc->args] = OPND+operand_index;
00285 current_print_desc->args++;
00286 }
00287
00289 void Result (int result_index)
00291
00293 {
00294 if (result_index >= MAX_RESULTS) {
00295 fprintf(stderr, "### Error: result index (%d) exceeds %d\n",
00296 result_index, MAX_RESULTS-1);
00297 exit(EXIT_FAILURE);
00298 }
00299 if (current_print_desc->args == MAX_LISTING_OPERANDS) {
00300 fprintf(stderr, "### Error: too many listing operands for %s\n",
00301 current_print_desc->type->name);
00302 exit(EXIT_FAILURE);
00303 }
00304 current_print_desc->arg[current_print_desc->args] = RESULT+result_index;
00305 current_print_desc->args++;
00306 }
00307
00309
00310
00311
00312
00313 extern "C" { void Set_AsmName_Func(const char *(*asmname_func)(TOP topcode))
00315
00317 {
00318 asmname = asmname_func;
00319 }
00320
00321 }
00323 void ISA_Print_End(void)
00325
00327 {
00328 list<LISTING_INFO>::iterator isi;
00329
00330 #define FNAME "targ_isa_print"
00331 char buf[1000];
00332 sprintf (buf, "%s.h", FNAME);
00333 FILE* hfile = fopen(buf, "w");
00334 sprintf (buf, "%s.c", FNAME);
00335 FILE* cfile = fopen(buf, "w");
00336 sprintf (buf, "%s.Exported", FNAME);
00337 FILE* efile = fopen(buf, "w");
00338 const char comma = ',';
00339 const char space = ' ';
00340 const char * const isa_print_type_format = "\t/* %s[%d] */";
00341 const char * const isa_print_format_format = " { %-14s ";
00342 const char * const isa_print_args_format = " %s%c";
00343 int top;
00344 bool err;
00345
00346 for (err = false, top = 0; top < TOP_count; ++top) {
00347 bool is_dummy = TOP_is_dummy((TOP)top);
00348 bool is_simulated = TOP_is_simulated((TOP)top);
00349 if (!top_specified[top]) {
00350 if (!is_simulated && !is_dummy) {
00351 fprintf(stderr, "### Error: no print specification for %s\n",
00352 TOP_Name((TOP)top));
00353 err = true;
00354 }
00355 } else if (is_dummy) {
00356 fprintf(stderr, "### Error: print specification for dummy op %s\n",
00357 TOP_Name((TOP)top));
00358 err = true;
00359 } else if (is_simulated) {
00360 fprintf(stderr, "### Error: print specification for simulated op %s\n",
00361 TOP_Name((TOP)top));
00362 err = true;
00363 }
00364 }
00365 if (err) exit(EXIT_FAILURE);
00366
00367 fprintf(cfile,"#include <string.h>\n");
00368 fprintf(cfile,"#include \"topcode.h\"\n");
00369 fprintf(cfile,"#include \"%s.h\"\n\n", FNAME);
00370
00371 sprintf (buf, "%s", FNAME);
00372 Emit_Header (hfile, buf, interface);
00373 fprintf(hfile,"#include \"topcode.h\"\n");
00374
00375 Emit_Definitions (hfile, "ISA_PRINT_");
00376
00377 fprintf(hfile, "\ntypedef enum {\n"
00378 " %-21s = %d, /* %s */\n"
00379 " %-21s = %d, /* %s */\n"
00380 " %-21s = %d, /* %s */\n"
00381 " %-21s = %d, /* %s */\n"
00382 " %-21s = %d /* %s */\n"
00383 "} ISA_PRINT_COMP;\n",
00384 Print_Name(END), END, "End of list marker",
00385 Print_Name(NAME), NAME, "Instruction name",
00386 Print_Name(OPND), OPND, "OPND+n => operand n",
00387 Print_Name(RESULT), RESULT, "RESULT+n => result n",
00388 "ISA_PRINT_COMP_MAX", MAX_LISTING_OPERANDS-1, "Last component");
00389
00390 fprintf(hfile, "\ntypedef struct {\n"
00391 " const char *format;\n"
00392 " mUINT8 comp[%d];\n"
00393 "} ISA_PRINT_INFO;\n",MAX_LISTING_OPERANDS);
00394
00395 fprintf(hfile, "\nextern const ISA_PRINT_INFO ISA_PRINT_info[%d];\n",
00396 list_index + 1);
00397
00398 fprintf(efile, "ISA_PRINT_info\n");
00399
00400 fprintf(cfile, "\nconst ISA_PRINT_INFO ISA_PRINT_info[%d] = {\n",
00401 list_index + 1);
00402
00403 fprintf (cfile, isa_print_format_format, "\"\",");
00404 fprintf (cfile, isa_print_args_format, Print_Name(END), space);
00405 fprintf (cfile, "},");
00406 fprintf (cfile, isa_print_type_format, "print_NULL", 0);
00407 fprintf (cfile, "\n");
00408 for ( isi = all_prints.begin(); isi != all_prints.end(); ++isi ) {
00409 LISTING_INFO curr_type = *isi;
00410 sprintf (buf, "\"%s\",", curr_type->type->format_string);
00411 fprintf (cfile, isa_print_format_format, buf);
00412 for (int i = 0; i < curr_type->args; i++) {
00413 fprintf (cfile, isa_print_args_format,
00414 Print_Name(curr_type->arg[i]),
00415 comma);
00416 fprintf (cfile, isa_print_type_format, curr_type->type->name, i);
00417 fprintf (cfile, "\n%19s", "");
00418 }
00419 fprintf (cfile, isa_print_args_format, Print_Name(END), space);
00420 fprintf (cfile, "},");
00421 fprintf (cfile, isa_print_type_format,
00422 curr_type->type->name,
00423 curr_type->args);
00424 fprintf (cfile, "\n");
00425 }
00426 fprintf (cfile, "};\n");
00427
00428 fprintf(hfile, "\nextern const unsigned char ISA_PRINT_info_index[%d];\n", TOP_count);
00429
00430 fprintf(efile, "ISA_PRINT_info_index\n");
00431
00432 fprintf(cfile, "\nconst mUINT8 ISA_PRINT_info_index[%d] = {\n", TOP_count);
00433 for (top = 0; top < TOP_count; ++top ) {
00434 op_pr *op_print = op_prints[top];
00435 if (op_print) {
00436 fprintf(cfile, " %3d, /* %s: %s */\n",
00437 op_print->desc->index+1,
00438 TOP_Name((TOP)top),
00439 op_print->desc->type->name);
00440 } else {
00441 fprintf(cfile, " %3d, /* %s */\n",
00442 0,
00443 TOP_Name((TOP)top));
00444 }
00445 }
00446 fprintf(cfile, "};\n");
00447
00448 fprintf(hfile, "\ninline const ISA_PRINT_INFO *ISA_PRINT_Info(TOP topcode)\n"
00449 "{\n"
00450 " INT index = ISA_PRINT_info_index[(INT)topcode];\n"
00451 " return index == 0 ? 0 : &ISA_PRINT_info[index];\n"
00452 "}\n");
00453
00454 fprintf(hfile, "\ninline const char* ISA_PRINT_INFO_Format(const ISA_PRINT_INFO *info)\n"
00455 "{\n"
00456 " return info->format;\n"
00457 "}\n");
00458
00459 fprintf(hfile, "\ninline INT ISA_PRINT_INFO_Comp(const ISA_PRINT_INFO *info, INT index)\n"
00460 "{\n"
00461 " return info->comp[index];\n"
00462 "}\n");
00463
00464 if (asmname) {
00465 fprintf(cfile, "\nconst char * const ISA_PRINT_asmname[] = {\n");
00466 for (top = 0; top < TOP_count; ++top) {
00467 fprintf(cfile, " \"%s\",\n", asmname((TOP)top));
00468 }
00469 fprintf(cfile, " \"UNDEFINED\"\n"
00470 "};\n");
00471
00472 fprintf(hfile, "\ninline const char *ISA_PRINT_AsmName(TOP topcode)\n"
00473 "{\n"
00474 " extern const char * const ISA_PRINT_asmname[];\n"
00475 " return ISA_PRINT_asmname[(INT)topcode];\n"
00476 "}\n");
00477
00478 fprintf(efile, "ISA_PRINT_asmname\n");
00479 } else {
00480 fprintf(hfile, "\ninline const char *ISA_PRINT_AsmName(TOP topcode)\n"
00481 "{\n"
00482 " return TOP_Name(topcode);\n"
00483 "}\n");
00484 }
00485
00486 fprintf(hfile, "\nextern BOOL ISA_PRINT_Operand_Is_Part_Of_Name(TOP topcode, INT opindex);\n");
00487 fprintf(efile, "ISA_PRINT_Operand_Is_Part_Of_Name\n");
00488 fprintf(cfile, "\nBOOL ISA_PRINT_Operand_Is_Part_Of_Name(TOP topcode, INT opindex)\n"
00489 "{\n"
00490 " const ISA_PRINT_INFO *info = ISA_PRINT_Info(topcode);\n"
00491 " const char *place_in_format = ISA_PRINT_INFO_Format(info);\n"
00492 " BOOL in_name_part = 0;\n"
00493 " INT comp;\n"
00494 " INT i = 0;\n"
00495 " for (;;) {\n"
00496 " comp = ISA_PRINT_INFO_Comp(info,i);\n"
00497 " if (comp == ISA_PRINT_COMP_end) break;\n"
00498 " place_in_format = strchr(place_in_format, '%%');\n"
00499 " place_in_format += 2; /* assume %%s */\n"
00500 " if (comp == ISA_PRINT_COMP_name) {\n"
00501 " if (*place_in_format == '\\0' || *place_in_format == ' ')\n"
00502 " in_name_part = 0;\n"
00503 " else\n"
00504 " in_name_part = 1;\n"
00505 " }\n"
00506 " if (comp >= ISA_PRINT_COMP_opnd && comp < ISA_PRINT_COMP_result) {\n"
00507 " if (in_name_part) {\n"
00508 " INT comp_opindex = comp - ISA_PRINT_COMP_opnd;\n"
00509 " if (comp_opindex == opindex)\n"
00510 " return 1;\n"
00511 " if (*place_in_format == '\\0' || *place_in_format == ' ')\n"
00512 " in_name_part = 0;\n"
00513 " }\n"
00514 " }\n"
00515 " ++i;\n"
00516 " }\n"
00517 " return 0;\n"
00518 "}\n");
00519
00520 Emit_Footer (hfile);
00521 }