GCC后端及汇编发布(39)

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

10.   genopinit工具

10.1.  概览

这个工具将从机器描述文件输出insn-opinit.c。这个文件提供函数init_all_optabs来把内建函数与枚举insn_code绑定一起。而通过这个值,能显示该指令是否被支持。

10.2.  程序入口

332  int

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  }

 

对应define_insn或define_expand模式的每个rtx对象将由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   }

 

数据optabs 具有如下的定义。

 

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     …

 

以62行的内容为例子,在gen_insn的185行将扫描这个字符串直到遇到“$(”。然后188行的FOR循环将检测子字符串“extend$a$b2$”。接着在193行,检查define_insn或define_expand的名字是否匹配“extend”。对于i386系统,为了匹配这些子字符串,我们以以下的define_insn模式作为例子。

 

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 })

 

在匹配之后,我们遇到子字符串“$a$b2$”。

在这个字符串中,“$a”及“$b”被用于匹配一个短的模式(mode)名(模式名部分不包括“mode”并转换到小写)。当输出这个初始值时,使用整个字符串。“$A”及“$B”为该模式的完整名字所替代;“$a”及“$b”则如上所示,为这个模式名字的短短形式所替代。 如果在这个模式(pattern)中出现了“$N”,这意味着这两个模式(mode)必须是同一个模式(mode)类别中,具有相邻长度的(比如,Qimode与Himode)。“$I”则表示下一个模式(mode)仅考虑完整的整数模式(mode),而“$F”则表示仅考虑浮点模式(mode)。“$P”表示完整的及部分的整数模式(mode)都应该考虑。“$V”表示如果第一个模式(mode)是MODE_FLOAT模式,输出‘'v’。

 

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  }

 

注意在284行,宏HAVE_`insn-name`在genflags工具一节中输出,该宏的细节参考着一节。仅当这些宏等于1时,才把指令编号赋给相应的optab

然后在289行的FOR循环为这个optab输出初始编号。等于我们的例子,sext_optab被定义为convert_optab_table[CTI_sext],其定义为convert_optab。照这个结构体定义模式(mode)间某种转换操作。

等于我们的例子,我们将得到如下代码片段。

 

  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;

 

上面handlers的定义是optab_handler,域insn_codeenum insn_code,它显示在一个特定机器模式(mode)上,如何为这个操作生成一条指令。如果在目标机器上没有这样的指令,它是CODE_FOR_nothingenum insn_code由gencodes(gencodes工具)产生。

 


原创粉丝点击