noop.c 9.9 KB

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