LEFT | RIGHT |
1 // Inferno utils/5l/noop.c | 1 // Inferno utils/5l/noop.c |
2 // http://code.google.com/p/inferno-os/source/browse/utils/5l/noop.c | 2 // http://code.google.com/p/inferno-os/source/browse/utils/5l/noop.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 14 matching lines...) Expand all Loading... |
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 transformations. | 31 // Code transformations. |
32 | 32 |
33 #include "l.h" | 33 #include "l.h" |
34 #include "../ld/lib.h" | 34 #include "../ld/lib.h" |
35 | 35 #include» "../../pkg/runtime/stack.h" |
36 // see ../../runtime/proc.c:/StackGuard | |
37 enum | |
38 { | |
39 » StackBig = 4096, | |
40 » StackSmall = 128, | |
41 }; | |
42 | 36 |
43 static Sym* sym_div; | 37 static Sym* sym_div; |
44 static Sym* sym_divu; | 38 static Sym* sym_divu; |
45 static Sym* sym_mod; | 39 static Sym* sym_mod; |
46 static Sym* sym_modu; | 40 static Sym* sym_modu; |
47 | 41 |
48 static void | 42 static void |
49 linkcase(Prog *casep) | 43 linkcase(Prog *casep) |
50 { | 44 { |
51 Prog *p; | 45 Prog *p; |
52 | 46 |
53 for(p = casep; p != P; p = p->link){ | 47 for(p = casep; p != P; p = p->link){ |
54 if(p->as == ABCASE) { | 48 if(p->as == ABCASE) { |
55 for(; p != P && p->as == ABCASE; p = p->link) | 49 for(; p != P && p->as == ABCASE; p = p->link) |
56 p->pcrel = casep; | 50 p->pcrel = casep; |
57 break; | 51 break; |
58 } | 52 } |
59 } | 53 } |
60 } | 54 } |
61 | 55 |
62 void | 56 void |
63 noops(void) | 57 noops(void) |
64 { | 58 { |
65 Prog *p, *q, *q1, *q2; | 59 Prog *p, *q, *q1, *q2; |
66 int o; | 60 int o; |
| 61 int32 arg; |
67 Prog *pmorestack; | 62 Prog *pmorestack; |
68 Sym *symmorestack, *tlsfallback, *gmsym; | 63 Sym *symmorestack, *tlsfallback, *gmsym; |
69 | 64 |
70 /* | 65 /* |
71 * find leaf subroutines | 66 * find leaf subroutines |
72 * strip NOPs | 67 * strip NOPs |
73 * expand RET | 68 * expand RET |
74 * expand BECOME pseudo | 69 * expand BECOME pseudo |
75 * fixup TLS | 70 * fixup TLS |
76 */ | 71 */ |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 cursym->name); | 221 cursym->name); |
227 Bflush(&bso); | 222 Bflush(&bso); |
228 cursym->text->mark |= LEAF; | 223 cursym->text->mark |= LEAF; |
229 } | 224 } |
230 if(cursym->text->mark & LEAF) { | 225 if(cursym->text->mark & LEAF) { |
231 cursym->leaf = 1; | 226 cursym->leaf = 1; |
232 if(!autosize) | 227 if(!autosize) |
233 break; | 228 break; |
234 } | 229 } |
235 ········ | 230 ········ |
236 » » » » if(p->reg & NOSPLIT) { | 231 » » » » if(!(p->reg & NOSPLIT)) { |
237 » » » » » q1 = prg(); | |
238 » » » » » q1->as = AMOVW; | |
239 » » » » » q1->scond |= C_WBIT; | |
240 » » » » » q1->line = p->line; | |
241 » » » » » q1->from.type = D_REG; | |
242 » » » » » q1->from.reg = REGLINK; | |
243 » » » » » q1->to.type = D_OREG; | |
244 » » » » » q1->to.offset = -autosize; | |
245 » » » » » q1->to.reg = REGSP; | |
246 » » » » » q1->spadj = autosize; | |
247 » » » » » q1->link = p->link; | |
248 » » » » » p->link = q1; | |
249 » » » » } else if (autosize < StackBig) { | |
250 » » » » » // split stack check for small functions | |
251 » » » » » // MOVW»» » g_stackguard(g),
R1 | |
252 » » » » » // CMP» » » R1, $-autosize(S
P) | |
253 » » » » » // MOVW.LO» » $autosize, R1 | |
254 » » » » » // MOVW.LO» » $args, R2 | |
255 » » » » » // MOVW.LO» » R14, R3 | |
256 » » » » » // BL.LO» » » runtime.
morestack(SB) // modifies LR | |
257 » » » » » // MOVW.W» » R14,$-autosize(S
P) | |
258 »······· | |
259 » » » » » // TODO(kaib): add more trampolines | |
260 » » » » » // TODO(kaib): put stackguard in registe
r | |
261 » » » » » // TODO(kaib): add support for -K and un
derflow detection | |
262 | |
263 // MOVW g_stackguard(g),
R1 | 232 // MOVW g_stackguard(g),
R1 |
264 p = appendp(p); | 233 p = appendp(p); |
265 p->as = AMOVW; | 234 p->as = AMOVW; |
266 p->from.type = D_OREG; | 235 p->from.type = D_OREG; |
267 p->from.reg = REGG; | 236 p->from.reg = REGG; |
268 p->to.type = D_REG; | 237 p->to.type = D_REG; |
269 p->to.reg = 1; | 238 p->to.reg = 1; |
270 ········································ | 239 ········································ |
271 » » » » » if(autosize < StackSmall) {» | 240 » » » » » if(autosize <= StackSmall) { |
272 » » » » » » // CMP» » » R1, SP | 241 » » » » » » // small stack: SP < stackguard |
| 242 » » » » » » //» CMP» stackguard, SP |
273 p = appendp(p); | 243 p = appendp(p); |
274 p->as = ACMP; | 244 p->as = ACMP; |
275 p->from.type = D_REG; | 245 p->from.type = D_REG; |
276 p->from.reg = 1; | 246 p->from.reg = 1; |
277 p->reg = REGSP; | 247 p->reg = REGSP; |
278 » » » » » } else { | 248 » » » » » } else if(autosize <= StackBig) { |
279 » » » » » » // MOVW»» $-autosize(SP),
R2 | 249 » » » » » » // large stack: SP-framesize < s
tackguard-StackSmall |
280 » » » » » » // CMP» R1, R2 | 250 » » » » » » //» MOVW $-autosize(SP), R2 |
| 251 » » » » » » //» CMP stackguard, R2 |
281 p = appendp(p); | 252 p = appendp(p); |
282 p->as = AMOVW; | 253 p->as = AMOVW; |
283 p->from.type = D_CONST; | 254 p->from.type = D_CONST; |
284 p->from.reg = REGSP; | 255 p->from.reg = REGSP; |
285 p->from.offset = -autosize; | 256 p->from.offset = -autosize; |
286 p->to.type = D_REG; | 257 p->to.type = D_REG; |
287 p->to.reg = 2; | 258 p->to.reg = 2; |
288 ················································ | 259 ················································ |
289 p = appendp(p); | 260 p = appendp(p); |
290 p->as = ACMP; | 261 p->as = ACMP; |
291 p->from.type = D_REG; | 262 p->from.type = D_REG; |
292 p->from.reg = 1; | 263 p->from.reg = 1; |
293 p->reg = 2; | 264 p->reg = 2; |
| 265 } else { |
| 266 // Such a large stack we need to
protect against wraparound |
| 267 // if SP is close to zero. |
| 268 // SP-stackguard+StackGuard
< framesize + (StackGuard-StackSmall) |
| 269 // The +StackGuard on both sides
is required to keep the left side positive: |
| 270 // SP is allowed to be slightly
below stackguard. See stack.h. |
| 271 // CMP $StackPreempt, R1 |
| 272 // MOVW.NE $StackGuard(SP),
R2 |
| 273 // SUB.NE R1, R2 |
| 274 // MOVW.NE $(autosize+(Stac
kGuard-StackSmall)), R3 |
| 275 // CMP.NE R3, R2 |
| 276 p = appendp(p); |
| 277 p->as = ACMP; |
| 278 p->from.type = D_CONST; |
| 279 p->from.offset = (uint32)StackPr
eempt; |
| 280 p->reg = 1; |
| 281 |
| 282 p = appendp(p); |
| 283 p->as = AMOVW; |
| 284 p->from.type = D_CONST; |
| 285 p->from.reg = REGSP; |
| 286 p->from.offset = StackGuard; |
| 287 p->to.type = D_REG; |
| 288 p->to.reg = 2; |
| 289 p->scond = C_SCOND_NE; |
| 290 ················································ |
| 291 p = appendp(p); |
| 292 p->as = ASUB; |
| 293 p->from.type = D_REG; |
| 294 p->from.reg = 1; |
| 295 p->to.type = D_REG; |
| 296 p->to.reg = 2; |
| 297 p->scond = C_SCOND_NE; |
| 298 ················································ |
| 299 p = appendp(p); |
| 300 p->as = AMOVW; |
| 301 p->from.type = D_CONST; |
| 302 p->from.offset = autosize + (Sta
ckGuard - StackSmall); |
| 303 p->to.type = D_REG; |
| 304 p->to.reg = 3; |
| 305 p->scond = C_SCOND_NE; |
| 306 ················································ |
| 307 p = appendp(p); |
| 308 p->as = ACMP; |
| 309 p->from.type = D_REG; |
| 310 p->from.reg = 3; |
| 311 p->reg = 2; |
| 312 p->scond = C_SCOND_NE; |
294 } | 313 } |
295 | 314 » » » » » |
296 » » » » » // MOVW.LO» » $autosize, R1 | 315 » » » » » // MOVW.LS» » $autosize, R1 |
297 p = appendp(p); | 316 p = appendp(p); |
298 p->as = AMOVW; | 317 p->as = AMOVW; |
299 » » » » » p->scond = C_SCOND_LO; | 318 » » » » » p->scond = C_SCOND_LS; |
300 p->from.type = D_CONST; | 319 p->from.type = D_CONST; |
301 p->from.offset = autosize; | 320 p->from.offset = autosize; |
302 p->to.type = D_REG; | 321 p->to.type = D_REG; |
303 p->to.reg = 1; | 322 p->to.reg = 1; |
304 ········ | 323 ········ |
305 » » » » » // MOVW.LO» » $args, R2 | 324 » » » » » // MOVW.LS» » $args, R2 |
306 p = appendp(p); | 325 p = appendp(p); |
307 p->as = AMOVW; | 326 p->as = AMOVW; |
308 » » » » » p->scond = C_SCOND_LO; | 327 » » » » » p->scond = C_SCOND_LS; |
309 p->from.type = D_CONST; | 328 p->from.type = D_CONST; |
310 » » » » » p->from.offset = (cursym->text->to.offse
t2 + 3) & ~3; | 329 » » » » » arg = cursym->text->to.offset2; |
| 330 » » » » » if(arg == 1) // special marker for known
0 |
| 331 » » » » » » arg = 0; |
| 332 » » » » » if(arg&3) |
| 333 » » » » » » diag("misaligned argument size i
n stack split"); |
| 334 » » » » » p->from.offset = arg; |
311 p->to.type = D_REG; | 335 p->to.type = D_REG; |
312 p->to.reg = 2; | 336 p->to.reg = 2; |
313 ········ | 337 ········ |
314 » » » » » // MOVW.LO» R14, R3 | 338 » » » » » // MOVW.LS» R14, R3 |
315 p = appendp(p); | 339 p = appendp(p); |
316 p->as = AMOVW; | 340 p->as = AMOVW; |
317 » » » » » p->scond = C_SCOND_LO; | 341 » » » » » p->scond = C_SCOND_LS; |
318 p->from.type = D_REG; | 342 p->from.type = D_REG; |
319 p->from.reg = REGLINK; | 343 p->from.reg = REGLINK; |
320 p->to.type = D_REG; | 344 p->to.type = D_REG; |
321 p->to.reg = 3; | 345 p->to.reg = 3; |
322 ········ | 346 ········ |
323 » » » » » // BL.LO» » runtime.morestac
k(SB) // modifies LR | 347 » » » » » // BL.LS» » runtime.morestac
k(SB) // modifies LR, returns with LO still asserted |
324 p = appendp(p); | 348 p = appendp(p); |
325 p->as = ABL; | 349 p->as = ABL; |
326 » » » » » p->scond = C_SCOND_LO; | 350 » » » » » p->scond = C_SCOND_LS; |
327 p->to.type = D_BRANCH; | 351 p->to.type = D_BRANCH; |
328 p->to.sym = symmorestack; | 352 p->to.sym = symmorestack; |
329 p->cond = pmorestack; | 353 p->cond = pmorestack; |
330 »······· | 354 » » » » »······· |
331 » » » » » // MOVW.W» » R14,$-autosize(S
P) | 355 » » » » » // BLS» start |
332 p = appendp(p); | 356 p = appendp(p); |
333 » » » » » p->as = AMOVW; | 357 » » » » » p->as = ABLS; |
334 » » » » » p->scond |= C_WBIT; | |
335 » » » » » p->from.type = D_REG; | |
336 » » » » » p->from.reg = REGLINK; | |
337 » » » » » p->to.type = D_OREG; | |
338 » » » » » p->to.offset = -autosize; | |
339 » » » » » p->to.reg = REGSP; | |
340 » » » » » p->spadj = autosize; | |
341 » » » » } else { // > StackBig | |
342 » » » » » // MOVW»» $autosize, R1 | |
343 » » » » » // MOVW»» $args, R2 | |
344 » » » » » // MOVW»» R14, R3 | |
345 » » » » » // BL» » » runtime.morestac
k(SB) // modifies LR | |
346 » » » » » // MOVW.W» » R14,$-autosize(S
P) | |
347 »······· | |
348 » » » » » // MOVW»» $autosize, R1 | |
349 » » » » » p = appendp(p); | |
350 » » » » » p->as = AMOVW; | |
351 » » » » » p->from.type = D_CONST; | |
352 » » » » » p->from.offset = autosize; | |
353 » » » » » p->to.type = D_REG; | |
354 » » » » » p->to.reg = 1; | |
355 »······· | |
356 » » » » » // MOVW»» $args, R2 | |
357 » » » » » // also need to store the extra 4 bytes. | |
358 » » » » » p = appendp(p); | |
359 » » » » » p->as = AMOVW; | |
360 » » » » » p->from.type = D_CONST; | |
361 » » » » » p->from.offset = (cursym->text->to.offse
t2 + 3) & ~3; | |
362 » » » » » p->to.type = D_REG; | |
363 » » » » » p->to.reg = 2; | |
364 »······· | |
365 » » » » » // MOVW»R14, R3 | |
366 » » » » » p = appendp(p); | |
367 » » » » » p->as = AMOVW; | |
368 » » » » » p->from.type = D_REG; | |
369 » » » » » p->from.reg = REGLINK; | |
370 » » » » » p->to.type = D_REG; | |
371 » » » » » p->to.reg = 3; | |
372 »······· | |
373 » » » » » // BL» » runtime.morestack(SB) //
modifies LR | |
374 » » » » » p = appendp(p); | |
375 » » » » » p->as = ABL; | |
376 p->to.type = D_BRANCH; | 358 p->to.type = D_BRANCH; |
377 » » » » » p->to.sym = symmorestack; | 359 » » » » » p->cond = cursym->text->link; |
378 » » » » » p->cond = pmorestack; | 360 » » » » } |
379 »······· | 361 » » » »······· |
380 » » » » » // MOVW.W» » R14,$-autosize(S
P) | 362 » » » » // MOVW.W» » R14,$-autosize(SP) |
381 » » » » » p = appendp(p); | 363 » » » » p = appendp(p); |
382 » » » » » p->as = AMOVW; | 364 » » » » p->as = AMOVW; |
383 » » » » » p->scond |= C_WBIT; | 365 » » » » p->scond |= C_WBIT; |
384 » » » » » p->from.type = D_REG; | 366 » » » » p->from.type = D_REG; |
385 » » » » » p->from.reg = REGLINK; | 367 » » » » p->from.reg = REGLINK; |
386 » » » » » p->to.type = D_OREG; | 368 » » » » p->to.type = D_OREG; |
387 » » » » » p->to.offset = -autosize; | 369 » » » » p->to.offset = -autosize; |
388 » » » » » p->to.reg = REGSP; | 370 » » » » p->to.reg = REGSP; |
389 » » » » » p->spadj = autosize; | 371 » » » » p->spadj = autosize; |
390 » » » » } | |
391 break; | 372 break; |
392 ········ | 373 ········ |
393 case ARET: | 374 case ARET: |
394 nocache(p); | 375 nocache(p); |
395 if(cursym->text->mark & LEAF) { | 376 if(cursym->text->mark & LEAF) { |
396 if(!autosize) { | 377 if(!autosize) { |
397 p->as = AB; | 378 p->as = AB; |
398 p->from = zprg.from; | 379 p->from = zprg.from; |
399 if(p->to.sym) { // retjmp | 380 if(p->to.sym) { // retjmp |
400 p->to.type = D_BRANCH; | 381 p->to.type = D_BRANCH; |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 } | 579 } |
599 } | 580 } |
600 | 581 |
601 void | 582 void |
602 nocache(Prog *p) | 583 nocache(Prog *p) |
603 { | 584 { |
604 p->optab = 0; | 585 p->optab = 0; |
605 p->from.class = 0; | 586 p->from.class = 0; |
606 p->to.class = 0; | 587 p->to.class = 0; |
607 } | 588 } |
LEFT | RIGHT |