OLD | NEW |
1 // Inferno utils/5c/peep.c | 1 // Inferno utils/5c/peep.c |
2 // http://code.google.com/p/inferno-os/source/browse/utils/5c/peep.c | 2 // http://code.google.com/p/inferno-os/source/browse/utils/5c/peep.c |
3 // | 3 // |
4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. | 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. |
5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) | 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) |
6 // Portions Copyright © 1997-1999 Vita Nuova Limited | 6 // Portions Copyright © 1997-1999 Vita Nuova Limited |
7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuov
a.com) | 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuov
a.com) |
8 // Portions Copyright © 2004,2006 Bruce Ellis | 8 // Portions Copyright © 2004,2006 Bruce Ellis |
9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) | 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) |
10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others | 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 int isdconst(Addr *a); | 42 int isdconst(Addr *a); |
43 | 43 |
44 void | 44 void |
45 peep(void) | 45 peep(void) |
46 { | 46 { |
47 Reg *r, *r1, *r2; | 47 Reg *r, *r1, *r2; |
48 Prog *p, *p1; | 48 Prog *p, *p1; |
49 int t; | 49 int t; |
50 | 50 |
51 p1 = nil; | 51 p1 = nil; |
52 USED(p1); // ... in unreachable code... | |
53 /* | 52 /* |
54 * complete R structure | 53 * complete R structure |
55 */ | 54 */ |
56 for(r=firstr; r!=R; r=r1) { | 55 for(r=firstr; r!=R; r=r1) { |
57 r1 = r->link; | 56 r1 = r->link; |
58 if(r1 == R) | 57 if(r1 == R) |
59 break; | 58 break; |
60 p = r->prog->link; | 59 p = r->prog->link; |
61 while(p != r1->prog) | 60 while(p != r1->prog) |
62 switch(p->as) { | 61 switch(p->as) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 break; | 112 break; |
114 } | 113 } |
115 if(subprop(r) && copyprop(r)) { | 114 if(subprop(r) && copyprop(r)) { |
116 excise(r); | 115 excise(r); |
117 t++; | 116 t++; |
118 break; | 117 break; |
119 } | 118 } |
120 } | 119 } |
121 break; | 120 break; |
122 | 121 |
123 #ifdef» NOTDEF | 122 #ifdef NOTDEF |
124 if(p->scond == C_SCOND_NONE) | 123 if(p->scond == C_SCOND_NONE) |
125 if(regtyp(&p->to)) | 124 if(regtyp(&p->to)) |
126 if(isdconst(&p->from)) { | 125 if(isdconst(&p->from)) { |
127 constprop(&p->from, &p->to, r->s1); | 126 constprop(&p->from, &p->to, r->s1); |
128 } | 127 } |
129 break; | 128 break; |
130 #endif | 129 #endif |
131 } | 130 } |
132 } | 131 } |
133 if(t) | 132 if(t) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 if(p1->as != p->as) | 167 if(p1->as != p->as) |
169 break; | 168 break; |
170 if(p1->from.type != D_REG || p1->from.reg != p->to.reg) | 169 if(p1->from.type != D_REG || p1->from.reg != p->to.reg) |
171 break; | 170 break; |
172 if(p1->to.type != D_REG || p1->to.reg != p->to.reg) | 171 if(p1->to.type != D_REG || p1->to.reg != p->to.reg) |
173 break; | 172 break; |
174 excise(r1); | 173 excise(r1); |
175 break; | 174 break; |
176 } | 175 } |
177 } | 176 } |
178 #ifdef NOTDEF | |
179 | 177 |
180 //» for(r=firstr; r!=R; r=r->link) { | 178 » for(r=firstr; r!=R; r=r->link) { |
181 //» » p = r->prog; | 179 » » p = r->prog; |
182 //» » switch(p->as) { | 180 » » switch(p->as) { |
183 //» » case AMOVW: | 181 » » case AMOVW: |
184 //» » case AMOVB: | 182 » » case AMOVB: |
185 //» » case AMOVBU: | 183 » » case AMOVBU: |
186 //» » » if(p->from.type == D_OREG && p->from.offset == 0) | 184 » » » if(p->from.type == D_OREG && p->from.offset == 0) |
187 //» » » » xtramodes(r, &p->from); | 185 » » » » xtramodes(r, &p->from); |
188 //» » » else | 186 » » » else |
189 //» » » if(p->to.type == D_OREG && p->to.offset == 0) | 187 » » » if(p->to.type == D_OREG && p->to.offset == 0) |
190 //» » » » xtramodes(r, &p->to); | 188 » » » » xtramodes(r, &p->to); |
191 //» » » else | 189 » » » else |
192 //» » » » continue; | 190 » » » » continue; |
193 //» » » break; | 191 » » » break; |
194 // case ACMP: | 192 // case ACMP: |
195 // /* | 193 // /* |
196 // * elide CMP $0,x if calculation of x can set condition
codes | 194 // * elide CMP $0,x if calculation of x can set condition
codes |
197 // */ | 195 // */ |
198 // if(isdconst(&p->from) || p->from.offset != 0) | 196 // if(isdconst(&p->from) || p->from.offset != 0) |
199 // continue; | 197 // continue; |
200 // r2 = r->s1; | 198 // r2 = r->s1; |
201 // if(r2 == R) | 199 // if(r2 == R) |
202 // continue; | 200 // continue; |
203 // t = r2->prog->as; | 201 // t = r2->prog->as; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 // case AADD: | 249 // case AADD: |
252 // case AADC: | 250 // case AADC: |
253 // case ASBC: | 251 // case ASBC: |
254 // case ARSC: | 252 // case ARSC: |
255 // break; | 253 // break; |
256 // } | 254 // } |
257 // p1->scond |= C_SBIT; | 255 // p1->scond |= C_SBIT; |
258 // r2->prog->as = t; | 256 // r2->prog->as = t; |
259 // excise(r); | 257 // excise(r); |
260 // continue; | 258 // continue; |
261 //» » } | 259 » » } |
262 //» } | 260 » } |
263 | 261 |
264 » predicate(); | 262 //» predicate(); |
265 #endif | |
266 } | 263 } |
267 | 264 |
| 265 /* |
| 266 * uniqp returns a "unique" predecessor to instruction r. |
| 267 * If the instruction is the first one or has multiple |
| 268 * predecessors due to jump, R is returned. |
| 269 */ |
268 Reg* | 270 Reg* |
269 uniqp(Reg *r) | 271 uniqp(Reg *r) |
270 { | 272 { |
271 Reg *r1; | 273 Reg *r1; |
272 | 274 |
273 r1 = r->p1; | 275 r1 = r->p1; |
274 if(r1 == R) { | 276 if(r1 == R) { |
275 r1 = r->p2; | 277 r1 = r->p2; |
276 if(r1 == R || r1->p2link != R) | 278 if(r1 == R || r1->p2link != R) |
277 return R; | 279 return R; |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 case ASRA: | 732 case ASRA: |
731 o |= 2<<5; | 733 o |= 2<<5; |
732 break; | 734 break; |
733 } | 735 } |
734 p2->from.offset = o; | 736 p2->from.offset = o; |
735 if(debug['P']) | 737 if(debug['P']) |
736 print("\t=>%P\tSUCCEED\n", p2); | 738 print("\t=>%P\tSUCCEED\n", p2); |
737 return 1; | 739 return 1; |
738 } | 740 } |
739 | 741 |
| 742 /* |
| 743 * findpre returns the last instruction mentioning v |
| 744 * before r. It must be a set, and there must be |
| 745 * a unique path from that instruction to r. |
| 746 */ |
740 Reg* | 747 Reg* |
741 findpre(Reg *r, Adr *v) | 748 findpre(Reg *r, Adr *v) |
742 { | 749 { |
743 Reg *r1; | 750 Reg *r1; |
744 | 751 |
745 for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) { | 752 for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) { |
746 if(uniqs(r1) != r) | 753 if(uniqs(r1) != r) |
747 return R; | 754 return R; |
748 switch(copyu(r1->prog, v, A)) { | 755 switch(copyu(r1->prog, v, A)) { |
749 case 1: /* used */ | 756 case 1: /* used */ |
750 case 2: /* read-alter-rewrite */ | 757 case 2: /* read-alter-rewrite */ |
751 return R; | 758 return R; |
752 case 3: /* set */ | 759 case 3: /* set */ |
753 case 4: /* set and used */ | 760 case 4: /* set and used */ |
754 return r1; | 761 return r1; |
755 } | 762 } |
756 } | 763 } |
757 return R; | 764 return R; |
758 } | 765 } |
759 | 766 |
| 767 /* |
| 768 * findinc finds ADD instructions with a constant |
| 769 * argument which falls within the immed_12 range. |
| 770 */ |
760 Reg* | 771 Reg* |
761 findinc(Reg *r, Reg *r2, Adr *v) | 772 findinc(Reg *r, Reg *r2, Adr *v) |
762 { | 773 { |
763 Reg *r1; | 774 Reg *r1; |
764 Prog *p; | 775 Prog *p; |
765 | 776 |
766 | 777 |
767 for(r1=uniqs(r); r1!=R && r1!=r2; r=r1,r1=uniqs(r)) { | 778 for(r1=uniqs(r); r1!=R && r1!=r2; r=r1,r1=uniqs(r)) { |
768 if(uniqp(r1) != r) | 779 if(uniqp(r1) != r) |
769 return R; | 780 return R; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
840 int | 851 int |
841 finduse(Reg *r, Adr *v) | 852 finduse(Reg *r, Adr *v) |
842 { | 853 { |
843 Reg *r1; | 854 Reg *r1; |
844 | 855 |
845 for(r1=firstr; r1!=R; r1=r1->link) | 856 for(r1=firstr; r1!=R; r1=r1->link) |
846 r1->active = 0; | 857 r1->active = 0; |
847 return findu1(r, v); | 858 return findu1(r, v); |
848 } | 859 } |
849 | 860 |
| 861 /* |
| 862 * xtramodes enables the ARM post increment and |
| 863 * shift offset addressing modes to transform |
| 864 * MOVW 0(R3),R1 |
| 865 * ADD $4,R3,R3 |
| 866 * into |
| 867 * MOVW.P 4(R3),R1 |
| 868 * and· |
| 869 * ADD R0,R1 |
| 870 * MOVBU 0(R1),R0 |
| 871 * into· |
| 872 * MOVBU R0<<0(R1),R0 |
| 873 */ |
850 int | 874 int |
851 xtramodes(Reg *r, Adr *a) | 875 xtramodes(Reg *r, Adr *a) |
852 { | 876 { |
853 Reg *r1, *r2, *r3; | 877 Reg *r1, *r2, *r3; |
854 Prog *p, *p1; | 878 Prog *p, *p1; |
855 Adr v; | 879 Adr v; |
856 | 880 |
857 p = r->prog; | 881 p = r->prog; |
858 if(debug['h'] && p->as == AMOVB && p->from.type == D_OREG) /* byte
load */ | |
859 return 0; | |
860 v = *a; | 882 v = *a; |
861 v.type = D_REG; | 883 v.type = D_REG; |
862 r1 = findpre(r, &v); | 884 r1 = findpre(r, &v); |
863 if(r1 != R) { | 885 if(r1 != R) { |
864 p1 = r1->prog; | 886 p1 = r1->prog; |
865 if(p1->to.type == D_REG && p1->to.reg == v.reg) | 887 if(p1->to.type == D_REG && p1->to.reg == v.reg) |
866 switch(p1->as) { | 888 switch(p1->as) { |
867 case AADD: | 889 case AADD: |
| 890 if(p1->scond & C_SBIT) |
| 891 // avoid altering ADD.S/ADC sequences. |
| 892 break; |
868 if(p1->from.type == D_REG || | 893 if(p1->from.type == D_REG || |
869 (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4))
== 0 && | 894 (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4))
== 0 && |
870 (p->as != AMOVB || (a == &p->from && (p1->from.offse
t&~0xf) == 0))) || | 895 (p->as != AMOVB || (a == &p->from && (p1->from.offse
t&~0xf) == 0))) || |
871 (p1->from.type == D_CONST && | 896 (p1->from.type == D_CONST && |
872 p1->from.offset > -4096 && p1->from.offset < 4096)) | 897 p1->from.offset > -4096 && p1->from.offset < 4096)) |
873 if(nochange(uniqs(r1), r, p1)) { | 898 if(nochange(uniqs(r1), r, p1)) { |
874 if(a != &p->from || v.reg != p->to.reg) | 899 if(a != &p->from || v.reg != p->to.reg) |
875 if (finduse(r->s1, &v)) { | 900 if (finduse(r->s1, &v)) { |
876 if(p1->reg == NREG || p1->reg == v.reg) | 901 if(p1->reg == NREG || p1->reg == v.reg) |
877 /* pre-indexing */ | 902 /* pre-indexing */ |
(...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1519 } | 1544 } |
1520 } | 1545 } |
1521 | 1546 |
1522 int | 1547 int |
1523 isdconst(Addr *a) | 1548 isdconst(Addr *a) |
1524 { | 1549 { |
1525 if(a->type == D_CONST && a->reg == NREG) | 1550 if(a->type == D_CONST && a->reg == NREG) |
1526 return 1; | 1551 return 1; |
1527 return 0; | 1552 return 0; |
1528 } | 1553 } |
OLD | NEW |