LEFT | RIGHT |
1 // Inferno utils/8l/pass.c | 1 // Inferno utils/8l/pass.c |
2 // http://code.google.com/p/inferno-os/source/browse/utils/8l/pass.c | 2 // http://code.google.com/p/inferno-os/source/browse/utils/8l/pass.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 10 matching lines...) Expand all Loading... |
21 // all copies or substantial portions of the Software. | 21 // all copies or substantial portions of the Software. |
22 // | 22 // |
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
29 // THE SOFTWARE. | 29 // THE SOFTWARE. |
30 | 30 |
| 31 // Code and data passes. |
| 32 |
31 #include "l.h" | 33 #include "l.h" |
32 #include "../ld/lib.h" | 34 #include "../ld/lib.h" |
| 35 |
| 36 static void xfol(Prog*, Prog**); |
33 | 37 |
34 // see ../../pkg/runtime/proc.c:/StackGuard | 38 // see ../../pkg/runtime/proc.c:/StackGuard |
35 enum | 39 enum |
36 { | 40 { |
37 StackSmall = 128, | 41 StackSmall = 128, |
38 StackBig = 4096, | 42 StackBig = 4096, |
39 }; | 43 }; |
40 | |
41 void | |
42 dodata(void) | |
43 { | |
44 int i; | |
45 Sym *s; | |
46 Prog *p; | |
47 int32 t, u; | |
48 Section *sect; | |
49 | |
50 if(debug['v']) | |
51 Bprint(&bso, "%5.2f dodata\n", cputime()); | |
52 Bflush(&bso); | |
53 | |
54 segdata.rwx = 06; | |
55 segdata.vaddr = 0; /* span will += INITDAT */ | |
56 | |
57 for(p = datap; p != P; p = p->link) { | |
58 s = p->from.sym; | |
59 if(p->as == ADYNT || p->as == AINIT) | |
60 s->value = dtype; | |
61 if(s->type == SBSS) | |
62 s->type = SDATA; | |
63 if(s->type != SDATA && s->type != SELFDATA && s->type != SRODATA
) | |
64 diag("initialize non-data (%d): %s\n%P", | |
65 s->type, s->name, p); | |
66 t = p->from.offset + p->width; | |
67 if(t > s->size) | |
68 diag("initialize bounds (%ld): %s\n%P", | |
69 s->size, s->name, p); | |
70 } | |
71 | |
72 /* allocate elf guys - must be segregated from real data */ | |
73 datsize = 0; | |
74 for(i=0; i<NHASH; i++) | |
75 for(s = hash[i]; s != S; s = s->link) { | |
76 if(!s->reachable) | |
77 continue; | |
78 if(s->type != SELFDATA) | |
79 continue; | |
80 t = rnd(s->size, 4); | |
81 s->size = t; | |
82 s->value = datsize; | |
83 datsize += t; | |
84 } | |
85 elfdatsize = datsize; | |
86 | |
87 sect = addsection(&segdata, ".data", 06); | |
88 sect->vaddr = datsize; | |
89 | |
90 /* allocate small guys */ | |
91 for(i=0; i<NHASH; i++) | |
92 for(s = hash[i]; s != S; s = s->link) { | |
93 if(!s->reachable) | |
94 continue; | |
95 if(s->type != SDATA) | |
96 if(s->type != SBSS) | |
97 continue; | |
98 t = s->size; | |
99 if(t == 0 && s->name[0] != '.') { | |
100 diag("%s: no size", s->name); | |
101 t = 1; | |
102 } | |
103 t = rnd(t, 4); | |
104 s->size = t; | |
105 if(t > MINSIZ) | |
106 continue; | |
107 s->value = datsize; | |
108 datsize += t; | |
109 s->type = SDATA1; | |
110 } | |
111 | |
112 /* allocate the rest of the data */ | |
113 for(i=0; i<NHASH; i++) | |
114 for(s = hash[i]; s != S; s = s->link) { | |
115 if(s->type != SDATA) { | |
116 if(s->type == SDATA1) | |
117 s->type = SDATA; | |
118 continue; | |
119 } | |
120 t = s->size; | |
121 s->value = datsize; | |
122 datsize += t; | |
123 } | |
124 | |
125 if(debug['j']) { | |
126 /* | |
127 * pad data with bss that fits up to next | |
128 * 8k boundary, then push data to 8k | |
129 */ | |
130 u = rnd(datsize, 8192); | |
131 u -= datsize; | |
132 for(i=0; i<NHASH; i++) | |
133 for(s = hash[i]; s != S; s = s->link) { | |
134 if(!s->reachable) | |
135 continue; | |
136 if(s->type != SBSS) | |
137 continue; | |
138 t = s->value; | |
139 if(t > u) | |
140 continue; | |
141 u -= t; | |
142 s->size = t; | |
143 s->value = datsize; | |
144 s->type = SDATA; | |
145 datsize += t; | |
146 } | |
147 datsize += u; | |
148 } | |
149 | |
150 if(dynptrsize > 0) { | |
151 /* dynamic pointer section between data and bss */ | |
152 datsize = rnd(datsize, 4); | |
153 } | |
154 sect->len = datsize - sect->vaddr; | |
155 | |
156 /* now the bss */ | |
157 sect = addsection(&segdata, ".bss", 06); | |
158 sect->vaddr = datsize; | |
159 bsssize = 0; | |
160 for(i=0; i<NHASH; i++) | |
161 for(s = hash[i]; s != S; s = s->link) { | |
162 if(!s->reachable) | |
163 continue; | |
164 if(s->type != SBSS) | |
165 continue; | |
166 t = s->size; | |
167 s->value = bsssize + dynptrsize + datsize; | |
168 bsssize += t; | |
169 } | |
170 sect->len = bsssize; | |
171 | |
172 segdata.len = datsize+bsssize; | |
173 segdata.filelen = datsize; | |
174 | |
175 xdefine("data", SBSS, 0); | |
176 xdefine("edata", SBSS, datsize); | |
177 xdefine("end", SBSS, dynptrsize + bsssize + datsize); | |
178 | |
179 if(debug['s'] || HEADTYPE == 8) | |
180 xdefine("symdat", SFIXED, 0); | |
181 else | |
182 xdefine("symdat", SFIXED, SYMDATVA); | |
183 } | |
184 | 44 |
185 Prog* | 45 Prog* |
186 brchain(Prog *p) | 46 brchain(Prog *p) |
187 { | 47 { |
188 int i; | 48 int i; |
189 | 49 |
190 for(i=0; i<20; i++) { | 50 for(i=0; i<20; i++) { |
191 if(p == P || p->as != AJMP) | 51 if(p == P || p->as != AJMP) |
192 return p; | 52 return p; |
193 p = p->pcond; | 53 p = p->pcond; |
194 } | 54 } |
195 return P; | 55 return P; |
196 } | 56 } |
197 | 57 |
198 void | 58 void |
199 follow(void) | 59 follow(void) |
200 { | 60 { |
| 61 Prog *firstp, *lastp; |
201 | 62 |
202 if(debug['v']) | 63 if(debug['v']) |
203 Bprint(&bso, "%5.2f follow\n", cputime()); | 64 Bprint(&bso, "%5.2f follow\n", cputime()); |
204 Bflush(&bso); | 65 Bflush(&bso); |
205 » firstp = prg(); | 66 »······· |
206 » lastp = firstp; | 67 » for(cursym = textp; cursym != nil; cursym = cursym->next) { |
207 » xfol(textp); | 68 » » firstp = prg(); |
208 » lastp->link = P; | 69 » » lastp = firstp; |
209 » firstp = firstp->link; | 70 » » xfol(cursym->text, &lastp); |
210 } | 71 » » lastp->link = nil; |
211 | 72 » » cursym->text = firstp->link; |
212 void | 73 » } |
213 xfol(Prog *p) | 74 } |
| 75 |
| 76 static int |
| 77 nofollow(int a) |
| 78 { |
| 79 » switch(a) { |
| 80 » case AJMP: |
| 81 » case ARET: |
| 82 » case AIRETL: |
| 83 » case AIRETW: |
| 84 » » return 1; |
| 85 » } |
| 86 » return 0; |
| 87 } |
| 88 |
| 89 static int |
| 90 pushpop(int a) |
| 91 { |
| 92 » switch(a) { |
| 93 » case APUSHL: |
| 94 » case APUSHFL: |
| 95 » case APUSHW: |
| 96 » case APUSHFW: |
| 97 » case APOPL: |
| 98 » case APOPFL: |
| 99 » case APOPW: |
| 100 » case APOPFW: |
| 101 » » return 1; |
| 102 » } |
| 103 » return 0; |
| 104 } |
| 105 |
| 106 static void |
| 107 xfol(Prog *p, Prog **last) |
214 { | 108 { |
215 Prog *q; | 109 Prog *q; |
216 int i; | 110 int i; |
217 enum as a; | 111 enum as a; |
218 | 112 |
219 loop: | 113 loop: |
220 if(p == P) | 114 if(p == P) |
221 return; | 115 return; |
222 if(p->as == ATEXT) | |
223 curtext = p; | |
224 if(!curtext->from.sym->reachable) { | |
225 p = p->pcond; | |
226 goto loop; | |
227 } | |
228 if(p->as == AJMP) | 116 if(p->as == AJMP) |
229 if((q = p->pcond) != P && q->as != ATEXT) { | 117 if((q = p->pcond) != P && q->as != ATEXT) { |
| 118 /* mark instruction as done and continue layout at target of jum
p */ |
230 p->mark = 1; | 119 p->mark = 1; |
231 p = q; | 120 p = q; |
232 if(p->mark == 0) | 121 if(p->mark == 0) |
233 goto loop; | 122 goto loop; |
234 } | 123 } |
235 if(p->mark) { | 124 if(p->mark) { |
236 » » /* copy up to 4 instructions to avoid branch */ | 125 » » /*· |
| 126 » » * p goes here, but already used it elsewhere. |
| 127 » » * copy up to 4 instructions or else branch to other copy. |
| 128 » » */ |
237 for(i=0,q=p; i<4; i++,q=q->link) { | 129 for(i=0,q=p; i<4; i++,q=q->link) { |
238 if(q == P) | 130 if(q == P) |
239 break; | 131 break; |
240 » » » if(q == lastp) | 132 » » » if(q == *last) |
241 break; | 133 break; |
242 a = q->as; | 134 a = q->as; |
243 if(a == ANOP) { | 135 if(a == ANOP) { |
244 i--; | 136 i--; |
245 continue; | 137 continue; |
246 } | 138 } |
247 » » » switch(a) { | 139 » » » if(nofollow(a) || pushpop(a))»·· |
248 » » » case AJMP: | 140 » » » » break;» // NOTE(rsc): arm does goto copy |
249 » » » case ARET: | |
250 » » » case AIRETL: | |
251 | |
252 » » » case APUSHL: | |
253 » » » case APUSHFL: | |
254 » » » case APUSHW: | |
255 » » » case APUSHFW: | |
256 » » » case APOPL: | |
257 » » » case APOPFL: | |
258 » » » case APOPW: | |
259 » » » case APOPFW: | |
260 » » » » goto brk; | |
261 » » » } | |
262 if(q->pcond == P || q->pcond->mark) | 141 if(q->pcond == P || q->pcond->mark) |
263 continue; | 142 continue; |
264 if(a == ACALL || a == ALOOP) | 143 if(a == ACALL || a == ALOOP) |
265 continue; | 144 continue; |
266 for(;;) { | 145 for(;;) { |
267 if(p->as == ANOP) { | 146 if(p->as == ANOP) { |
268 p = p->link; | 147 p = p->link; |
269 continue; | 148 continue; |
270 } | 149 } |
271 q = copyp(p); | 150 q = copyp(p); |
272 p = p->link; | 151 p = p->link; |
273 q->mark = 1; | 152 q->mark = 1; |
274 » » » » lastp->link = q; | 153 » » » » (*last)->link = q; |
275 » » » » lastp = q; | 154 » » » » *last = q; |
276 if(q->as != a || q->pcond == P || q->pcond->mark
) | 155 if(q->as != a || q->pcond == P || q->pcond->mark
) |
277 continue; | 156 continue; |
278 | 157 |
279 q->as = relinv(q->as); | 158 q->as = relinv(q->as); |
280 p = q->pcond; | 159 p = q->pcond; |
281 q->pcond = q->link; | 160 q->pcond = q->link; |
282 q->link = p; | 161 q->link = p; |
283 » » » » xfol(q->link); | 162 » » » » xfol(q->link, last); |
284 p = q->link; | 163 p = q->link; |
285 if(p->mark) | 164 if(p->mark) |
286 return; | 165 return; |
287 goto loop; | 166 goto loop; |
288 } | 167 } |
289 } /* */ | 168 } /* */ |
290 brk:; | |
291 q = prg(); | 169 q = prg(); |
292 q->as = AJMP; | 170 q->as = AJMP; |
293 q->line = p->line; | 171 q->line = p->line; |
294 q->to.type = D_BRANCH; | 172 q->to.type = D_BRANCH; |
295 q->to.offset = p->pc; | 173 q->to.offset = p->pc; |
296 q->pcond = p; | 174 q->pcond = p; |
297 p = q; | 175 p = q; |
298 } | 176 } |
| 177 ········ |
| 178 /* emit p */ |
299 p->mark = 1; | 179 p->mark = 1; |
300 » lastp->link = p; | 180 » (*last)->link = p; |
301 » lastp = p; | 181 » *last = p; |
302 a = p->as; | 182 a = p->as; |
303 » if(a == AJMP || a == ARET || a == AIRETL) | 183 |
| 184 » /* continue loop with what comes after p */ |
| 185 » if(nofollow(a)) |
304 return; | 186 return; |
305 » if(p->pcond != P) | 187 » if(p->pcond != P && a != ACALL) { |
306 » if(a != ACALL) { | 188 » » /* |
| 189 » » * some kind of conditional branch. |
| 190 » » * recurse to follow one path. |
| 191 » » * continue loop on the other. |
| 192 » » */ |
307 q = brchain(p->link); | 193 q = brchain(p->link); |
308 if(q != P && q->mark) | 194 if(q != P && q->mark) |
309 » » if(a != ALOOP && a != ATEXT) { | 195 » » if(a != ALOOP) { |
310 p->as = relinv(a); | 196 p->as = relinv(a); |
311 p->link = p->pcond; | 197 p->link = p->pcond; |
312 p->pcond = q; | 198 p->pcond = q; |
313 } | 199 } |
314 » » xfol(p->link); | 200 » » xfol(p->link, last); |
315 q = brchain(p->pcond); | 201 q = brchain(p->pcond); |
316 if(q->mark) { | 202 if(q->mark) { |
317 p->pcond = q; | 203 p->pcond = q; |
318 return; | 204 return; |
319 } | 205 } |
320 p = q; | 206 p = q; |
321 goto loop; | 207 goto loop; |
322 } | 208 } |
323 p = p->link; | 209 p = p->link; |
324 goto loop; | 210 goto loop; |
(...skipping 19 matching lines...) Expand all Loading... |
344 case AJPS: return AJPC; | 230 case AJPS: return AJPC; |
345 case AJPC: return AJPS; | 231 case AJPC: return AJPS; |
346 case AJOS: return AJOC; | 232 case AJOS: return AJOC; |
347 case AJOC: return AJOS; | 233 case AJOC: return AJOS; |
348 } | 234 } |
349 diag("unknown relation: %s in %s", anames[a], TNAME); | 235 diag("unknown relation: %s in %s", anames[a], TNAME); |
350 return a; | 236 return a; |
351 } | 237 } |
352 | 238 |
353 void | 239 void |
354 doinit(void) | |
355 { | |
356 Sym *s; | |
357 Prog *p; | |
358 int x; | |
359 | |
360 for(p = datap; p != P; p = p->link) { | |
361 x = p->to.type; | |
362 if(x != D_EXTERN && x != D_STATIC) | |
363 continue; | |
364 s = p->to.sym; | |
365 if(s->type == 0 || s->type == SXREF) | |
366 diag("undefined %s initializer of %s", | |
367 s->name, p->from.sym->name); | |
368 p->to.offset += s->value; | |
369 p->to.type = D_CONST; | |
370 if(s->type == SDATA || s->type == SBSS) | |
371 p->to.offset += INITDAT; | |
372 } | |
373 } | |
374 | |
375 void | |
376 patch(void) | 240 patch(void) |
377 { | 241 { |
378 int32 c; | 242 int32 c; |
379 Prog *p, *q; | 243 Prog *p, *q; |
380 Sym *s; | 244 Sym *s; |
381 int32 vexit; | 245 int32 vexit; |
382 | 246 |
383 if(debug['v']) | 247 if(debug['v']) |
384 Bprint(&bso, "%5.2f mkfwd\n", cputime()); | 248 Bprint(&bso, "%5.2f mkfwd\n", cputime()); |
385 Bflush(&bso); | 249 Bflush(&bso); |
386 mkfwd(); | 250 mkfwd(); |
387 if(debug['v']) | 251 if(debug['v']) |
388 Bprint(&bso, "%5.2f patch\n", cputime()); | 252 Bprint(&bso, "%5.2f patch\n", cputime()); |
389 Bflush(&bso); | 253 Bflush(&bso); |
390 s = lookup("exit", 0); | 254 s = lookup("exit", 0); |
391 vexit = s->value; | 255 vexit = s->value; |
392 » for(p = firstp; p != P; p = p->link) { | 256 » for(cursym = textp; cursym != nil; cursym = cursym->next) { |
393 » » if(HEADTYPE == 10) {» // Windows | 257 » » for(p = cursym->text; p != P; p = p->link) { |
394 » » » // Convert | 258 » » » if(HEADTYPE == 10) {» // Windows |
395 » » » // op» n(GS), reg | 259 » » » » // Convert |
396 » » » // to | 260 » » » » // op» n(GS), reg |
397 » » » // MOVL 0x2C(FS), reg | 261 » » » » // to |
398 » » » // op» n(reg), reg | 262 » » » » // MOVL 0x2C(FS), reg |
399 » » » // The purpose of this patch is to fix some accesses | 263 » » » » // op» n(reg), reg |
400 » » » // to extern register variables (TLS) on Windows, as | 264 » » » » // The purpose of this patch is to fix some acce
sses |
401 » » » // a different method is used to access them. | 265 » » » » // to extern register variables (TLS) on Windows
, as |
402 » » » if(p->from.type == D_INDIR+D_GS | 266 » » » » // a different method is used to access them. |
403 » » » && p->to.type >= D_AX && p->to.type <= D_DI) { | 267 » » » » if(p->from.type == D_INDIR+D_GS |
404 » » » » q = appendp(p); | 268 » » » » && p->to.type >= D_AX && p->to.type <= D_DI) { |
405 » » » » q->from = p->from; | 269 » » » » » q = appendp(p); |
406 » » » » q->from.type = D_INDIR + p->to.type; | 270 » » » » » q->from = p->from; |
407 » » » » q->to = p->to; | 271 » » » » » q->from.type = D_INDIR + p->to.type; |
408 » » » » q->as = p->as; | 272 » » » » » q->to = p->to; |
409 » » » » p->as = AMOVL; | 273 » » » » » q->as = p->as; |
410 » » » » p->from.type = D_INDIR+D_FS; | 274 » » » » » p->as = AMOVL; |
411 » » » » p->from.offset = 0x2C; | 275 » » » » » p->from.type = D_INDIR+D_FS; |
412 » » » } | 276 » » » » » p->from.offset = 0x2C; |
| 277 » » » » } |
| 278 » » » } |
| 279 » » » if(HEADTYPE == 7) {» // Linux |
| 280 » » » » // Running binaries under Xen requires using |
| 281 » » » » //» MOVL 0(GS), reg |
| 282 » » » » // and then off(reg) instead of saying off(GS) d
irectly |
| 283 » » » » // when the offset is negative. |
| 284 » » » » if(p->from.type == D_INDIR+D_GS && p->from.offse
t < 0 |
| 285 » » » » && p->to.type >= D_AX && p->to.type <= D_DI) { |
| 286 » » » » » q = appendp(p); |
| 287 » » » » » q->from = p->from; |
| 288 » » » » » q->from.type = D_INDIR + p->to.type; |
| 289 » » » » » q->to = p->to; |
| 290 » » » » » q->as = p->as; |
| 291 » » » » » p->as = AMOVL; |
| 292 » » » » » p->from.type = D_INDIR+D_GS; |
| 293 » » » » » p->from.offset = 0; |
| 294 » » » » } |
| 295 » » » } |
| 296 » » » if(HEADTYPE == 2) {» // Plan 9 |
| 297 » » » » if(p->from.type == D_INDIR+D_GS |
| 298 » » » » && p->to.type >= D_AX && p->to.type <= D_DI) { |
| 299 » » » » » p->as = AMOVL; |
| 300 » » » » » p->from.type = D_ADDR+D_STATIC; |
| 301 » » » » » p->from.offset += 0xdfffefc0; |
| 302 » » » » } |
| 303 » » » } |
| 304 » » » if(p->as == ACALL || (p->as == AJMP && p->to.type != D_B
RANCH)) { |
| 305 » » » » s = p->to.sym; |
| 306 » » » » if(s) { |
| 307 » » » » » if(debug['c']) |
| 308 » » » » » » Bprint(&bso, "%s calls %s\n", TN
AME, s->name); |
| 309 » » » » » switch(s->type) { |
| 310 » » » » » default: |
| 311 » » » » » » /* diag prints TNAME first */ |
| 312 » » » » » » diag("undefined: %s", s->name); |
| 313 » » » » » » s->type = STEXT; |
| 314 » » » » » » s->value = vexit; |
| 315 » » » » » » continue;» // avoid more er
ror messages |
| 316 » » » » » case STEXT: |
| 317 » » » » » » p->to.offset = s->value; |
| 318 » » » » » » break; |
| 319 » » » » » } |
| 320 » » » » » p->to.type = D_BRANCH; |
| 321 » » » » } |
| 322 » » » } |
| 323 » » » if(p->to.type != D_BRANCH) |
| 324 » » » » continue; |
| 325 » » » c = p->to.offset; |
| 326 » » » for(q = textp->text; q != P;) { |
| 327 » » » » if(c == q->pc) |
| 328 » » » » » break; |
| 329 » » » » if(q->forwd != P && c >= q->forwd->pc) |
| 330 » » » » » q = q->forwd; |
| 331 » » » » else |
| 332 » » » » » q = q->link; |
| 333 » » » } |
| 334 » » » if(q == P) { |
| 335 » » » » diag("branch out of range in %s\n%P", TNAME, p); |
| 336 » » » » p->to.type = D_NONE; |
| 337 » » » } |
| 338 » » » p->pcond = q; |
413 } | 339 } |
414 » » if(HEADTYPE == 7) {» // Linux | 340 » } |
415 » » » // Running binaries under Xen requires using | 341 |
416 » » » //» MOVL 0(GS), reg | 342 » for(cursym = textp; cursym != nil; cursym = cursym->next) { |
417 » » » // and then off(reg) instead of saying off(GS) directly | 343 » » for(p = cursym->text; p != P; p = p->link) { |
418 » » » // when the offset is negative. | 344 » » » p->mark = 0;» /* initialization for follow */ |
419 » » » if(p->from.type == D_INDIR+D_GS && p->from.offset < 0 | 345 » » » if(p->pcond != P) { |
420 » » » && p->to.type >= D_AX && p->to.type <= D_DI) { | 346 » » » » p->pcond = brloop(p->pcond); |
421 » » » » q = appendp(p); | 347 » » » » if(p->pcond != P) |
422 » » » » q->from = p->from; | 348 » » » » if(p->to.type == D_BRANCH) |
423 » » » » q->from.type = D_INDIR + p->to.type; | 349 » » » » » p->to.offset = p->pcond->pc; |
424 » » » » q->to = p->to; | 350 » » » } |
425 » » » » q->as = p->as; | |
426 » » » » p->as = AMOVL; | |
427 » » » » p->from.type = D_INDIR+D_GS; | |
428 » » » » p->from.offset = 0; | |
429 » » » } | |
430 » » } | |
431 » » if(HEADTYPE == 2) {» // Plan 9 | |
432 » » » if(p->from.type == D_INDIR+D_GS | |
433 » » » && p->to.type >= D_AX && p->to.type <= D_DI) { | |
434 » » » » p->as = AMOVL; | |
435 » » » » p->from.type = D_ADDR+D_STATIC; | |
436 » » » » p->from.offset += 0xdfffefc0; | |
437 » » » } | |
438 » » }················ | |
439 » » if(p->as == ATEXT) | |
440 » » » curtext = p; | |
441 » » if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH))
{ | |
442 » » » s = p->to.sym; | |
443 » » » if(s) { | |
444 » » » » if(debug['c']) | |
445 » » » » » Bprint(&bso, "%s calls %s\n", TNAME, s->
name); | |
446 » » » » switch(s->type) { | |
447 » » » » default: | |
448 » » » » » /* diag prints TNAME first */ | |
449 » » » » » diag("undefined: %s", s->name); | |
450 » » » » » s->type = STEXT; | |
451 » » » » » s->value = vexit; | |
452 » » » » » continue;» // avoid more error mess
ages | |
453 » » » » case STEXT: | |
454 » » » » » p->to.offset = s->value; | |
455 » » » » » break; | |
456 » » » » case SUNDEF: | |
457 » » » » » p->pcond = UP; | |
458 » » » » » p->to.offset = 0; | |
459 » » » » » break; | |
460 » » » » } | |
461 » » » » p->to.type = D_BRANCH; | |
462 » » » } | |
463 » » } | |
464 » » if(p->to.type != D_BRANCH || p->pcond == UP) | |
465 » » » continue; | |
466 » » c = p->to.offset; | |
467 » » for(q = firstp; q != P;) { | |
468 » » » if(q->forwd != P) | |
469 » » » if(c >= q->forwd->pc) { | |
470 » » » » q = q->forwd; | |
471 » » » » continue; | |
472 » » » } | |
473 » » » if(c == q->pc) | |
474 » » » » break; | |
475 » » » q = q->link; | |
476 » » } | |
477 » » if(q == P) { | |
478 » » » diag("branch out of range in %s\n%P", TNAME, p); | |
479 » » » p->to.type = D_NONE; | |
480 » » } | |
481 » » p->pcond = q; | |
482 » } | |
483 | |
484 » for(p = firstp; p != P; p = p->link) { | |
485 » » if(p->as == ATEXT) | |
486 » » » curtext = p; | |
487 » » p->mark = 0;» /* initialization for follow */ | |
488 » » if(p->pcond != P && p->pcond != UP) { | |
489 » » » p->pcond = brloop(p->pcond); | |
490 » » » if(p->pcond != P) | |
491 » » » if(p->to.type == D_BRANCH) | |
492 » » » » p->to.offset = p->pcond->pc; | |
493 » » } | |
494 » } | |
495 } | |
496 | |
497 #define»LOG» 5 | |
498 void | |
499 mkfwd(void) | |
500 { | |
501 » Prog *p; | |
502 » int i; | |
503 » int32 dwn[LOG], cnt[LOG]; | |
504 » Prog *lst[LOG]; | |
505 | |
506 » for(i=0; i<LOG; i++) { | |
507 » » if(i == 0) | |
508 » » » cnt[i] = 1; else | |
509 » » » cnt[i] = LOG * cnt[i-1]; | |
510 » » dwn[i] = 1; | |
511 » » lst[i] = P; | |
512 » } | |
513 » i = 0; | |
514 » for(p = firstp; p != P; p = p->link) { | |
515 » » if(p->as == ATEXT) | |
516 » » » curtext = p; | |
517 » » i--; | |
518 » » if(i < 0) | |
519 » » » i = LOG-1; | |
520 » » p->forwd = P; | |
521 » » dwn[i]--; | |
522 » » if(dwn[i] <= 0) { | |
523 » » » dwn[i] = cnt[i]; | |
524 » » » if(lst[i] != P) | |
525 » » » » lst[i]->forwd = p; | |
526 » » » lst[i] = p; | |
527 } | 351 } |
528 } | 352 } |
529 } | 353 } |
530 | 354 |
531 Prog* | 355 Prog* |
532 brloop(Prog *p) | 356 brloop(Prog *p) |
533 { | 357 { |
534 int c; | 358 int c; |
535 Prog *q; | 359 Prog *q; |
536 | 360 |
537 c = 0; | 361 c = 0; |
538 for(q = p; q != P; q = q->pcond) { | 362 for(q = p; q != P; q = q->pcond) { |
539 if(q->as != AJMP) | 363 if(q->as != AJMP) |
540 break; | 364 break; |
541 c++; | 365 c++; |
542 if(c >= 5000) | 366 if(c >= 5000) |
543 return P; | 367 return P; |
544 } | 368 } |
545 return q; | 369 return q; |
546 } | 370 } |
547 | 371 |
548 void | 372 void |
549 dostkoff(void) | 373 dostkoff(void) |
550 { | 374 { |
551 Prog *p, *q, *q1; | 375 Prog *p, *q, *q1; |
552 int32 autoffset, deltasp; | 376 int32 autoffset, deltasp; |
553 » int a, f, curframe, curbecome, maxbecome; | 377 » int a; |
554 Prog *pmorestack; | 378 Prog *pmorestack; |
555 Sym *symmorestack; | 379 Sym *symmorestack; |
556 | 380 |
557 pmorestack = P; | 381 pmorestack = P; |
558 symmorestack = lookup("runtime.morestack", 0); | 382 symmorestack = lookup("runtime.morestack", 0); |
559 | 383 |
560 » if(symmorestack->type == STEXT) | 384 » if(symmorestack->type != STEXT) |
561 » for(p = firstp; p != P; p = p->link) { | 385 » » diag("runtime.morestack not defined"); |
562 » » if(p->as == ATEXT) { | 386 » else { |
563 » » » if(p->from.sym == symmorestack) { | 387 » » pmorestack = symmorestack->text; |
564 » » » » pmorestack = p; | 388 » » symmorestack->text->from.scale |= NOSPLIT; |
565 » » » » p->from.scale |= NOSPLIT; | 389 » } |
| 390 |
| 391 » for(cursym = textp; cursym != nil; cursym = cursym->next) { |
| 392 » » p = cursym->text; |
| 393 |
| 394 » » autoffset = p->to.offset; |
| 395 » » if(autoffset < 0) |
| 396 » » » autoffset = 0; |
| 397 |
| 398 » » q = P; |
| 399 » » q1 = P; |
| 400 » » if(pmorestack != P) |
| 401 » » if(!(p->from.scale & NOSPLIT)) { |
| 402 » » » p = appendp(p);»// load g into CX |
| 403 » » » switch(HEADTYPE) { |
| 404 » » » case 10:» // Windows |
| 405 » » » » p->as = AMOVL; |
| 406 » » » » p->from.type = D_INDIR+D_FS; |
| 407 » » » » p->from.offset = 0x2c; |
| 408 » » » » p->to.type = D_CX; |
| 409 |
| 410 » » » » p = appendp(p); |
| 411 » » » » p->as = AMOVL; |
| 412 » » » » p->from.type = D_INDIR+D_CX; |
| 413 » » » » p->from.offset = 0; |
| 414 » » » » p->to.type = D_CX; |
566 break; | 415 break; |
567 » » » } | 416 » » »······· |
568 » » } | 417 » » » case 7:»// Linux |
569 » } | 418 » » » » p->as = AMOVL; |
570 » if(pmorestack == P) | 419 » » » » p->from.type = D_INDIR+D_GS; |
571 » » diag("runtime.morestack not defined"); | 420 » » » » p->from.offset = 0; |
572 | 421 » » » » p->to.type = D_CX; |
573 » curframe = 0; | 422 |
574 » curbecome = 0; | 423 » » » » p = appendp(p); |
575 » maxbecome = 0; | 424 » » » » p->as = AMOVL; |
576 » curtext = 0; | 425 » » » » p->from.type = D_INDIR+D_CX; |
577 » for(p = firstp; p != P; p = p->link) { | 426 » » » » p->from.offset = tlsoffset + 0; |
578 | 427 » » » » p->to.type = D_CX; |
579 » » /* find out how much arg space is used in this TEXT */ | 428 » » » » break; |
580 » » if(p->to.type == (D_INDIR+D_SP)) | 429 » » »······· |
581 » » » if(p->to.offset > curframe) | 430 » » » case 2:»// Plan 9 |
582 » » » » curframe = p->to.offset; | 431 » » » » p->as = AMOVL; |
583 | 432 » » » » p->from.type = D_ADDR+D_STATIC; |
584 » » switch(p->as) { | 433 » » » » p->from.offset = 0xdfffefc0; |
585 » » case ATEXT: | 434 » » » » p->to.type = D_CX; |
586 » » » if(curtext && curtext->from.sym) { | 435 » » » » break; |
587 » » » » curtext->from.sym->frame = curframe; | 436 » » »······· |
588 » » » » curtext->from.sym->become = curbecome; | 437 » » » default: |
589 » » » » if(curbecome > maxbecome) | 438 » » » » p->as = AMOVL; |
590 » » » » » maxbecome = curbecome; | 439 » » » » p->from.type = D_INDIR+D_GS; |
591 » » » } | 440 » » » » p->from.offset = tlsoffset + 0; |
592 » » » curframe = 0; | 441 » » » » p->to.type = D_CX; |
593 » » » curbecome = 0; | 442 » » » } |
594 | 443 |
595 » » » curtext = p; | 444 » » » if(debug['K']) { |
596 » » » break; | 445 » » » » // 8l -K means check not only for stack |
597 | 446 » » » » // overflow but stack underflow. |
598 » » case ARET: | 447 » » » » // On underflow, INT 3 (breakpoint). |
599 » » » /* special form of RET is BECOME */ | 448 » » » » // Underflow itself is rare but this also |
600 » » » if(p->from.type == D_CONST) | 449 » » » » // catches out-of-sync stack guard info. |
601 » » » » if(p->from.offset > curbecome) | 450 » » » » p = appendp(p); |
602 » » » » » curbecome = p->from.offset; | 451 » » » » p->as = ACMPL; |
603 » » » break; | 452 » » » » p->from.type = D_INDIR+D_CX; |
604 » » } | 453 » » » » p->from.offset = 4; |
605 » } | 454 » » » » p->to.type = D_SP; |
606 » if(curtext && curtext->from.sym) { | 455 |
607 » » curtext->from.sym->frame = curframe; | 456 » » » » p = appendp(p); |
608 » » curtext->from.sym->become = curbecome; | 457 » » » » p->as = AJCC; |
609 » » if(curbecome > maxbecome) | 458 » » » » p->to.type = D_BRANCH; |
610 » » » maxbecome = curbecome; | 459 » » » » p->to.offset = 4; |
611 » } | 460 » » » » q1 = p; |
612 | 461 |
613 » if(debug['b']) | 462 » » » » p = appendp(p); |
614 » » print("max become = %d\n", maxbecome); | 463 » » » » p->as = AINT; |
615 » xdefine("ALEFbecome", STEXT, maxbecome); | 464 » » » » p->from.type = D_CONST; |
616 | 465 » » » » p->from.offset = 3; |
617 » curtext = 0; | |
618 » for(p = firstp; p != P; p = p->link) { | |
619 » » switch(p->as) { | |
620 » » case ATEXT: | |
621 » » » curtext = p; | |
622 » » » break; | |
623 » » case ACALL: | |
624 » » » if(curtext != P && curtext->from.sym != S && curtext->to
.offset >= 0) { | |
625 » » » » f = maxbecome - curtext->from.sym->frame; | |
626 » » » » if(f <= 0) | |
627 » » » » » break; | |
628 » » » » /* calling a become or calling a variable */ | |
629 » » » » if(p->to.sym == S || p->to.sym->become) { | |
630 » » » » » curtext->to.offset += f; | |
631 » » » » » if(debug['b']) { | |
632 » » » » » » curp = p; | |
633 » » » » » » print("%D calling %D increase %d
\n", | |
634 » » » » » » » &curtext->from, &p->to,
f); | |
635 » » » » » } | |
636 » » » » } | |
637 » » » } | |
638 » » » break; | |
639 » » } | |
640 » } | |
641 | |
642 » autoffset = 0; | |
643 » deltasp = 0; | |
644 » for(p = firstp; p != P; p = p->link) { | |
645 » » if(p->as == ATEXT) { | |
646 » » » curtext = p; | |
647 » » » autoffset = p->to.offset; | |
648 » » » if(autoffset < 0) | |
649 » » » » autoffset = 0; | |
650 | |
651 » » » q = P; | |
652 » » » q1 = P; | |
653 » » » if(pmorestack != P) | |
654 » » » if(!(p->from.scale & NOSPLIT)) { | |
655 » » » » p = appendp(p);»// load g into CX | |
656 » » » » switch(HEADTYPE) { | |
657 » » » » case 10:» // Windows | |
658 » » » » » p->as = AMOVL; | |
659 » » » » » p->from.type = D_INDIR+D_FS; | |
660 » » » » » p->from.offset = 0x2c; | |
661 » » » » » p->to.type = D_CX; | |
662 | |
663 » » » » » p = appendp(p); | |
664 » » » » » p->as = AMOVL; | |
665 » » » » » p->from.type = D_INDIR+D_CX; | |
666 » » » » » p->from.offset = 0; | |
667 » » » » » p->to.type = D_CX; | |
668 » » » » » break; | |
669 ································ | 466 ································ |
670 » » » » case 7:»// Linux | 467 » » » » p = appendp(p); |
671 » » » » » p->as = AMOVL; | 468 » » » » p->as = ANOP; |
672 » » » » » p->from.type = D_INDIR+D_GS; | 469 » » » » q1->pcond = p; |
673 » » » » » p->from.offset = 0; | 470 » » » } |
674 » » » » » p->to.type = D_CX; | 471 |
675 | 472 » » » if(autoffset < StackBig) { // do we need to call morest
ack |
676 » » » » » p = appendp(p); | 473 » » » » if(autoffset <= StackSmall) { |
677 » » » » » p->as = AMOVL; | 474 » » » » » // small stack |
678 » » » » » p->from.type = D_INDIR+D_CX; | |
679 » » » » » p->from.offset = tlsoffset + 0; | |
680 » » » » » p->to.type = D_CX; | |
681 » » » » » break; | |
682 » » » »······· | |
683 » » » » case 2:»// Plan 9 | |
684 » » » » » p->as = AMOVL; | |
685 » » » » » p->from.type = D_ADDR+D_STATIC; | |
686 » » » » » p->from.offset = 0xdfffefc0; | |
687 » » » » » p->to.type = D_CX; | |
688 » » » » » break; | |
689 | |
690 » » » » default: | |
691 » » » » » p->as = AMOVL; | |
692 » » » » » p->from.type = D_INDIR+D_GS; | |
693 » » » » » p->from.offset = tlsoffset + 0; | |
694 » » » » » p->to.type = D_CX; | |
695 » » » » } | |
696 | |
697 » » » » if(debug['K']) { | |
698 » » » » » // 8l -K means check not only for stack | |
699 » » » » » // overflow but stack underflow. | |
700 » » » » » // On underflow, INT 3 (breakpoint). | |
701 » » » » » // Underflow itself is rare but this als
o | |
702 » » » » » // catches out-of-sync stack guard info. | |
703 p = appendp(p); | 475 p = appendp(p); |
704 p->as = ACMPL; | 476 p->as = ACMPL; |
705 » » » » » p->from.type = D_INDIR+D_CX; | 477 » » » » » p->from.type = D_SP; |
706 » » » » » p->from.offset = 4; | 478 » » » » » p->to.type = D_INDIR+D_CX; |
707 » » » » » p->to.type = D_SP; | 479 » » » » } else { |
708 | 480 » » » » » // large stack |
709 p = appendp(p); | 481 p = appendp(p); |
710 » » » » » p->as = AJCC; | 482 » » » » » p->as = ALEAL; |
711 » » » » » p->to.type = D_BRANCH; | 483 » » » » » p->from.type = D_INDIR+D_SP; |
712 » » » » » p->to.offset = 4; | 484 » » » » » p->from.offset = -(autoffset-StackSmall)
; |
713 » » » » » q1 = p; | 485 » » » » » p->to.type = D_AX; |
714 | 486 |
715 p = appendp(p); | 487 p = appendp(p); |
716 » » » » » p->as = AINT; | 488 » » » » » p->as = ACMPL; |
717 » » » » » p->from.type = D_CONST; | 489 » » » » » p->from.type = D_AX; |
718 » » » » » p->from.offset = 3; | 490 » » » » » p->to.type = D_INDIR+D_CX; |
719 » » » » »······· | |
720 » » » » » p = appendp(p); | |
721 » » » » » p->as = ANOP; | |
722 » » » » » q1->pcond = p; | |
723 } | 491 } |
724 | 492 |
725 » » » » if(autoffset < StackBig) { // do we need to cal
l morestack | 493 » » » » // common |
726 » » » » » if(autoffset <= StackSmall) { | 494 » » » » p = appendp(p); |
727 » » » » » » // small stack | 495 » » » » p->as = AJHI; |
728 » » » » » » p = appendp(p); | |
729 » » » » » » p->as = ACMPL; | |
730 » » » » » » p->from.type = D_SP; | |
731 » » » » » » p->to.type = D_INDIR+D_CX; | |
732 » » » » » } else { | |
733 » » » » » » // large stack | |
734 » » » » » » p = appendp(p); | |
735 » » » » » » p->as = ALEAL; | |
736 » » » » » » p->from.type = D_INDIR+D_SP; | |
737 » » » » » » p->from.offset = -(autoffset-Sta
ckSmall); | |
738 » » » » » » p->to.type = D_AX; | |
739 | |
740 » » » » » » p = appendp(p); | |
741 » » » » » » p->as = ACMPL; | |
742 » » » » » » p->from.type = D_AX; | |
743 » » » » » » p->to.type = D_INDIR+D_CX; | |
744 » » » » » } | |
745 | |
746 » » » » » // common | |
747 » » » » » p = appendp(p); | |
748 » » » » » p->as = AJHI; | |
749 » » » » » p->to.type = D_BRANCH; | |
750 » » » » » p->to.offset = 4; | |
751 » » » » » q = p; | |
752 » » » » } | |
753 | |
754 » » » » p = appendp(p);»// save frame size in DX | |
755 » » » » p->as = AMOVL; | |
756 » » » » p->to.type = D_DX; | |
757 » » » » /* 160 comes from 3 calls (3*8) 4 safes (4*8) an
d 104 guard */ | |
758 » » » » p->from.type = D_CONST; | |
759 » » » » if(autoffset+160 > 4096) | |
760 » » » » » p->from.offset = (autoffset+160) & ~7LL; | |
761 | |
762 » » » » p = appendp(p);»// save arg size in AX | |
763 » » » » p->as = AMOVL; | |
764 » » » » p->to.type = D_AX; | |
765 » » » » p->from.type = D_CONST; | |
766 » » » » p->from.offset = curtext->to.offset2; | |
767 | |
768 » » » » p = appendp(p); | |
769 » » » » p->as = ACALL; | |
770 p->to.type = D_BRANCH; | 496 p->to.type = D_BRANCH; |
771 » » » » p->pcond = pmorestack; | 497 » » » » p->to.offset = 4; |
772 » » » » p->to.sym = symmorestack; | 498 » » » » q = p; |
773 | 499 » » » } |
774 » » » } | 500 |
775 | 501 » » » p = appendp(p);»// save frame size in DX |
| 502 » » » p->as = AMOVL; |
| 503 » » » p->to.type = D_DX; |
| 504 » » » /* 160 comes from 3 calls (3*8) 4 safes (4*8) and 104 gu
ard */ |
| 505 » » » p->from.type = D_CONST; |
| 506 » » » if(autoffset+160 > 4096) |
| 507 » » » » p->from.offset = (autoffset+160) & ~7LL; |
| 508 |
| 509 » » » p = appendp(p);»// save arg size in AX |
| 510 » » » p->as = AMOVL; |
| 511 » » » p->to.type = D_AX; |
| 512 » » » p->from.type = D_CONST; |
| 513 » » » p->from.offset = cursym->text->to.offset2; |
| 514 |
| 515 » » » p = appendp(p); |
| 516 » » » p->as = ACALL; |
| 517 » » » p->to.type = D_BRANCH; |
| 518 » » » p->pcond = pmorestack; |
| 519 » » » p->to.sym = symmorestack; |
| 520 |
| 521 » » } |
| 522 |
| 523 » » if(q != P) |
| 524 » » » q->pcond = p->link; |
| 525 |
| 526 » » if(autoffset) { |
| 527 » » » p = appendp(p); |
| 528 » » » p->as = AADJSP; |
| 529 » » » p->from.type = D_CONST; |
| 530 » » » p->from.offset = autoffset; |
| 531 » » » p->spadj = autoffset; |
776 if(q != P) | 532 if(q != P) |
777 » » » » q->pcond = p->link; | 533 » » » » q->pcond = p; |
778 | 534 » » } |
| 535 » » deltasp = autoffset; |
| 536 » »······· |
| 537 » » for(; p != P; p = p->link) { |
| 538 » » » a = p->from.type; |
| 539 » » » if(a == D_AUTO) |
| 540 » » » » p->from.offset += deltasp; |
| 541 » » » if(a == D_PARAM) |
| 542 » » » » p->from.offset += deltasp + 4; |
| 543 » » » a = p->to.type; |
| 544 » » » if(a == D_AUTO) |
| 545 » » » » p->to.offset += deltasp; |
| 546 » » » if(a == D_PARAM) |
| 547 » » » » p->to.offset += deltasp + 4; |
| 548 »······· |
| 549 » » » switch(p->as) { |
| 550 » » » default: |
| 551 » » » » continue; |
| 552 » » » case APUSHL: |
| 553 » » » case APUSHFL: |
| 554 » » » » deltasp += 4; |
| 555 » » » » p->spadj = 4; |
| 556 » » » » continue; |
| 557 » » » case APUSHW: |
| 558 » » » case APUSHFW: |
| 559 » » » » deltasp += 2; |
| 560 » » » » p->spadj = 2; |
| 561 » » » » continue; |
| 562 » » » case APOPL: |
| 563 » » » case APOPFL: |
| 564 » » » » deltasp -= 4; |
| 565 » » » » p->spadj = -4; |
| 566 » » » » continue; |
| 567 » » » case APOPW: |
| 568 » » » case APOPFW: |
| 569 » » » » deltasp -= 2; |
| 570 » » » » p->spadj = -2; |
| 571 » » » » continue; |
| 572 » » » case ARET: |
| 573 » » » » break; |
| 574 » » » } |
| 575 »······· |
| 576 » » » if(autoffset != deltasp) |
| 577 » » » » diag("unbalanced PUSH/POP"); |
| 578 »······· |
779 if(autoffset) { | 579 if(autoffset) { |
780 » » » » p = appendp(p); | 580 » » » » q = p; |
781 » » » » p->as = AADJSP; | 581 » » » » p = appendp(p); |
782 » » » » p->from.type = D_CONST; | 582 » » » » p->as = ARET; |
783 » » » » p->from.offset = autoffset; | 583 »······· |
784 » » » » p->spadj = autoffset; | 584 » » » » q->as = AADJSP; |
785 » » » » if(q != P) | 585 » » » » q->from.type = D_CONST; |
786 » » » » » q->pcond = p; | 586 » » » » q->from.offset = -autoffset; |
787 » » » } | 587 » » » » p->spadj = -autoffset; |
788 » » » deltasp = autoffset; | 588 » » » } |
789 } | 589 } |
790 a = p->from.type; | |
791 if(a == D_AUTO) | |
792 p->from.offset += deltasp; | |
793 if(a == D_PARAM) | |
794 p->from.offset += deltasp + 4; | |
795 a = p->to.type; | |
796 if(a == D_AUTO) | |
797 p->to.offset += deltasp; | |
798 if(a == D_PARAM) | |
799 p->to.offset += deltasp + 4; | |
800 | |
801 switch(p->as) { | |
802 default: | |
803 continue; | |
804 case APUSHL: | |
805 case APUSHFL: | |
806 deltasp += 4; | |
807 p->spadj = 4; | |
808 continue; | |
809 case APUSHW: | |
810 case APUSHFW: | |
811 deltasp += 2; | |
812 p->spadj = 2; | |
813 continue; | |
814 case APOPL: | |
815 case APOPFL: | |
816 deltasp -= 4; | |
817 p->spadj = -4; | |
818 continue; | |
819 case APOPW: | |
820 case APOPFW: | |
821 deltasp -= 2; | |
822 p->spadj = -2; | |
823 continue; | |
824 case ARET: | |
825 break; | |
826 } | |
827 | |
828 if(autoffset != deltasp) | |
829 diag("unbalanced PUSH/POP"); | |
830 if(p->from.type == D_CONST) | |
831 goto become; | |
832 | |
833 if(autoffset) { | |
834 q = p; | |
835 p = appendp(p); | |
836 p->as = ARET; | |
837 | |
838 q->as = AADJSP; | |
839 q->from.type = D_CONST; | |
840 q->from.offset = -autoffset; | |
841 p->spadj = -autoffset; | |
842 } | |
843 continue; | |
844 | |
845 become: | |
846 q = p; | |
847 p = appendp(p); | |
848 p->as = AJMP; | |
849 p->to = q->to; | |
850 p->pcond = q->pcond; | |
851 | |
852 q->as = AADJSP; | |
853 q->from = zprg.from; | |
854 q->from.type = D_CONST; | |
855 q->from.offset = -autoffset; | |
856 p->spadj = -autoffset; | |
857 q->to = zprg.to; | |
858 continue; | |
859 } | 590 } |
860 } | 591 } |
861 | 592 |
862 int32 | 593 int32 |
863 atolwhex(char *s) | 594 atolwhex(char *s) |
864 { | 595 { |
865 int32 n; | 596 int32 n; |
866 int f; | 597 int f; |
867 | 598 |
868 n = 0; | 599 n = 0; |
(...skipping 30 matching lines...) Expand all Loading... |
899 return n; | 630 return n; |
900 } | 631 } |
901 | 632 |
902 void | 633 void |
903 undef(void) | 634 undef(void) |
904 { | 635 { |
905 int i; | 636 int i; |
906 Sym *s; | 637 Sym *s; |
907 | 638 |
908 for(i=0; i<NHASH; i++) | 639 for(i=0; i<NHASH; i++) |
909 » for(s = hash[i]; s != S; s = s->link) | 640 » for(s = hash[i]; s != S; s = s->hash) |
910 if(s->type == SXREF) | 641 if(s->type == SXREF) |
911 diag("%s: not defined", s->name); | 642 diag("%s: not defined", s->name); |
912 } | 643 } |
913 | |
914 void | |
915 import(void) | |
916 { | |
917 int i; | |
918 Sym *s; | |
919 | |
920 for(i = 0; i < NHASH; i++) | |
921 for(s = hash[i]; s != S; s = s->link) | |
922 if(s->sig != 0 && s->type == SXREF && (nimports == 0 ||
s->subtype == SIMPORT)){ | |
923 if(s->value != 0) | |
924 diag("value != 0 on SXREF"); | |
925 undefsym(s); | |
926 Bprint(&bso, "IMPORT: %s sig=%lux v=%ld\n", s->n
ame, s->sig, s->value); | |
927 if(debug['S']) | |
928 s->sig = 0; | |
929 } | |
930 } | |
931 | |
932 void | |
933 ckoff(Sym *s, int32 v) | |
934 { | |
935 if(v < 0 || v >= 1<<Roffset) | |
936 diag("relocation offset %ld for %s out of range", v, s->name); | |
937 } | |
938 | |
939 Prog* | |
940 newdata(Sym *s, int o, int w, int t) | |
941 { | |
942 Prog *p; | |
943 | |
944 p = prg(); | |
945 if(edatap == P) | |
946 datap = p; | |
947 else | |
948 edatap->link = p; | |
949 edatap = p; | |
950 p->as = ADATA; | |
951 p->width = w; | |
952 p->from.scale = w; | |
953 p->from.type = t; | |
954 p->from.sym = s; | |
955 p->from.offset = o; | |
956 p->to.type = D_CONST; | |
957 p->dlink = s->data; | |
958 s->data = p; | |
959 return p; | |
960 } | |
961 | |
962 Prog* | |
963 newtext(Prog *p, Sym *s) | |
964 { | |
965 if(p == P) { | |
966 p = prg(); | |
967 p->as = ATEXT; | |
968 p->from.sym = s; | |
969 } | |
970 s->type = STEXT; | |
971 s->text = p; | |
972 s->value = pc; | |
973 lastp->link = p; | |
974 lastp = p; | |
975 p->pc = pc++; | |
976 if(textp == P) | |
977 textp = p; | |
978 else | |
979 etextp->pcond = p; | |
980 etextp = p; | |
981 return p; | |
982 } | |
983 | |
984 void | |
985 export(void) | |
986 { | |
987 int i, j, n, off, nb, sv, ne; | |
988 Sym *s, *et, *str, **esyms; | |
989 Prog *p; | |
990 char buf[NSNAME], *t; | |
991 | |
992 n = 0; | |
993 for(i = 0; i < NHASH; i++) | |
994 for(s = hash[i]; s != S; s = s->link) | |
995 if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF
&& (nexports == 0 || s->subtype == SEXPORT)) | |
996 n++; | |
997 esyms = mal(n*sizeof(Sym*)); | |
998 ne = n; | |
999 n = 0; | |
1000 for(i = 0; i < NHASH; i++) | |
1001 for(s = hash[i]; s != S; s = s->link) | |
1002 if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF
&& (nexports == 0 || s->subtype == SEXPORT)) | |
1003 esyms[n++] = s; | |
1004 for(i = 0; i < ne-1; i++) | |
1005 for(j = i+1; j < ne; j++) | |
1006 if(strcmp(esyms[i]->name, esyms[j]->name) > 0){ | |
1007 s = esyms[i]; | |
1008 esyms[i] = esyms[j]; | |
1009 esyms[j] = s; | |
1010 } | |
1011 | |
1012 nb = 0; | |
1013 off = 0; | |
1014 et = lookup(EXPTAB, 0); | |
1015 if(et->type != 0 && et->type != SXREF) | |
1016 diag("%s already defined", EXPTAB); | |
1017 et->type = SDATA; | |
1018 str = lookup(".string", 0); | |
1019 if(str->type == 0) | |
1020 str->type = SDATA; | |
1021 sv = str->value; | |
1022 for(i = 0; i < ne; i++){ | |
1023 s = esyms[i]; | |
1024 if(debug['S']) | |
1025 s->sig = 0; | |
1026 /* Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s
->type); */ | |
1027 | |
1028 /* signature */ | |
1029 p = newdata(et, off, sizeof(int32), D_EXTERN); | |
1030 off += sizeof(int32); | |
1031 p->to.offset = s->sig; | |
1032 | |
1033 /* address */ | |
1034 p = newdata(et, off, sizeof(int32), D_EXTERN); | |
1035 off += sizeof(int32); | |
1036 p->to.type = D_ADDR; | |
1037 p->to.index = D_EXTERN; | |
1038 p->to.sym = s; | |
1039 | |
1040 /* string */ | |
1041 t = s->name; | |
1042 n = strlen(t)+1; | |
1043 for(;;){ | |
1044 buf[nb++] = *t; | |
1045 sv++; | |
1046 if(nb >= NSNAME){ | |
1047 p = newdata(str, sv-NSNAME, NSNAME, D_STATIC); | |
1048 p->to.type = D_SCONST; | |
1049 memmove(p->to.scon, buf, NSNAME); | |
1050 nb = 0; | |
1051 } | |
1052 if(*t++ == 0) | |
1053 break; | |
1054 } | |
1055 | |
1056 /* name */ | |
1057 p = newdata(et, off, sizeof(int32), D_EXTERN); | |
1058 off += sizeof(int32); | |
1059 p->to.type = D_ADDR; | |
1060 p->to.index = D_STATIC; | |
1061 p->to.sym = str; | |
1062 p->to.offset = sv-n; | |
1063 } | |
1064 | |
1065 if(nb > 0){ | |
1066 p = newdata(str, sv-nb, nb, D_STATIC); | |
1067 p->to.type = D_SCONST; | |
1068 memmove(p->to.scon, buf, nb); | |
1069 } | |
1070 | |
1071 for(i = 0; i < 3; i++){ | |
1072 newdata(et, off, sizeof(int32), D_EXTERN); | |
1073 off += sizeof(int32); | |
1074 } | |
1075 et->size = off; | |
1076 if(sv == 0) | |
1077 sv = 1; | |
1078 str->size = sv; | |
1079 exports = ne; | |
1080 free(esyms); | |
1081 } | |
LEFT | RIGHT |