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