noop.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. #include "l.h"
  2. static Sym* sym_div;
  3. static Sym* sym_divu;
  4. static Sym* sym_mod;
  5. static Sym* sym_modu;
  6. void
  7. noops(void)
  8. {
  9. Prog *p, *q, *q1;
  10. int o, curframe, curbecome, maxbecome;
  11. /*
  12. * find leaf subroutines
  13. * become sizes
  14. * frame sizes
  15. * strip NOPs
  16. * expand RET
  17. * expand BECOME pseudo
  18. */
  19. if(debug['v'])
  20. Bprint(&bso, "%5.2f noops\n", cputime());
  21. Bflush(&bso);
  22. curframe = 0;
  23. curbecome = 0;
  24. maxbecome = 0;
  25. curtext = 0;
  26. q = P;
  27. for(p = firstp; p != P; p = p->link) {
  28. /* find out how much arg space is used in this TEXT */
  29. if(p->to.type == D_OREG && p->to.reg == REGSP)
  30. if(p->to.offset > curframe)
  31. curframe = p->to.offset;
  32. switch(p->as) {
  33. case ATEXT:
  34. if(curtext && curtext->from.sym) {
  35. curtext->from.sym->frame = curframe;
  36. curtext->from.sym->become = curbecome;
  37. if(curbecome > maxbecome)
  38. maxbecome = curbecome;
  39. }
  40. curframe = 0;
  41. curbecome = 0;
  42. p->mark |= LEAF;
  43. curtext = p;
  44. break;
  45. case ARET:
  46. /* special form of RET is BECOME */
  47. if(p->from.type == D_CONST)
  48. if(p->from.offset > curbecome)
  49. curbecome = p->from.offset;
  50. break;
  51. case ADIV:
  52. case ADIVU:
  53. case AMOD:
  54. case AMODU:
  55. q = p;
  56. if(prog_div == P)
  57. initdiv();
  58. if(curtext != P)
  59. curtext->mark &= ~LEAF;
  60. continue;
  61. case ANOP:
  62. q1 = p->link;
  63. q->link = q1; /* q is non-nop */
  64. q1->mark |= p->mark;
  65. continue;
  66. case ABL:
  67. if(curtext != P)
  68. curtext->mark &= ~LEAF;
  69. case ABCASE:
  70. case AB:
  71. case ABEQ:
  72. case ABNE:
  73. case ABCS:
  74. case ABHS:
  75. case ABCC:
  76. case ABLO:
  77. case ABMI:
  78. case ABPL:
  79. case ABVS:
  80. case ABVC:
  81. case ABHI:
  82. case ABLS:
  83. case ABGE:
  84. case ABLT:
  85. case ABGT:
  86. case ABLE:
  87. q1 = p->cond;
  88. if(q1 != P) {
  89. while(q1->as == ANOP) {
  90. q1 = q1->link;
  91. p->cond = q1;
  92. }
  93. }
  94. break;
  95. }
  96. q = p;
  97. }
  98. if(curtext && curtext->from.sym) {
  99. curtext->from.sym->frame = curframe;
  100. curtext->from.sym->become = curbecome;
  101. if(curbecome > maxbecome)
  102. maxbecome = curbecome;
  103. }
  104. if(debug['b'])
  105. print("max become = %d\n", maxbecome);
  106. xdefine("ALEFbecome", STEXT, maxbecome);
  107. curtext = 0;
  108. for(p = firstp; p != P; p = p->link) {
  109. switch(p->as) {
  110. case ATEXT:
  111. curtext = p;
  112. break;
  113. case ABL:
  114. if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
  115. o = maxbecome - curtext->from.sym->frame;
  116. if(o <= 0)
  117. break;
  118. /* calling a become or calling a variable */
  119. if(p->to.sym == S || p->to.sym->become) {
  120. curtext->to.offset += o;
  121. if(debug['b']) {
  122. curp = p;
  123. print("%D calling %D increase %d\n",
  124. &curtext->from, &p->to, o);
  125. }
  126. }
  127. }
  128. break;
  129. }
  130. }
  131. for(p = firstp; p != P; p = p->link) {
  132. o = p->as;
  133. switch(o) {
  134. case ATEXT:
  135. curtext = p;
  136. autosize = p->to.offset + 4;
  137. if(autosize <= 4)
  138. if(curtext->mark & LEAF) {
  139. p->to.offset = -4;
  140. autosize = 0;
  141. }
  142. if(!autosize && !(curtext->mark & LEAF)) {
  143. if(debug['v'])
  144. Bprint(&bso, "save suppressed in: %s\n",
  145. curtext->from.sym->name);
  146. Bflush(&bso);
  147. curtext->mark |= LEAF;
  148. }
  149. if(curtext->mark & LEAF) {
  150. if(curtext->from.sym)
  151. curtext->from.sym->type = SLEAF;
  152. #ifdef optimise_time
  153. if(autosize) {
  154. q = prg();
  155. q->as = ASUB;
  156. q->line = p->line;
  157. q->from.type = D_CONST;
  158. q->from.offset = autosize;
  159. q->to.type = D_REG;
  160. q->to.reg = REGSP;
  161. q->link = p->link;
  162. p->link = q;
  163. }
  164. break;
  165. #else
  166. if(!autosize)
  167. break;
  168. #endif
  169. }
  170. q1 = prg();
  171. q1->as = AMOVW;
  172. q1->scond |= C_WBIT;
  173. q1->line = p->line;
  174. q1->from.type = D_REG;
  175. q1->from.reg = REGLINK;
  176. q1->to.type = D_OREG;
  177. q1->to.offset = -autosize;
  178. q1->to.reg = REGSP;
  179. q1->link = p->link;
  180. p->link = q1;
  181. break;
  182. case ARET:
  183. nocache(p);
  184. if(p->from.type == D_CONST)
  185. goto become;
  186. if(curtext->mark & LEAF) {
  187. if(!autosize) {
  188. p->as = AB;
  189. p->from = zprg.from;
  190. p->to.type = D_OREG;
  191. p->to.offset = 0;
  192. p->to.reg = REGLINK;
  193. break;
  194. }
  195. #ifdef optimise_time
  196. p->as = AADD;
  197. p->from.type = D_CONST;
  198. p->from.offset = autosize;
  199. p->to.type = D_REG;
  200. p->to.reg = REGSP;
  201. q = prg();
  202. q->as = AB;
  203. q->scond = p->scond;
  204. q->line = p->line;
  205. q->to.type = D_OREG;
  206. q->to.offset = 0;
  207. q->to.reg = REGLINK;
  208. q->link = p->link;
  209. p->link = q;
  210. break;
  211. #endif
  212. }
  213. p->as = AMOVW;
  214. p->scond |= C_PBIT;
  215. p->from.type = D_OREG;
  216. p->from.offset = autosize;
  217. p->from.reg = REGSP;
  218. p->to.type = D_REG;
  219. p->to.reg = REGPC;
  220. break;
  221. become:
  222. if(curtext->mark & LEAF) {
  223. if(!autosize) {
  224. p->as = AB;
  225. p->from = zprg.from;
  226. break;
  227. }
  228. #ifdef optimise_time
  229. q = prg();
  230. q->scond = p->scond;
  231. q->line = p->line;
  232. q->as = AB;
  233. q->from = zprg.from;
  234. q->to = p->to;
  235. q->cond = p->cond;
  236. q->link = p->link;
  237. p->link = q;
  238. p->as = AADD;
  239. p->from = zprg.from;
  240. p->from.type = D_CONST;
  241. p->from.offset = autosize;
  242. p->to = zprg.to;
  243. p->to.type = D_REG;
  244. p->to.reg = REGSP;
  245. break;
  246. #endif
  247. }
  248. q = prg();
  249. q->scond = p->scond;
  250. q->line = p->line;
  251. q->as = AB;
  252. q->from = zprg.from;
  253. q->to = p->to;
  254. q->cond = p->cond;
  255. q->link = p->link;
  256. p->link = q;
  257. p->as = AMOVW;
  258. p->scond |= C_PBIT;
  259. p->from = zprg.from;
  260. p->from.type = D_OREG;
  261. p->from.offset = autosize;
  262. p->from.reg = REGSP;
  263. p->to = zprg.to;
  264. p->to.type = D_REG;
  265. p->to.reg = REGLINK;
  266. break;
  267. /*
  268. * 5c code generation for unsigned -> double made the
  269. * unfortunate assumption that single and double floating
  270. * point registers are aliased - true for emulated 7500
  271. * but not for vfp. Now corrected, but this test is
  272. * insurance against old 5c compiled code in libraries.
  273. */
  274. case AMOVWD:
  275. if((q = p->link) != P && q->as == ACMP)
  276. if((q = q->link) != P && q->as == AMOVF)
  277. if((q1 = q->link) != P && q1->as == AADDF)
  278. if(q1->to.type == D_FREG && q1->to.reg == p->to.reg) {
  279. q1->as = AADDD;
  280. q1 = prg();
  281. q1->scond = q->scond;
  282. q1->line = q->line;
  283. q1->as = AMOVFD;
  284. q1->from = q->to;
  285. q1->to = q1->from;
  286. q1->link = q->link;
  287. q->link = q1;
  288. }
  289. break;
  290. case ADIV:
  291. case ADIVU:
  292. case AMOD:
  293. case AMODU:
  294. if(debug['M'])
  295. break;
  296. if(p->from.type != D_REG)
  297. break;
  298. if(p->to.type != D_REG)
  299. break;
  300. q1 = p;
  301. /* MOV a,4(SP) */
  302. q = prg();
  303. q->link = p->link;
  304. p->link = q;
  305. p = q;
  306. p->as = AMOVW;
  307. p->line = q1->line;
  308. p->from.type = D_REG;
  309. p->from.reg = q1->from.reg;
  310. p->to.type = D_OREG;
  311. p->to.reg = REGSP;
  312. p->to.offset = 4;
  313. /* MOV b,REGTMP */
  314. q = prg();
  315. q->link = p->link;
  316. p->link = q;
  317. p = q;
  318. p->as = AMOVW;
  319. p->line = q1->line;
  320. p->from.type = D_REG;
  321. p->from.reg = q1->reg;
  322. if(q1->reg == NREG)
  323. p->from.reg = q1->to.reg;
  324. p->to.type = D_REG;
  325. p->to.reg = REGTMP;
  326. p->to.offset = 0;
  327. /* CALL appropriate */
  328. q = prg();
  329. q->link = p->link;
  330. p->link = q;
  331. p = q;
  332. p->as = ABL;
  333. p->line = q1->line;
  334. p->to.type = D_BRANCH;
  335. p->cond = p;
  336. switch(o) {
  337. case ADIV:
  338. p->cond = prog_div;
  339. p->to.sym = sym_div;
  340. break;
  341. case ADIVU:
  342. p->cond = prog_divu;
  343. p->to.sym = sym_divu;
  344. break;
  345. case AMOD:
  346. p->cond = prog_mod;
  347. p->to.sym = sym_mod;
  348. break;
  349. case AMODU:
  350. p->cond = prog_modu;
  351. p->to.sym = sym_modu;
  352. break;
  353. }
  354. /* MOV REGTMP, b */
  355. q = prg();
  356. q->link = p->link;
  357. p->link = q;
  358. p = q;
  359. p->as = AMOVW;
  360. p->line = q1->line;
  361. p->from.type = D_REG;
  362. p->from.reg = REGTMP;
  363. p->from.offset = 0;
  364. p->to.type = D_REG;
  365. p->to.reg = q1->to.reg;
  366. /* ADD $8,SP */
  367. q = prg();
  368. q->link = p->link;
  369. p->link = q;
  370. p = q;
  371. p->as = AADD;
  372. p->from.type = D_CONST;
  373. p->from.reg = NREG;
  374. p->from.offset = 8;
  375. p->reg = NREG;
  376. p->to.type = D_REG;
  377. p->to.reg = REGSP;
  378. /* SUB $8,SP */
  379. q1->as = ASUB;
  380. q1->from.type = D_CONST;
  381. q1->from.offset = 8;
  382. q1->from.reg = NREG;
  383. q1->reg = NREG;
  384. q1->to.type = D_REG;
  385. q1->to.reg = REGSP;
  386. break;
  387. }
  388. }
  389. }
  390. static void
  391. sigdiv(char *n)
  392. {
  393. Sym *s;
  394. s = lookup(n, 0);
  395. if(s->type == STEXT){
  396. if(s->sig == 0)
  397. s->sig = SIGNINTERN;
  398. }
  399. else if(s->type == 0 || s->type == SXREF)
  400. s->type = SUNDEF;
  401. }
  402. void
  403. divsig(void)
  404. {
  405. sigdiv("_div");
  406. sigdiv("_divu");
  407. sigdiv("_mod");
  408. sigdiv("_modu");
  409. }
  410. static void
  411. sdiv(Sym *s)
  412. {
  413. if(s->type == 0 || s->type == SXREF){
  414. /* undefsym(s); */
  415. s->type = SXREF;
  416. if(s->sig == 0)
  417. s->sig = SIGNINTERN;
  418. s->subtype = SIMPORT;
  419. }
  420. else if(s->type != STEXT)
  421. diag("undefined: %s", s->name);
  422. }
  423. void
  424. initdiv(void)
  425. {
  426. Sym *s2, *s3, *s4, *s5;
  427. Prog *p;
  428. if(prog_div != P)
  429. return;
  430. sym_div = s2 = lookup("_div", 0);
  431. sym_divu = s3 = lookup("_divu", 0);
  432. sym_mod = s4 = lookup("_mod", 0);
  433. sym_modu = s5 = lookup("_modu", 0);
  434. if(dlm) {
  435. sdiv(s2); if(s2->type == SXREF) prog_div = UP;
  436. sdiv(s3); if(s3->type == SXREF) prog_divu = UP;
  437. sdiv(s4); if(s4->type == SXREF) prog_mod = UP;
  438. sdiv(s5); if(s5->type == SXREF) prog_modu = UP;
  439. }
  440. for(p = firstp; p != P; p = p->link)
  441. if(p->as == ATEXT) {
  442. if(p->from.sym == s2)
  443. prog_div = p;
  444. if(p->from.sym == s3)
  445. prog_divu = p;
  446. if(p->from.sym == s4)
  447. prog_mod = p;
  448. if(p->from.sym == s5)
  449. prog_modu = p;
  450. }
  451. if(prog_div == P) {
  452. diag("undefined: %s", s2->name);
  453. prog_div = curtext;
  454. }
  455. if(prog_divu == P) {
  456. diag("undefined: %s", s3->name);
  457. prog_divu = curtext;
  458. }
  459. if(prog_mod == P) {
  460. diag("undefined: %s", s4->name);
  461. prog_mod = curtext;
  462. }
  463. if(prog_modu == P) {
  464. diag("undefined: %s", s5->name);
  465. prog_modu = curtext;
  466. }
  467. }
  468. void
  469. nocache(Prog *p)
  470. {
  471. p->optab = 0;
  472. p->from.class = 0;
  473. p->to.class = 0;
  474. }