00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "hconfig.h"
00024 #include "system.h"
00025 #include "rtl.h"
00026 #include "errors.h"
00027 #include "insn-config.h"
00028 #include "gensupport.h"
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 struct extraction
00042 {
00043 int op_count;
00044 char *oplocs[MAX_RECOG_OPERANDS];
00045 int dup_count;
00046 char *duplocs[MAX_DUP_OPERANDS];
00047 int dupnums[MAX_DUP_OPERANDS];
00048 struct code_ptr *insns;
00049 struct extraction *next;
00050 };
00051
00052
00053
00054 struct code_ptr
00055 {
00056 int insn_code;
00057 struct code_ptr *next;
00058 };
00059
00060 static struct extraction *extractions;
00061
00062
00063 static char **insn_name_ptr = 0;
00064 static int insn_name_ptr_size = 0;
00065
00066
00067
00068 static int insn_code_number;
00069
00070
00071
00072 static int op_count;
00073
00074
00075
00076
00077 static char *oplocs[MAX_RECOG_OPERANDS];
00078
00079
00080
00081
00082 static int dup_count;
00083
00084
00085
00086 static char *duplocs[MAX_DUP_OPERANDS];
00087
00088
00089
00090 static int dupnums[MAX_DUP_OPERANDS];
00091
00092
00093
00094 static struct code_ptr *peepholes;
00095
00096 static void gen_insn PARAMS ((rtx));
00097 static void walk_rtx PARAMS ((rtx, const char *));
00098 static void print_path PARAMS ((const char *));
00099 static void record_insn_name PARAMS ((int, const char *));
00100
00101 static void
00102 gen_insn (insn)
00103 rtx insn;
00104 {
00105 int i;
00106 struct extraction *p;
00107 struct code_ptr *link;
00108
00109 op_count = 0;
00110 dup_count = 0;
00111
00112
00113 memset (oplocs, 0, sizeof oplocs);
00114
00115
00116
00117
00118 if (XVECLEN (insn, 1) == 1)
00119 walk_rtx (XVECEXP (insn, 1, 0), "");
00120 else
00121 for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
00122 {
00123 char path[2];
00124
00125 path[0] = 'a' + i;
00126 path[1] = 0;
00127
00128 walk_rtx (XVECEXP (insn, 1, i), path);
00129 }
00130
00131 link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
00132 link->insn_code = insn_code_number;
00133
00134
00135
00136 for (p = extractions; p; p = p->next)
00137 {
00138 if (p->op_count != op_count || p->dup_count != dup_count)
00139 continue;
00140
00141 for (i = 0; i < op_count; i++)
00142 if (p->oplocs[i] != oplocs[i]
00143 && ! (p->oplocs[i] != 0 && oplocs[i] != 0
00144 && ! strcmp (p->oplocs[i], oplocs[i])))
00145 break;
00146
00147 if (i != op_count)
00148 continue;
00149
00150 for (i = 0; i < dup_count; i++)
00151 if (p->dupnums[i] != dupnums[i]
00152 || strcmp (p->duplocs[i], duplocs[i]))
00153 break;
00154
00155 if (i != dup_count)
00156 continue;
00157
00158
00159 link->next = p->insns;
00160 p->insns = link;
00161 return;
00162 }
00163
00164
00165
00166 p = (struct extraction *) xmalloc (sizeof (struct extraction));
00167 p->op_count = op_count;
00168 p->dup_count = dup_count;
00169 p->next = extractions;
00170 extractions = p;
00171 p->insns = link;
00172 link->next = 0;
00173
00174 for (i = 0; i < op_count; i++)
00175 p->oplocs[i] = oplocs[i];
00176
00177 for (i = 0; i < dup_count; i++)
00178 p->dupnums[i] = dupnums[i], p->duplocs[i] = duplocs[i];
00179 }
00180
00181 static void
00182 walk_rtx (x, path)
00183 rtx x;
00184 const char *path;
00185 {
00186 RTX_CODE code;
00187 int i;
00188 int len;
00189 const char *fmt;
00190 int depth = strlen (path);
00191 char *newpath;
00192
00193 if (x == 0)
00194 return;
00195
00196 code = GET_CODE (x);
00197
00198 switch (code)
00199 {
00200 case PC:
00201 case CC0:
00202 case CONST_INT:
00203 case SYMBOL_REF:
00204 return;
00205
00206 case MATCH_OPERAND:
00207 case MATCH_SCRATCH:
00208 oplocs[XINT (x, 0)] = xstrdup (path);
00209 op_count = MAX (op_count, XINT (x, 0) + 1);
00210 break;
00211
00212 case MATCH_DUP:
00213 duplocs[dup_count] = xstrdup (path);
00214 dupnums[dup_count] = XINT (x, 0);
00215 dup_count++;
00216 break;
00217
00218 case MATCH_PAR_DUP:
00219 case MATCH_OP_DUP:
00220 duplocs[dup_count] = xstrdup (path);
00221 dupnums[dup_count] = XINT (x, 0);
00222 dup_count++;
00223
00224 newpath = (char *) xmalloc (depth + 2);
00225 strcpy (newpath, path);
00226 newpath[depth + 1] = 0;
00227
00228 for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
00229 {
00230 newpath[depth] = (code == MATCH_OP_DUP ? '0' : 'a') + i;
00231 walk_rtx (XVECEXP (x, 1, i), newpath);
00232 }
00233 free (newpath);
00234 return;
00235
00236 case MATCH_OPERATOR:
00237 oplocs[XINT (x, 0)] = xstrdup (path);
00238 op_count = MAX (op_count, XINT (x, 0) + 1);
00239
00240 newpath = (char *) xmalloc (depth + 2);
00241 strcpy (newpath, path);
00242 newpath[depth + 1] = 0;
00243
00244 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
00245 {
00246 newpath[depth] = '0' + i;
00247 walk_rtx (XVECEXP (x, 2, i), newpath);
00248 }
00249 free (newpath);
00250 return;
00251
00252 case MATCH_PARALLEL:
00253 oplocs[XINT (x, 0)] = xstrdup (path);
00254 op_count = MAX (op_count, XINT (x, 0) + 1);
00255
00256 newpath = (char *) xmalloc (depth + 2);
00257 strcpy (newpath, path);
00258 newpath[depth + 1] = 0;
00259
00260 for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
00261 {
00262 newpath[depth] = 'a' + i;
00263 walk_rtx (XVECEXP (x, 2, i), newpath);
00264 }
00265 free (newpath);
00266 return;
00267
00268 case ADDRESS:
00269 walk_rtx (XEXP (x, 0), path);
00270 return;
00271
00272 default:
00273 break;
00274 }
00275
00276 newpath = (char *) xmalloc (depth + 2);
00277 strcpy (newpath, path);
00278 newpath[depth + 1] = 0;
00279
00280 fmt = GET_RTX_FORMAT (code);
00281 len = GET_RTX_LENGTH (code);
00282 for (i = 0; i < len; i++)
00283 {
00284 if (fmt[i] == 'e' || fmt[i] == 'u')
00285 {
00286 newpath[depth] = '0' + i;
00287 walk_rtx (XEXP (x, i), newpath);
00288 }
00289 else if (fmt[i] == 'E')
00290 {
00291 int j;
00292 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
00293 {
00294 newpath[depth] = 'a' + j;
00295 walk_rtx (XVECEXP (x, i, j), newpath);
00296 }
00297 }
00298 }
00299 free (newpath);
00300 }
00301
00302
00303
00304
00305
00306 static void
00307 print_path (path)
00308 const char *path;
00309 {
00310 int len = strlen (path);
00311 int i;
00312
00313 if (len == 0)
00314 {
00315
00316
00317 printf("PATTERN (insn)");
00318 return;
00319 }
00320
00321
00322
00323
00324 for (i = len - 1; i >=0 ; i--)
00325 {
00326 if (ISLOWER(path[i]))
00327 printf ("XVECEXP (");
00328 else if (ISDIGIT(path[i]))
00329 printf ("XEXP (");
00330 else
00331 abort ();
00332 }
00333
00334 printf ("pat");
00335
00336 for (i = 0; i < len; i++)
00337 {
00338 if (ISLOWER(path[i]))
00339 printf (", 0, %d)", path[i] - 'a');
00340 else if (ISDIGIT(path[i]))
00341 printf (", %d)", path[i] - '0');
00342 else
00343 abort ();
00344 }
00345 }
00346
00347 extern int main PARAMS ((int, char **));
00348
00349 int
00350 main (argc, argv)
00351 int argc;
00352 char **argv;
00353 {
00354 rtx desc;
00355 int i;
00356 struct extraction *p;
00357 struct code_ptr *link;
00358 const char *name;
00359
00360 progname = "genextract";
00361
00362 if (argc <= 1)
00363 fatal ("no input file name");
00364
00365 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
00366 return (FATAL_EXIT_CODE);
00367
00368
00369
00370
00371 insn_code_number = 0;
00372
00373 printf ("/* Generated automatically by the program `genextract'\n\
00374 from the machine description file `md'. */\n\n");
00375
00376 printf ("#include \"config.h\"\n");
00377 printf ("#include \"system.h\"\n");
00378 printf ("#include \"rtl.h\"\n");
00379 printf ("#include \"insn-config.h\"\n");
00380 printf ("#include \"recog.h\"\n");
00381 printf ("#include \"toplev.h\"\n\n");
00382
00383
00384
00385 printf ("static rtx junk ATTRIBUTE_UNUSED;\n");
00386
00387 printf ("void\ninsn_extract (insn)\n");
00388 printf (" rtx insn;\n");
00389 printf ("{\n");
00390 printf (" rtx *ro = recog_data.operand;\n");
00391 printf (" rtx **ro_loc = recog_data.operand_loc;\n");
00392 printf (" rtx pat = PATTERN (insn);\n");
00393 printf (" int i ATTRIBUTE_UNUSED;\n\n");
00394 printf (" memset (ro, 0, sizeof (*ro) * MAX_RECOG_OPERANDS);\n");
00395 printf (" memset (ro_loc, 0, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n");
00396 printf (" switch (INSN_CODE (insn))\n");
00397 printf (" {\n");
00398 printf (" case -1:\n");
00399 printf (" fatal_insn_not_found (insn);\n\n");
00400
00401
00402
00403 while (1)
00404 {
00405 int line_no;
00406
00407 desc = read_md_rtx (&line_no, &insn_code_number);
00408 if (desc == NULL)
00409 break;
00410
00411 if (GET_CODE (desc) == DEFINE_INSN)
00412 {
00413 record_insn_name (insn_code_number, XSTR (desc, 0));
00414 gen_insn (desc);
00415 }
00416
00417 else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
00418 {
00419 struct code_ptr *link
00420 = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
00421
00422 link->insn_code = insn_code_number;
00423 link->next = peepholes;
00424 peepholes = link;
00425 }
00426 }
00427
00428
00429
00430 if (peepholes)
00431 {
00432 for (link = peepholes; link; link = link->next)
00433 printf (" case %d:\n", link->insn_code);
00434
00435
00436
00437
00438
00439
00440 printf (" for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)\n");
00441 printf (" ro[i] = *(ro_loc[i] = &XVECEXP (pat, 0, i));\n");
00442 printf (" break;\n\n");
00443 }
00444
00445
00446 for (p = extractions; p; p = p->next)
00447 {
00448 for (link = p->insns; link; link = link->next)
00449 {
00450 i = link->insn_code;
00451 name = get_insn_name (i);
00452 if (name)
00453 printf (" case %d: /* %s */\n", i, name);
00454 else
00455 printf (" case %d:\n", i);
00456 }
00457
00458 for (i = 0; i < p->op_count; i++)
00459 {
00460 if (p->oplocs[i] == 0)
00461 {
00462 printf (" ro[%d] = const0_rtx;\n", i);
00463 printf (" ro_loc[%d] = &junk;\n", i);
00464 }
00465 else
00466 {
00467 printf (" ro[%d] = *(ro_loc[%d] = &", i, i);
00468 print_path (p->oplocs[i]);
00469 printf (");\n");
00470 }
00471 }
00472
00473 for (i = 0; i < p->dup_count; i++)
00474 {
00475 printf (" recog_data.dup_loc[%d] = &", i);
00476 print_path (p->duplocs[i]);
00477 printf (";\n");
00478 printf (" recog_data.dup_num[%d] = %d;\n", i, p->dupnums[i]);
00479 }
00480
00481 printf (" break;\n\n");
00482 }
00483
00484
00485
00486
00487 printf (" default:\n abort ();\n");
00488
00489 printf (" }\n}\n");
00490
00491 fflush (stdout);
00492 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
00493 }
00494
00495
00496 const char *
00497 get_insn_name (code)
00498 int code ATTRIBUTE_UNUSED;
00499 {
00500 if (code < insn_name_ptr_size)
00501 return insn_name_ptr[code];
00502 else
00503 return NULL;
00504 }
00505
00506 static void
00507 record_insn_name (code, name)
00508 int code;
00509 const char *name;
00510 {
00511 static const char *last_real_name = "insn";
00512 static int last_real_code = 0;
00513 char *new;
00514
00515 if (insn_name_ptr_size <= code)
00516 {
00517 int new_size;
00518 new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
00519 insn_name_ptr =
00520 (char **) xrealloc (insn_name_ptr, sizeof(char *) * new_size);
00521 memset (insn_name_ptr + insn_name_ptr_size, 0,
00522 sizeof(char *) * (new_size - insn_name_ptr_size));
00523 insn_name_ptr_size = new_size;
00524 }
00525
00526 if (!name || name[0] == '\0')
00527 {
00528 new = xmalloc (strlen (last_real_name) + 10);
00529 sprintf (new, "%s+%d", last_real_name, code - last_real_code);
00530 }
00531 else
00532 {
00533 last_real_name = new = xstrdup (name);
00534 last_real_code = code;
00535 }
00536
00537 insn_name_ptr[code] = new;
00538 }