table 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /* 68020 desciptor table for ACK target optimizer */
  2. MAXOP 2;
  3. PAREN_OPEN "(";
  4. PAREN_CLOSE ")";
  5. %%;
  6. /* useful addressing modes-> */
  7. CONST {VAL[0] == '#' }; /* constant */
  8. NUM {is_number(VAL) };
  9. A,B {no_side_effects(VAL) };
  10. D {VAL[0] != '#' && !is_areg(VAL) }; /* not an addr. reg */
  11. X,Y {TRUE };
  12. DREG,DREG2 {is_dreg(VAL) }; /* data register */
  13. DSREG {is_dsreg(VAL) }; /* data register */
  14. AREG {is_areg(VAL) }; /* addressregister */
  15. FPREG,FPREG2 {is_fpreg(VAL) }; /* fp register */
  16. LAB,L1,L2 {VAL[0] == 'I' }; /* label */
  17. NO32 {no_part("div",VAL) && no_part("mul",VAL) && no_part(".l",VAL)};
  18. /* for move.w ... */
  19. BITNO {TRUE };
  20. %%;
  21. /* optimization patterns-> */
  22. /* rewriting rules */
  23. tst X -> tst.w X ;
  24. cmp X,Y -> cmp.w X,Y ;
  25. /* special instructions */
  26. move.w #0,D -> clr.w D ;
  27. move.l #0,D -> clr.l D ;
  28. move.l #0,AREG -> sub.l AREG,AREG ;
  29. /* tst-elimination */
  30. add.l #2,sp : tst.w X {no_part("sp",X)} -> move.w X,(sp)+ ;
  31. add.l #4,sp : tst.l D {no_part("sp",D)} -> move.l D,(sp)+ ;
  32. add.l #2,sp : move.w X,-(sp) -> move.w X,(sp) ;
  33. add.l #4,sp : move.l X,-(sp) -> move.l X,(sp) ;
  34. add.l #4,sp : pea (NUM) -> move.l #NUM,(sp) ;
  35. add.l #4,sp : pea (AREG) -> move.l AREG,(sp) ;
  36. add.l #NUM,sp : unlk AREG -> unlk AREG ;
  37. add.l #NUM,sp : movem.l X,Y : unlk AREG
  38. {no_part("sp",X) && no_part("sp",Y)} -> movem.l X,Y : unlk AREG ;
  39. move.w A,X : tst.w A -> move.w A,X ;
  40. move.w X,A : tst.w A -> move.w X,A ;
  41. move.l A,D : tst.l A {no_part(D,A)} -> move.l A,D ;
  42. move.l X,D : tst.l D -> move.l X,D ;
  43. move.l A,AREG : tst.l A
  44. {no_part(AREG,A)} -> tst.l A : move.l A,AREG ;
  45. move.l X,AREG : move.l AREG,DREG :
  46. tst.l DREG : beq LAB -> move.l X,DREG :
  47. move.l DREG,AREG: beq LAB ;
  48. move.l X,AREG : move.l AREG,DREG :
  49. tst.l DREG : bne LAB -> move.l X,DREG :
  50. move.l DREG,AREG: bne LAB ;
  51. /* redundant move */
  52. move.l DREG,DREG2 : move.l DREG2,DREG -> move.l DREG,DREG2 ;
  53. move.l DREG,AREG : move.l AREG,DREG -> move.l DREG,AREG : tst.l DREG ;
  54. move.l AREG,DREG : move.l DREG,AREG -> move.l AREG,DREG ;
  55. move.w DREG,DREG2 : move.w DREG2,DREG -> move.w DREG,DREG2 ;
  56. move.l AREG,AREG -> ;
  57. move.l A,B : move.l A,B -> move.l A,B ;
  58. move.w A,B : move.w A,B -> move.w A,B ;
  59. move.b A,B : move.b A,B -> move.b A,B ;
  60. /* register subsumption */
  61. move.w DREG,A : ANY A,X
  62. {reg_subs_allowed(ANY) &&
  63. !is_dreg(A) } -> move.w DREG,A : ANY DREG,X ;
  64. move.l DREG,A : ANY A,X
  65. {reg_subs_allowed(ANY) &&
  66. !is_dreg(A) } -> move.l DREG,A : ANY DREG,X ;
  67. move.w DREG,DREG2 : NO32 A,DREG2 : move.w DREG2,DREG
  68. {no_part(DREG2,A)} -> NO32 A,DREG : move.w DREG,DREG2 ;
  69. move.l DREG,DREG2 : ANY A,DREG2 : move.l DREG2,DREG
  70. {no_part(DREG2,A)} -> ANY A,DREG : move.l DREG,DREG2 ;
  71. cmp.b A,A : beq LAB -> bra LAB ;
  72. cmp.w A,A : beq LAB -> bra LAB ;
  73. cmp.l A,A : beq LAB -> bra LAB ;
  74. /* cannot delete cmp's because they affect condition codes (obvious, but ... )*/
  75. cmp.b A,A : bne LAB -> cmp.b A,A ;
  76. cmp.w A,A : bne LAB -> cmp.w A,A ;
  77. cmp.l A,A : bne LAB -> cmp.l A,A ;
  78. /* change some compares to tests */
  79. cmp.w #0,D : beq LAB -> tst.w D : beq LAB ;
  80. cmp.w #0,D : bne LAB -> tst.w D : bne LAB ;
  81. cmp.w #0,D : blt LAB -> tst.w D : blt LAB ;
  82. cmp.w #0,D : ble LAB -> tst.w D : ble LAB ;
  83. cmp.w #0,D : bge LAB -> tst.w D : bge LAB ;
  84. cmp.w #0,D : bgt LAB -> tst.w D : bgt LAB ;
  85. cmp.l #0,D : beq LAB -> tst.l D : beq LAB ;
  86. cmp.l #0,D : bne LAB -> tst.l D : bne LAB ;
  87. cmp.l #0,D : blt LAB -> tst.l D : blt LAB ;
  88. cmp.l #0,D : ble LAB -> tst.l D : ble LAB ;
  89. cmp.l #0,D : bge LAB -> tst.l D : bge LAB ;
  90. cmp.l #0,D : bgt LAB -> tst.l D : bgt LAB ;
  91. cmp.w D,#0 : beq LAB -> tst.w D : beq LAB ;
  92. cmp.w D,#0 : bne LAB -> tst.w D : bne LAB ;
  93. cmp.w D,#0 : blt LAB -> tst.w D : bgt LAB ;
  94. cmp.w D,#0 : ble LAB -> tst.w D : bge LAB ;
  95. cmp.w D,#0 : bge LAB -> tst.w D : ble LAB ;
  96. cmp.w D,#0 : bgt LAB -> tst.w D : blt LAB ;
  97. cmp.l D,#0 : beq LAB -> tst.l D : beq LAB ;
  98. cmp.l D,#0 : bne LAB -> tst.l D : bne LAB ;
  99. cmp.l D,#0 : blt LAB -> tst.l D : bgt LAB ;
  100. cmp.l D,#0 : ble LAB -> tst.l D : bge LAB ;
  101. cmp.l D,#0 : bge LAB -> tst.l D : ble LAB ;
  102. cmp.l D,#0 : bgt LAB -> tst.l D : blt LAB ;
  103. /* change "cmp" into "add" or "sub" (possibly "addq" or "subq") */
  104. cmp.w #-NUM,DSREG : beq LAB -> add.w #NUM,DSREG : beq LAB ;
  105. cmp.l #-NUM,DSREG : beq LAB -> add.l #NUM,DSREG : beq LAB ;
  106. cmp.w #-NUM,DSREG : bne LAB -> add.w #NUM,DSREG : bne LAB ;
  107. cmp.l #-NUM,DSREG : bne LAB -> add.l #NUM,DSREG : bne LAB ;
  108. cmp.w #NUM,DSREG : beq LAB -> sub.w #NUM,DSREG : beq LAB ;
  109. cmp.l #NUM,DSREG : beq LAB -> sub.l #NUM,DSREG : beq LAB ;
  110. cmp.w #NUM,DSREG : bne LAB -> sub.w #NUM,DSREG : bne LAB ;
  111. cmp.l #NUM,DSREG : bne LAB -> sub.l #NUM,DSREG : bne LAB ;
  112. /* addq and subq */
  113. lea -1(AREG),AREG -> sub.l #1,AREG ;
  114. add.w #-NUM,X -> sub.w #NUM,X ;
  115. add.l #-NUM,X -> sub.l #NUM,X ;
  116. sub.w #-NUM,X -> add.w #NUM,X ;
  117. sub.l #-NUM,X -> add.l #NUM,X ;
  118. /* bit-test instruction */
  119. move.b X,DSREG : and.w #NUM,DSREG :
  120. tst.w DSREG : beq LAB
  121. { bitno(NUM,BITNO)} -> btst #BITNO,X ;
  122. move.b X,DSREG : and.l #NUM,DSREG :
  123. tst.l DSREG : beq LAB
  124. { bitno(NUM,BITNO)} -> btst #BITNO,X ;
  125. /* skip over jump */
  126. beq L1 : bra L2: labdef L1 -> bne L2 : labdef L1 ;
  127. bge L1 : bra L2: labdef L1 -> blt L2 : labdef L1 ;
  128. bgt L1 : bra L2: labdef L1 -> ble L2 : labdef L1 ;
  129. blt L1 : bra L2: labdef L1 -> bge L2 : labdef L1 ;
  130. ble L1 : bra L2: labdef L1 -> bgt L2 : labdef L1 ;
  131. bne L1 : bra L2: labdef L1 -> beq L2 : labdef L1 ;
  132. move.l A, B : bra LAB : labdef L1 : move.l A, B : labdef LAB
  133. -> labdef L1 : move.l A, B :
  134. labdef LAB ;
  135. /* some strength reduction */
  136. mulu.l #NUM,DREG -> muls.l #NUM,DREG ;
  137. muls.l #NUM,DREG
  138. {isshift_once(NUM,X,Y)} -> asl.l #X,DREG :
  139. asl.l #Y,DREG ;
  140. muls.l #NUM,DREG
  141. {is_shift_twice(NUM,X,Y)} -> asl.l #X,DREG :
  142. move.l DREG,-(sp) :
  143. asl.l #Y,DREG :
  144. add.l (sp)+,DREG ;
  145. asl.l #0,DREG -> ;
  146. asl.l #1,DREG -> add.l DREG,DREG ;
  147. move.l A,-(sp) : move.l B,-(sp) : fmove.d (sp)+,FPREG
  148. {combines_to_double(A,B)} -> fmove.d B,FPREG ;
  149. move.l A,-(sp) : move.l B,-(sp) : fmove.d X,FPREG : fmove.d (sp)+,FPREG2
  150. {combines_to_double(A,B) &&
  151. strcmp(FPREG,FPREG2) &&
  152. no_part("sp",X) } -> fmove.d X,FPREG :
  153. fmove.d B,FPREG2 ;
  154. %%;
  155. /* auxiliary routines: */
  156. int no_side_effects(s)
  157. register char *s;
  158. {
  159. for(;;) {
  160. switch(*s++) {
  161. case '\0': return TRUE;
  162. case '-': if (*s == '(') return FALSE; break;
  163. case ')': if (*s == '+') return FALSE; break;
  164. }
  165. }
  166. /* NOTREACHED */
  167. }
  168. int isshift_once(s, c1, c2)
  169. char *s, *c1, *c2;
  170. {
  171. long atol();
  172. register int i = 0;
  173. long val = atol(s), pow = 1;
  174. while (i <= 16) {
  175. if (pow & val) {
  176. val -= pow;
  177. if (val == 0) {
  178. sprintf(c1, "%d", i <= 8 ? i : 8);
  179. sprintf(c2, "%d", i <= 8 ? 0 : i - 8);
  180. return 1;
  181. }
  182. return 0;
  183. }
  184. pow <<= 1;
  185. i++;
  186. }
  187. return 0;
  188. }
  189. int is_shift_twice(s, c1, c2)
  190. char *s, *c1, *c2;
  191. {
  192. long atol();
  193. register int i = 0;
  194. long val = atol(s), pow = 1;
  195. while (i <= 8) {
  196. if (pow & val) {
  197. val -= pow;
  198. sprintf(c1, "%d", i);
  199. break;
  200. }
  201. pow <<= 1;
  202. i++;
  203. }
  204. if (i > 8) return 0;
  205. if (pow > 0 && val) {
  206. i = 0;
  207. while (i <= 8) {
  208. if (pow & val) {
  209. val -= pow;
  210. sprintf(c2, "%d", i);
  211. if (val == 0) return 1;
  212. break;
  213. }
  214. pow <<= 1;
  215. i++;
  216. }
  217. }
  218. return 0;
  219. }
  220. int is_dreg(s)
  221. register char *s;
  222. {
  223. return *s++ == 'd' && *s >= '0' && *s++ <= '7' && *s == '\0';
  224. }
  225. int is_fpreg(s)
  226. register char *s;
  227. {
  228. return *s++ == 'f' && *s++ == 'p' &&
  229. *s >= '0' && *s++ <= '7' && *s == '\0';
  230. }
  231. int is_dsreg(s)
  232. register char *s;
  233. {
  234. return *s++ == 'd' && *s >= '0' && *s++ <= '2' && *s == '\0';
  235. }
  236. int is_areg(s)
  237. register char *s;
  238. {
  239. return *s++ == 'a' && *s >= '0' && *s++ <= '6' && *s == '\0';
  240. }
  241. int no_part(part,s)
  242. char *part,*s;
  243. {
  244. char *tmp1,*tmp2;
  245. while (*s != '\0') {
  246. if (*s == *part) {
  247. for (tmp1=part,tmp2=s;; tmp1++,tmp2++) {
  248. if (*tmp1== '\0') return FALSE;
  249. if (*tmp1 != *tmp2) break;
  250. }
  251. }
  252. s++;
  253. }
  254. return TRUE;
  255. }
  256. /* see if register subsumption is allowed for instruction Opc */
  257. int reg_subs_allowed(opc)
  258. char *opc;
  259. {
  260. return strcmp(opc,"cmp") != 0 && strcmp(opc,"lea") != 0;
  261. }
  262. int is_number(s)
  263. register char *s;
  264. {
  265. while (*s != '\0') {
  266. if (*s < '0' || *s++ > '9') return FALSE;
  267. }
  268. return TRUE;
  269. }
  270. int bitno(s,no)
  271. char *s,*no;
  272. {
  273. int n,i;
  274. n = atoi(s);
  275. if (n < 1 || n > 128) return FALSE;
  276. for (i = 0; i < 8 ; i++) {
  277. if (n == 1) {
  278. sprintf(no,"%d",i);
  279. return TRUE;
  280. }
  281. n >>= 1;
  282. }
  283. return FALSE;
  284. }
  285. int combines_to_double(a,b)
  286. register char *a,*b;
  287. {
  288. /* recognize (_name+4) combined with (_name),
  289. and (offset+4,...) combined with (offset,...)
  290. */
  291. if (*a++ == '(' && *b++ == '(') {
  292. if (*a == '-' || *a >= '0' && *a <= '9') {
  293. int na = atoi(a);
  294. int nb = atoi(b);
  295. if (*a == '-') a++;
  296. if (*b == '-') b++;
  297. if (na == nb + 4) {
  298. while (*a >= '0' && *a <= '9') a++;
  299. while (*b >= '0' && *b <= '9') b++;
  300. return !strcmp(a,b) && *a++ == ',' &&
  301. *a++ == 'a' && *a++ && *a++ == ')' &&
  302. !*a;
  303. }
  304. return FALSE;
  305. }
  306. while (*a && *a == *b) {
  307. a++;
  308. b++;
  309. }
  310. if (*b++ == ')' && ! *b && *a++ == '+' && *a++ == '4' &&
  311. *a++ == ')' && !*a)
  312. return TRUE;
  313. }
  314. return FALSE;
  315. }