PEEP386.C
上传用户:hlzzc88
上传日期:2007-01-06
资源大小:220k
文件大小:10k
源码类别:

编译器/解释器

开发平台:

Others

  1. /*
  2.  * 68K/386 32-bit C compiler.
  3.  *
  4.  * copyright (c) 1997, David Lindauer
  5.  * 
  6.  * This compiler is intended for educational use.  It may not be used
  7.  * for profit without the express written consent of the author.
  8.  *
  9.  * It may be freely redistributed, as long as this notice remains intact
  10.  * and either the original sources or derived sources 
  11.  * are distributed along with any executables derived from the originals.
  12.  *
  13.  * The author is not responsible for any damages that may arise from use
  14.  * of this software, either idirect or consequential.
  15.  *
  16.  * v1.35 March 1997
  17.  * David Lindauer, gclind01@starbase.spd.louisville.edu
  18.  *
  19.  * Credits to Mathew Brandt for original K&R C compiler
  20.  *
  21.  */
  22. #include        <stdio.h>
  23. #include        "expr.h"
  24. #include        "c.h"
  25. #include        "gen386.h"
  26. extern SYM *currentfunc;
  27. extern int funcfloat;
  28. extern int nextlabel;
  29. OCODE    *peep_head = 0,
  30.                 *peep_tail = 0,
  31. *peep_insert;
  32. void peepini(void)
  33. {
  34. peep_head = peep_tail = 0;
  35. }
  36. AMODE    *copy_addr(AMODE *ap)
  37. /*
  38.  *      copy an address mode structure (these things dont last).
  39.  */
  40. {       AMODE    *newap;
  41.         if( ap == 0 )
  42.                 return 0;
  43.         newap = xalloc(sizeof(AMODE));
  44.         newap->mode = ap->mode;
  45.         newap->preg = ap->preg;
  46.         newap->sreg = ap->sreg;
  47.         newap->tempflag = ap->tempflag;
  48.         newap->offset = ap->offset;
  49. newap->scale = ap->scale;
  50.         return newap;
  51. }
  52. void gen_code(int op,int len,AMODE *ap1,AMODE *ap2)
  53. /*
  54.  *      generate a code sequence into the peep list.
  55.  */
  56. {       OCODE    *new;
  57.         new = xalloc(sizeof(OCODE));
  58.         new->opcode = op;
  59.         new->oper1 = copy_addr(ap1);
  60.         new->oper2 = copy_addr(ap2);
  61. if (len < 0)
  62.          len = -len;
  63. if (new->oper1)
  64. new->oper1->length = len;
  65. if (new->oper2)
  66.   new->oper2->length = len;
  67.         add_peep(new);
  68. }
  69. void gen_codelab(SYM *lab)
  70. /*
  71.  *      generate a code sequence into the peep list.
  72.  */
  73. {       OCODE    *new;
  74.         new = xalloc(sizeof(OCODE));
  75.         new->opcode = op_funclabel;
  76.         new->oper1 = lab;
  77.         new->oper2 = 0;
  78.         add_peep(new);
  79. }
  80. void gen_branch(int op,int len, AMODE *ap1)
  81. {
  82. /*#ifndef NASM
  83. */ gen_code(op,len,ap1,0);
  84. /*#else
  85. */
  86. #ifdef HIII
  87.   int label = nextlabel++;
  88.   int op1;
  89.   AMODE *ap = make_label(label);
  90.   switch(op) {
  91. case op_jne:
  92. op1 = op_je;
  93. break;
  94. case op_je:
  95. op1 = op_jne;
  96. break;
  97. case op_jge:
  98. op1 = op_jl;
  99. break;
  100. case op_jl:
  101. op1 = op_jge;
  102. break;
  103. case op_jle:
  104. op1 = op_jg;
  105. break;
  106. case op_jg:
  107. op1 = op_jle;
  108. break;
  109. case op_jnc:
  110. op1 = op_jb;
  111. break;
  112. case op_jb:
  113. op1 = op_jnc;
  114. break;
  115. case op_ja:
  116. op1 = op_jbe;
  117. break;
  118. case op_jbe:
  119. op1 = op_ja;
  120. break;
  121. }
  122.   gen_code(op1,len,ap,0);
  123. gen_code(op_jmp,len,ap1,0);
  124.   gen_label(label);
  125. #endif
  126. }
  127. void gen_line(SNODE *stmt)
  128. {
  129. OCODE *new = xalloc(sizeof(OCODE));
  130. new->opcode = op_line;
  131. new->oper2 = (AMODE *)((int)stmt->exp);
  132. new->oper1 = (AMODE *)stmt->label;
  133. add_peep(new);
  134. }
  135. void gen_codef(int op, int len, AMODE *ap1, AMODE *ap2)
  136. {
  137.   
  138.   if (ap1 && ap2 && ap1->mode == am_freg && ap2->mode == am_freg)
  139. len=10;
  140. funcfloat++;
  141. gen_code(op,len,ap1,ap2);
  142. }
  143. void gen_code2(int op, int len, int len2, AMODE *ap1, AMODE *ap2)
  144. {
  145.         OCODE    *new;
  146.         new = xalloc(sizeof(OCODE));
  147.         new->opcode = op;
  148.         new->oper1 = copy_addr(ap1);
  149.         new->oper2 = copy_addr(ap2);
  150. if (len < 0)
  151.          len = -len;
  152. if (new->oper1)
  153. new->oper1->length = len;
  154. if (len2 < 0)
  155.          len2 = -len2;
  156. if (new->oper2)
  157. new->oper2->length = len2;
  158.         add_peep(new);
  159. }
  160. void add_peep(OCODE *new)
  161. /*
  162.  *      add the ocoderuction pointed to by new to the peep list.
  163.  */
  164. {       if( peep_head == 0 )
  165.                 {
  166.                 peep_head = peep_tail = new;
  167.                 new->fwd = 0;
  168.                 new->back = 0;
  169.                 }
  170.         else
  171.                 {
  172.                 new->fwd = 0;
  173.                 new->back = peep_tail;
  174.                 peep_tail->fwd = new;
  175.                 peep_tail = new;
  176.                 }
  177. }
  178. void gen_label(int labno)
  179. /*
  180.  *      add a compiler generated label to the peep list.
  181.  */
  182. {       OCODE    *new;
  183.         new = xalloc(sizeof(OCODE));
  184.         new->opcode = op_label;
  185.         new->oper1 = (AMODE *)labno;
  186.         add_peep(new);
  187. }
  188. void flush_peep(void)
  189. /*
  190.  *      output all code and labels in the peep list.
  191.  */
  192. {       opt3();         /* do the peephole optimizations */
  193.         while( peep_head != 0 )
  194.                 {
  195.                 if( peep_head->opcode == op_label )
  196.                         put_label((int)peep_head->oper1);
  197.                 else
  198. if (peep_head->opcode == op_funclabel)
  199. gen_strlab(peep_head->oper1);
  200. else
  201.                         put_code(peep_head);
  202.                 peep_head = peep_head->fwd;
  203.                 }
  204. dump_muldivval();
  205. peep_head = 0;
  206. }
  207. void peep_add(OCODE *ip)
  208. /*
  209.  * Turn add,1 into inc
  210.  */
  211. {
  212. if (ip->noopt)
  213. return;
  214. if (ip->oper2->mode != am_immed || !isintconst(ip->oper2->offset->nodetype))
  215. return;
  216. if (ip->oper2->offset->v.i == 1) {
  217. ip->opcode = op_inc;
  218. ip->oper2 = 0;
  219. }
  220. return;
  221. }
  222. /*
  223.  * Turn sub,1 into dec
  224.  */
  225. void peep_sub(OCODE *ip)
  226. {
  227. if (ip->noopt)
  228. return;
  229. if (ip->oper2->mode != am_immed || !isintconst(ip->oper2->offset->nodetype))
  230. return;
  231. if (ip->oper2->offset->v.i == 1) {
  232. ip->opcode = op_dec;
  233. ip->oper2 = 0;
  234. }
  235. return;
  236. }
  237. /*
  238.  * Turn move reg,0 into sub reg,reg
  239.  */
  240. void peep_move(OCODE *ip)
  241. {
  242. if (ip->noopt)
  243. return;
  244. if (ip->oper1->mode != am_dreg || 
  245. ip->oper2->mode != am_immed || !isintconst(ip->oper2->offset->nodetype))
  246. return;
  247. if (ip->oper2->offset->v.i == 0) {
  248. ip->opcode = op_sub;
  249. ip->oper2 = ip->oper1;
  250. }
  251. return;
  252. }
  253. /*
  254.  * delete or reg,reg preceded by an instruction that already sets flags
  255.  */
  256. void peep_or(OCODE *ip)
  257. {
  258. OCODE *ip2;
  259. if (ip->noopt)
  260. return;
  261. if ((ip->oper1->mode != ip->oper2->mode) || ip->oper1->mode != am_dreg ||
  262. (ip->oper1->preg != ip->oper2->preg))
  263. return;
  264. ip2 = ip->back;
  265. if (!ip2->oper1 || ip2->opcode == op_label || ip2->oper1->mode != am_dreg || ip2->oper1->preg != ip->oper1->preg)
  266. return;
  267. if (ip2->opcode != op_sub && ip2->opcode != op_add && ip2->opcode != op_inc
  268. && ip2->opcode != op_dec && ip2->opcode != op_and && ip2->opcode != op_or
  269. && ip2->opcode != op_xor)
  270. return;
  271. ip2->fwd = ip->fwd;
  272. ip->fwd->back = ip->back;
  273. /* A quick pentium optimization */
  274. if (ip2->opcode == op_and)
  275. ip2->opcode = op_test;
  276. }
  277. void peep_uctran(OCODE *ip)
  278. /*
  279.  *      peephole optimization for unconditional transfers.
  280.  *      deletes instructions which have no path.
  281.  *      applies to bra, jmp, and rts instructions.
  282.  */
  283. {       while( ip->fwd != 0 && ip->fwd->opcode != op_label )
  284.                 {
  285.                 ip->fwd = ip->fwd->fwd;
  286.                 if( ip->fwd != 0 )
  287.                         ip->fwd->back = ip;
  288.                 }
  289. }
  290. void peep_label(OCODE *ip)
  291. /*
  292.  * peephole optimization for labels
  293.  * deletes relbranches that jump to the next instruction
  294.  */
  295. {
  296. OCODE *curpos, *index;
  297. curpos = ip;
  298. do {
  299. curpos = curpos->back;
  300. } while(curpos->opcode == op_label || curpos->opcode == op_line);
  301. while ((curpos->opcode == op_jmp) || curpos->opcode == op_cmp
  302. || curpos->opcode == op_test 
  303. || (curpos->opcode == op_jne) || (curpos->opcode == op_je) 
  304. || (curpos->opcode == op_jge) || (curpos->opcode == op_jle) 
  305. || (curpos->opcode == op_jg) || (curpos->opcode == op_jl) 
  306. || (curpos->opcode == op_jnc) || (curpos->opcode == op_jbe) 
  307. || (curpos->opcode == op_ja) || (curpos->opcode == op_jb) ) {
  308. index = curpos->fwd;
  309. if (curpos->noopt)
  310. return;
  311. if (curpos->opcode == op_cmp
  312. || curpos->opcode == op_test) {
  313. curpos->back->fwd = curpos->fwd;
  314. curpos->fwd->back = curpos->back;
  315. curpos = curpos->back;
  316. }
  317. else {
  318. do {
  319. if ((index->opcode == op_label) && (curpos->oper1->mode == am_immed) && ((int)index->oper1 == curpos->oper1->offset->v.i)) {
  320. curpos->back->fwd = curpos->fwd;
  321. curpos->fwd->back = curpos->back;
  322. curpos = curpos->back;
  323. break;
  324. }
  325. index = index->fwd;
  326. } while (index != ip->fwd);
  327. if (index == ip->fwd)
  328. break;
  329. }
  330. while(curpos->opcode == op_label || curpos->opcode == op_line)
  331. curpos = curpos->back;
  332. }
  333. }
  334. int equal_address(AMODE *ap1,AMODE *ap2)
  335. {
  336. if (ap1->mode != ap2->mode)
  337. return(FALSE);
  338. switch (ap1->mode) {
  339. case am_indispscale:
  340. if (ap1->scale != ap2->scale || ap1->sreg != ap2->sreg)
  341. return(FALSE);
  342. case am_indisp:
  343. if (ap1->offset)
  344. if (ap2->offset) {
  345. if (ap1->offset->v.i != ap2->offset->v.i)
  346. return(FALSE);
  347. }
  348. else
  349. return(FALSE);
  350. else
  351. if (ap2->offset)
  352. return(FALSE);
  353. case am_dreg:
  354. case am_freg:
  355. if (ap1->preg != ap2->preg)
  356. return(FALSE);
  357. break;
  358. case am_direct:
  359. return FALSE;
  360. }
  361. return(TRUE);
  362. }
  363. void opt3(void)
  364. /*
  365.  *      peephole optimizer. This routine calls the instruction
  366.  *      specific optimization routines above for each instruction
  367.  *      in the peep list.
  368.  */
  369. {       OCODE    *ip;
  370.         ip = peep_head;
  371.         while( ip != 0 )
  372.                 {
  373.                 switch( ip->opcode )
  374.                         {
  375. case op_label:
  376. peep_label(ip);
  377. break;
  378. case op_add:
  379. peep_add(ip);
  380. break;
  381. case op_sub:
  382. peep_sub(ip);
  383. break;
  384. case op_mov:
  385. peep_move(ip);
  386. break;
  387. case op_or:
  388. peep_or(ip);
  389. break;
  390.                         case op_jmp:
  391.                         case op_ret:
  392.                                 peep_uctran(ip);
  393.                         }
  394.                 ip = ip->fwd;
  395.                 }
  396. }