GCC's bacl-end & assemble emission (39)

来源:互联网 发布:c语言bzero 编辑:程序博客网 时间:2024/04/30 10:07

10.   Toolof genopinit

10.1.  Overview

This tool will output insn-opinit.c from machine description file. The file provides functioninit_all_optabs whichbinds builtin functions with enum insn_code. And by this value, it indicateswhether the instruction is supported or not.

10.2.  Program Entry

333  main (int argc, char **argv)                                                                        ingenopinit.c

334  {

335   rtx desc;

336 

337   progname= "genopinit";

338 

339   if (argc <= 1)

340     fatal ("no input file name");

341 

342   if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)

343     return (FATAL_EXIT_CODE);

344 

345   printf ("/* Generated automatically by the program `genopinit'\n\

346         from the machine description file `md'. */\n\n");

347 

348    printf ("#include\"config.h\"\n");

349    printf("#include \"system.h\"\n");

350   printf ("#include \"coretypes.h\"\n");

351   printf ("#include \"tm.h\"\n");

352   printf ("#include \"rtl.h\"\n");

353   printf ("#include \"flags.h\"\n");

354   printf ("#include \"insn-config.h\"\n");

355   printf ("#include \"recog.h\"\n");

356   printf ("#include \"expr.h\"\n");

357    printf ("#include\"optabs.h\"\n");

358    printf ("#include\"reload.h\"\n\n");

359 

360    printf("void\ninit_all_optabs (void)\n{\n");

361 

362   puts ("\

363  #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC\n\

364    int i, j;\n\

365  #endif\n");

366 

367   /* Read the machine description.  */

368 

369   while (1)

370   {

371     int line_no, insn_code_number = 0;

372 

373     desc = read_md_rtx (&line_no,&insn_code_number);

374     if (desc == NULL)

375       break;

376 

377      if (GET_CODE (desc) ==DEFINE_INSN || GET_CODE (desc) == DEFINE_EXPAND)

378       gen_insn (desc);

379   }

380 

381   puts ("\

382  \n\

383  #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC\n\

384   /* This flag says the same insns that convertto a signed fixnum\n\

385      also convert validly to an unsigned one. */\n\

386    for (i = 0; i <NUM_MACHINE_MODES; i++)\n\

387      for (j = 0; j <NUM_MACHINE_MODES; j++)\n\

388        ufixtrunc_optab->handlers[i][j].insn_code\n\

389        =sfixtrunc_optab->handlers[i][j].insn_code;\n\

390  #endif\n\

391  }");

392 

393   fflush (stdout);

394   return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);

395  }

 

Every rtx object of define_insn or define_expand pattern will behandled by gen_insn.

 

162  static void

163  gen_insn (rtx insn)                                                                                     ingenopinit.c

164  {

165   const char *name = XSTR (insn, 0);

166   int m1 = 0, m2 = 0, op = 0;

167   size_t pindex;

168   int i;

169   const char *np, *pp, *p, *q;

170 

171   /* Don't mention instructions whose names arethe null string.

172      They are in the machine description just tobe recognized.  */

173   if (*name == 0)

174     return;

175 

176   /* See if NAME matches one of the patterns wehave for the optabs we know

177      about. */

178 

179   for (pindex = 0; pindex < ARRAY_SIZE(optabs);pindex++)

180   {

181     int force_float = 0, force_int = 0, force_partial_int = 0;

182     int force_consec = 0;

183     int matches = 1;

184 

185     for (pp = optabs[pindex]; pp[0] != '$' ||pp[1] != '('; pp++)

186       ;

187 

188     for (pp += 2, np = name; matches&& ! (pp[0] == '$' && pp[1] == ')');

189         pp++)

190     {

191       if (*pp != '$')

192       {

193         if (*pp != *np++)

194            break;

195       }

196       else

197         switch (*++pp)

198         {

199            case'N':

200              force_consec = 1;

201              break;

202            case'I':

203              force_int = 1;

204              break;

205            case'P':

206              force_partial_int = 1;

207              break;

208            case'F':

209              force_float = 1;

210              break;

211            case'V':

212              break;

213            case'c':

214              for(op = 0; op < NUM_RTX_CODE; op++)

215              {

216                for(p = GET_RTX_NAME(op), q = np; *p; p++, q++)

217                  if (*p != *q)

218                    break;

219 

220                /* Wehave to be concerned about matching "gt" and

221                   missing "gtu", e.g.,so verify we have reached the

222                   end of thing we are tomatch.  */

223                 if (*p == 0 && *q == 0&& GET_RTX_CLASS(op) == '<')

224                   break;

225              }

226 

227              if (op == NUM_RTX_CODE)

228                matches = 0;

229              else

230                np += strlen (GET_RTX_NAME(op));

231              break;

232            case'a':

233           case'b':

234              /* Thisloop will stop at the first prefix match, so

235                look through the modes in reverseorder, in case

236                there are extra CC modes and CCis a prefix of the

237                CC modes (as it should be).  */

238              for(i = (MAX_MACHINE_MODE) - 1; i >= 0; i--)

239              {

240                for(p = GET_MODE_NAME(i), q = np; *p; p++, q++)

241                  if (TOLOWER (*p) != *q)

242                    break;

243 

244                if (*p == 0

245                   && (! force_int ||mode_class[i] == MODE_INT

246                       || mode_class[i] ==MODE_VECTOR_INT)

247                   && (!force_partial_int

248                       || mode_class[i] ==MODE_INT

249                       || mode_class[i] == MODE_PARTIAL_INT

250                       || mode_class[i] ==MODE_VECTOR_INT)

251                   && (! force_float ||mode_class[i] == MODE_FLOAT

252                       || mode_class[i] ==MODE_VECTOR_FLOAT))

253                 break;

254              }

255 

256              if (i < 0)

257                matches = 0;

258              else if (*pp == 'a')

259                m1 = i, np += strlen (GET_MODE_NAME(i));

260              else

261                m2 = i, np += strlen (GET_MODE_NAME(i));

262 

263              force_int = force_partial_int =force_float = 0;

264              break;

265 

266            default:

267              abort ();

268         }

269     }

270 

271     if (matches && pp[0] == '$' && pp[1] == ')'

272        && *np == 0

273        && (! force_consec || (int) GET_MODE_WIDER_MODE(m1) == m2))

274       break;

275   }

 

Data optabshas following definition.

 

61    static const char * const optabs[] =                                                                      ingenopinit.c

62    {"sext_optab->handlers[$B][$A].insn_code =CODE_FOR_$(extend$a$b2$)",

63     "zext_optab->handlers[$B][$A].insn_code =CODE_FOR_$(zero_extend$a$b2$)",

64     "sfix_optab->handlers[$B][$A].insn_code =CODE_FOR_$(fix$F$a$I$b2$)",

65     "ufix_optab->handlers[$B][$A].insn_code =CODE_FOR_$(fixuns$F$a$b2$)",

66     "sfixtrunc_optab->handlers[$B][$A].insn_code =CODE_FOR_$(fix_trunc$F$a$I$b2$)",

67     "ufixtrunc_optab->handlers[$B][$A].insn_code =CODE_FOR_$(fixuns_trunc$F$a$I$b2$)",

68     …

 

Take content at line 62 above as example, in gen_insn, line 185 will scan thestring till arrive “$(“. ThenFORloop at line 188 will examine sub-string “extend$a$b2$”. Next at line 193, seeif the name of define_insn or define_expand matches “extend” or not. For i386system, to match these sub-strings, we take following define_insn pattern asexample.

 

3227 (define_expand"extendsidi2"                                                                             ini386.c

3228   [(parallel [(set (match_operand:DI 0"register_operand" "")

3229                 (sign_extend:DI (match_operand:SI 1 "register_operand" "")))

3230             (clobber (reg:CC 17))

3231             (clobber (match_scratch:SI 2 ""))])]

3232   ""

3233 {

3234   if (TARGET_64BIT)

3235     {

3236       emit_insn (gen_extendsidi2_rex64(operands[0], operands[1]));

3237       DONE;

3238     }

3239 })

 

After matching, we come to following sub-string “$a$b2$”.

In the string, “$a” and “$b” are used to match a short mode name(the part of the mode name not including “mode” and converted to lower-case).When writing out the initializer, the entire string is used. “$A” and “$B” arereplaced with the full name of the mode; “$a” and “$b” are replaced with theshort form of the name, as above. If “$N” is present in the pattern, it meansthe two modes must be consecutive widths in the same mode class (e.g, QImodeand HImode). “$I” means that only full integer modes should be considered forthe next mode, and “$F” means that only float modes should be considered. “$P”means that both full and partial integer modes should be considered. “$V” meansto emit 'v' if the first mode is MODE_FLOAT mode.

 

gen_insn (continued)

 

277   if (pindex == ARRAY_SIZE (optabs))

278     return;

279 

280   /* We found a match. If this pattern is onlyconditionally present,

281      write out the "if" and two extrablanks.  */

282 

283   if (*XSTR (insn, 2) != 0)

284     printf ("  if(HAVE_%s)\n  ", name);

285 

286   printf ("  ");

287 

288   /* Now write out the initialization, makingall required substitutions.  */

289   for (pp = optabs[pindex]; *pp; pp++)

290   {

291     if (*pp != '$')

292       putchar (*pp);

293     else

294       switch (*++pp)

295       {

296         case '(':  case ')':

297         case 'I':  case'F':  case'N':

298            break;

299         case 'V':

300            if (GET_MODE_CLASS (m1) ==MODE_FLOAT)

301             printf ("v");

302            break;

303         case 'a':

304            for(np = GET_MODE_NAME(m1); *np; np++)

305              putchar (TOLOWER (*np));

306            break;

307         case 'b':

308            for(np = GET_MODE_NAME(m2); *np; np++)

309              putchar (TOLOWER (*np));

310            break;

311         case 'A':

312            printf ("%smode",GET_MODE_NAME(m1));

313            break;

314         case 'B':

315            printf ("%smode",GET_MODE_NAME(m2));

316            break;

317         case'c':

318            printf ("%s",GET_RTX_NAME(op));

319            break;

320         case 'C':

321            for(np = GET_RTX_NAME(op); *np; np++)

322              putchar (TOUPPER (*np));

323            break;

324       }

325   }

326 

327   printf (";\n");

328  }

 

Notice that at line 284, the macro HAVE_`insn-name` is output in 12. Tool of genflags, refer to this section fordetail of the macros. Only when the macros equate to 1, it will asign the insnnumber to correspondingoptab.

Then FOR loop at line 289outputs the initialization code for the optab. For our example,sext_optabis defined as convert_optab_table[CTI_sext],which has definitionconvert_optab. The structuredefines some sort of conversion operation between modes.

For our example, we will get following code fragment.

 

  sext_optab->handlers[SImode][HImode].insn_code = CODE_FOR_extendhisi2;

  sext_optab->handlers[HImode][QImode].insn_code= CODE_FOR_extendqihi2;

 sext_optab->handlers[SImode][QImode].insn_code =CODE_FOR_extendqisi2;

 

Above handlershas definition of optab_handler, theinsn_codeslot is the enuminsn_code that says how to generate an instruction for this operationon a particular machine mode. It isCODE_FOR_nothing if there is no such instructionon the target machine. Theenum insn_code is output by gencodes (13. Tool of gencodes).

 


原创粉丝点击