Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(8)

Delta Between Two Patch Sets: src/liblink/obj5.c

Issue 56120043: code review 56120043: liblink, runtime: fix cgo on arm (Closed)
Left Patch Set: diff -r f9e8a970798c https://code.google.com/p/go/ Created 11 years, 1 month ago
Right Patch Set: diff -r 0dff07f88a28 https://code.google.com/p/go/ Created 11 years, 1 month ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/liblink/asm5.c ('k') | src/pkg/runtime/asm_arm.s » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Derived from Inferno utils/5c/swt.c
2 // http://code.google.com/p/inferno-os/source/browse/utils/5c/swt.c
3 //
4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
6 // Portions Copyright © 1997-1999 Vita Nuova Limited
7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuov a.com)
8 // Portions Copyright © 2004,2006 Bruce Ellis
9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
11 // Portions Copyright © 2009 The Go Authors. All rights reserved.
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a copy
14 // of this software and associated documentation files (the "Software"), to deal
15 // in the Software without restriction, including without limitation the rights
16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 // copies of the Software, and to permit persons to whom the Software is
18 // furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included in
21 // all copies or substantial portions of the Software.
22 //
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,
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
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
29 // THE SOFTWARE.
30
31 #include <u.h>
32 #include <libc.h>
33 #include <bio.h>
34 #include <link.h>
35 #include "../cmd/5l/5.out.h"
36 #include "../pkg/runtime/stack.h"
37
38 static Prog zprg = {
39 .as = AGOK,
40 .scond = C_SCOND_NONE,
41 .reg = NREG,
42 .from = {
43 .name = D_NONE,
44 .type = D_NONE,
45 .reg = NREG,
46 },
47 .to = {
48 .name = D_NONE,
49 .type = D_NONE,
50 .reg = NREG,
51 },
52 };
53
54 static int
55 symtype(Addr *a)
56 {
57 return a->name;
58 }
59
60 static int
61 isdata(Prog *p)
62 {
63 return p->as == ADATA || p->as == AGLOBL;
64 }
65
66 static int
67 iscall(Prog *p)
68 {
69 return p->as == ABL;
70 }
71
72 static int
73 datasize(Prog *p)
74 {
75 return p->reg;
76 }
77
78 static int
79 textflag(Prog *p)
80 {
81 return p->reg;
82 }
83
84 static void
85 settextflag(Prog *p, int f)
86 {
87 p->reg = f;
88 }
89
90 static void
91 progedit(Link *ctxt, Prog *p)
92 {
93 char literal[64];
94 LSym *s;
95
96 p->from.class = 0;
97 p->to.class = 0;
98
99 // Rewrite B/BL to symbol as D_BRANCH.
100 switch(p->as) {
101 case AB:
102 case ABL:
103 if(p->to.type == D_OREG && (p->to.name == D_EXTERN || p->to.name == D_STATIC) && p->to.sym != nil)
104 p->to.type = D_BRANCH;
105 break;
106 }
107
108 // Rewrite float constants to values stored in memory.
109 switch(p->as) {
110 case AMOVF:
111 if(p->from.type == D_FCONST && chipfloat5(ctxt, p->from.u.dval) < 0 &&
112 (chipzero5(ctxt, p->from.u.dval) < 0 || (p->scond & C_SCOND) != C_SCOND_NONE)) {
113 int32 i32;
114 float32 f32;
115 f32 = p->from.u.dval;
116 memmove(&i32, &f32, 4);
117 sprint(literal, "$f32.%08ux", (uint32)i32);
118 s = linklookup(ctxt, literal, 0);
119 if(s->type == 0) {
120 s->type = SRODATA;
121 adduint32(ctxt, s, i32);
122 s->reachable = 0;
123 }
124 p->from.type = D_OREG;
125 p->from.sym = s;
126 p->from.name = D_EXTERN;
127 p->from.offset = 0;
128 }
129 break;
130
131 case AMOVD:
132 if(p->from.type == D_FCONST && chipfloat5(ctxt, p->from.u.dval) < 0 &&
133 (chipzero5(ctxt, p->from.u.dval) < 0 || (p->scond & C_SCOND) != C_SCOND_NONE)) {
134 int64 i64;
135 memmove(&i64, &p->from.u.dval, 8);
136 sprint(literal, "$f64.%016llux", (uvlong)i64);
137 s = linklookup(ctxt, literal, 0);
138 if(s->type == 0) {
139 s->type = SRODATA;
140 adduint64(ctxt, s, i64);
141 s->reachable = 0;
142 }
143 p->from.type = D_OREG;
144 p->from.sym = s;
145 p->from.name = D_EXTERN;
146 p->from.offset = 0;
147 }
148 break;
149 }
150 }
151
152 static Prog*
153 prg(void)
154 {
155 Prog *p;
156
157 p = emallocz(sizeof(*p));
158 *p = zprg;
159 return p;
160 }
161
162 static Prog* stacksplit(Link*, Prog*, int32);
163 static void initdiv(Link*);
164 static void softfloat(Link*, LSym*);
165
166 // Prog.mark
167 enum
168 {
169 FOLL = 1<<0,
170 LABEL = 1<<1,
171 LEAF = 1<<2,
172 };
173
174 static void
175 linkcase(Prog *casep)
176 {
177 Prog *p;
178
179 for(p = casep; p != nil; p = p->link){
180 if(p->as == ABCASE) {
181 for(; p != nil && p->as == ABCASE; p = p->link)
182 p->pcrel = casep;
183 break;
184 }
185 }
186 }
187
188 static void
189 nocache(Prog *p)
190 {
191 p->optab = 0;
192 p->from.class = 0;
193 p->to.class = 0;
194 }
195
196 static void
197 addstacksplit(Link *ctxt, LSym *cursym)
198 { 1 {
199 Prog *p, *pl, *q, *q1, *q2; 2 Prog *p, *pl, *q, *q1, *q2;
200 int o; 3 int o;
201 LSym *tlsfallback; 4 LSym *tlsfallback;
202 int32 autosize, autoffset; 5 int32 autosize, autoffset;
203 ········ 6 ········
204 autosize = 0; 7 autosize = 0;
205
206 if(ctxt->symmorestack[0] == nil)
207 ctxt->symmorestack[0] = linklookup(ctxt, "runtime.morestack", 0) ;
208 ········
209 tlsfallback = linklookup(ctxt, "runtime.read_tls_fallback", 0);
210 if(ctxt->gmsym == nil)
211 ctxt->gmsym = linklookup(ctxt, "runtime.tlsgm", 0);
212 q = nil;
213 ········
214 ctxt->cursym = cursym;
215
216 if(cursym->text == nil || cursym->text->link == nil)
217 return;·························
218
219 softfloat(ctxt, cursym);
220
221 p = cursym->text;
222 autoffset = p->to.offset;
223 if(autoffset < 0)
224 autoffset = 0;
225 cursym->locals = autoffset;
226 cursym->args = p->to.offset2;
227
228 if(ctxt->debugzerostack) {
229 if(autoffset && !(p->reg&NOSPLIT)) {
230 // MOVW $4(R13), R1
231 p = appendp(ctxt, p);
232 p->as = AMOVW;
233 p->from.type = D_CONST;
234 p->from.reg = 13;
235 p->from.offset = 4;
236 p->to.type = D_REG;
237 p->to.reg = 1;
238 ········
239 // MOVW $n(R13), R2
240 p = appendp(ctxt, p);
241 p->as = AMOVW;
242 p->from.type = D_CONST;
243 p->from.reg = 13;
244 p->from.offset = 4 + autoffset;
245 p->to.type = D_REG;
246 p->to.reg = 2;
247 ········
248 // MOVW $0, R3
249 p = appendp(ctxt, p);
250 p->as = AMOVW;
251 p->from.type = D_CONST;
252 p->from.offset = 0;
253 p->to.type = D_REG;
254 p->to.reg = 3;
255 ········
256 // L:
257 // MOVW.nil R3, 0(R1) +4
258 // CMP R1, R2
259 // BNE L
260 p = pl = appendp(ctxt, p);
261 p->as = AMOVW;
262 p->from.type = D_REG;
263 p->from.reg = 3;
264 p->to.type = D_OREG;
265 p->to.reg = 1;
266 p->to.offset = 4;
267 p->scond |= C_PBIT;
268 ········
269 p = appendp(ctxt, p);
270 p->as = ACMP;
271 p->from.type = D_REG;
272 p->from.reg = 1;
273 p->reg = 2;
274 ········
275 p = appendp(ctxt, p);
276 p->as = ABNE;
277 p->to.type = D_BRANCH;
278 p->pcond = pl;
279 }
280 }
281
282 /*
283 * find leaf subroutines
284 * strip NOPs
285 * expand RET
286 * expand BECOME pseudo
287 * fixup TLS
288 */
289
290 for(p = cursym->text; p != nil; p = p->link) {
291 switch(p->as) {
292 case ACASE:
293 if(ctxt->flag_shared)
294 linkcase(p);
295 break;
296
297 case ATEXT:
298 p->mark |= LEAF;
299 break;
300
301 case ARET:
302 break;
303
304 case ADIV:
305 case ADIVU:
306 case AMOD:
307 case AMODU:
308 q = p;
309 if(ctxt->sym_div == nil)
310 initdiv(ctxt);
311 cursym->text->mark &= ~LEAF;
312 continue;
313
314 case ANOP:
315 q1 = p->link;
316 q->link = q1; /* q is non-nop */
317 if(q1 != nil)
318 q1->mark |= p->mark;
319 continue;
320
321 case ABL:
322 case ABX:
323 cursym->text->mark &= ~LEAF;
324
325 case ABCASE:
326 case AB:
327
328 case ABEQ:
329 case ABNE:
330 case ABCS:
331 case ABHS:
332 case ABCC:
333 case ABLO:
334 case ABMI:
335 case ABPL:
336 case ABVS:
337 case ABVC:
338 case ABHI:
339 case ABLS:
340 case ABGE:
341 case ABLT:
342 case ABGT:
343 case ABLE:
344 q1 = p->pcond;
345 if(q1 != nil) {
346 while(q1->as == ANOP) {
347 q1 = q1->link;
348 p->pcond = q1;
349 }
350 }
351 break;
352 }
353 q = p;
354 }
355
356 for(p = cursym->text; p != nil; p = p->link) {
357 o = p->as;
358 switch(o) {
359 case ATEXT:
360 autosize = p->to.offset + 4;
361 if(autosize <= 4)
362 if(cursym->text->mark & LEAF) {
363 p->to.offset = -4;
364 autosize = 0;
365 }
366
367 if(!autosize && !(cursym->text->mark & LEAF)) {
368 if(ctxt->debugvlog) {
369 Bprint(ctxt->bso, "save suppressed in: % s\n",
370 cursym->name);
371 Bflush(ctxt->bso);
372 }
373 cursym->text->mark |= LEAF;
374 }
375 if(cursym->text->mark & LEAF) {
376 cursym->leaf = 1;
377 if(!autosize)
378 break;
379 }
380
381 if(!(p->reg & NOSPLIT))
382 p = stacksplit(ctxt, p, autosize); // emit split check
383 ························
384 // MOVW.W R14,$-autosize(SP)
385 p = appendp(ctxt, p);
386 p->as = AMOVW;
387 p->scond |= C_WBIT;
388 p->from.type = D_REG;
389 p->from.reg = REGLINK;
390 p->to.type = D_OREG;
391 p->to.offset = -autosize;
392 p->to.reg = REGSP;
393 p->spadj = autosize;
394 ························
395 if(cursym->text->reg & WRAPPER) {
396 // g->panicwrap += autosize;
397 // MOVW panicwrap_offset(g), R3
398 // ADD $autosize, R3
399 // MOVW R3 panicwrap_offset(g)
400 p = appendp(ctxt, p);
401 p->as = AMOVW;
402 p->from.type = D_OREG;
403 p->from.reg = REGG;
404 p->from.offset = 2*ctxt->arch->ptrsize;
405 p->to.type = D_REG;
406 p->to.reg = 3;
407 ························
408 p = appendp(ctxt, p);
409 p->as = AADD;
410 p->from.type = D_CONST;
411 p->from.offset = autosize;
412 p->to.type = D_REG;
413 p->to.reg = 3;
414 ································
415 p = appendp(ctxt, p);
416 p->as = AMOVW;
417 p->from.type = D_REG;
418 p->from.reg = 3;
419 p->to.type = D_OREG;
420 p->to.reg = REGG;
421 p->to.offset = 2*ctxt->arch->ptrsize;
422 }
423 break;
424
425 case ARET:
426 nocache(p);
427 if(cursym->text->mark & LEAF) {
428 if(!autosize) {
429 p->as = AB;
430 p->from = zprg.from;
431 if(p->to.sym) { // retjmp
432 p->to.type = D_BRANCH;
433 } else {
434 p->to.type = D_OREG;
435 p->to.offset = 0;
436 p->to.reg = REGLINK;
437 }
438 break;
439 }
440 }
441
442 if(cursym->text->reg & WRAPPER) {
443 int scond;
444 ································
445 // Preserve original RET's cond, to allow RET.EQ
446 // in the implementation of reflect.call.
447 scond = p->scond;
448 p->scond = C_SCOND_NONE;
449
450 // g->panicwrap -= autosize;
451 // MOVW panicwrap_offset(g), R3
452 // SUB $autosize, R3
453 // MOVW R3 panicwrap_offset(g)
454 p->as = AMOVW;
455 p->from.type = D_OREG;
456 p->from.reg = REGG;
457 p->from.offset = 2*ctxt->arch->ptrsize;
458 p->to.type = D_REG;
459 p->to.reg = 3;
460 p = appendp(ctxt, p);
461 ························
462 p->as = ASUB;
463 p->from.type = D_CONST;
464 p->from.offset = autosize;
465 p->to.type = D_REG;
466 p->to.reg = 3;
467 p = appendp(ctxt, p);
468
469 p->as = AMOVW;
470 p->from.type = D_REG;
471 p->from.reg = 3;
472 p->to.type = D_OREG;
473 p->to.reg = REGG;
474 p->to.offset = 2*ctxt->arch->ptrsize;
475 p = appendp(ctxt, p);
476
477 p->scond = scond;
478 }
479
480 p->as = AMOVW;
481 p->scond |= C_PBIT;
482 p->from.type = D_OREG;
483 p->from.offset = autosize;
484 p->from.reg = REGSP;
485 p->to.type = D_REG;
486 p->to.reg = REGPC;
487 // If there are instructions following
488 // this ARET, they come from a branch
489 // with the same stackframe, so no spadj.
490 ························
491 if(p->to.sym) { // retjmp
492 p->to.reg = REGLINK;
493 q2 = appendp(ctxt, p);
494 q2->as = AB;
495 q2->to.type = D_BRANCH;
496 q2->to.sym = p->to.sym;
497 p->to.sym = nil;
498 p = q2;
499 }
500 break;
501
502 case AADD:
503 if(p->from.type == D_CONST && p->from.reg == NREG && p-> to.type == D_REG && p->to.reg == REGSP)
504 p->spadj = -p->from.offset;
505 break;
506
507 case ASUB:
508 if(p->from.type == D_CONST && p->from.reg == NREG && p-> to.type == D_REG && p->to.reg == REGSP)
509 p->spadj = p->from.offset;
510 break;
511
512 case ADIV:
513 case ADIVU:
514 case AMOD:
515 case AMODU:
516 if(ctxt->debugdivmod)
517 break;
518 if(p->from.type != D_REG)
519 break;
520 if(p->to.type != D_REG)
521 break;
522 q1 = p;
523
524 /* MOV a,4(SP) */
525 p = appendp(ctxt, p);
526 p->as = AMOVW;
527 p->lineno = q1->lineno;
528 p->from.type = D_REG;
529 p->from.reg = q1->from.reg;
530 p->to.type = D_OREG;
531 p->to.reg = REGSP;
532 p->to.offset = 4;
533
534 /* MOV b,REGTMP */
535 p = appendp(ctxt, p);
536 p->as = AMOVW;
537 p->lineno = q1->lineno;
538 p->from.type = D_REG;
539 p->from.reg = q1->reg;
540 if(q1->reg == NREG)
541 p->from.reg = q1->to.reg;
542 p->to.type = D_REG;
543 p->to.reg = REGTMP;
544 p->to.offset = 0;
545
546 /* CALL appropriate */
547 p = appendp(ctxt, p);
548 p->as = ABL;
549 p->lineno = q1->lineno;
550 p->to.type = D_BRANCH;
551 switch(o) {
552 case ADIV:
553 p->to.sym = ctxt->sym_div;
554 break;
555 case ADIVU:
556 p->to.sym = ctxt->sym_divu;
557 break;
558 case AMOD:
559 p->to.sym = ctxt->sym_mod;
560 break;
561 case AMODU:
562 p->to.sym = ctxt->sym_modu;
563 break;
564 }
565
566 /* MOV REGTMP, b */
567 p = appendp(ctxt, p);
568 p->as = AMOVW;
569 p->lineno = q1->lineno;
570 p->from.type = D_REG;
571 p->from.reg = REGTMP;
572 p->from.offset = 0;
573 p->to.type = D_REG;
574 p->to.reg = q1->to.reg;
575
576 /* ADD $8,SP */
577 p = appendp(ctxt, p);
578 p->as = AADD;
579 p->lineno = q1->lineno;
580 p->from.type = D_CONST;
581 p->from.reg = NREG;
582 p->from.offset = 8;
583 p->reg = NREG;
584 p->to.type = D_REG;
585 p->to.reg = REGSP;
586 p->spadj = -8;
587
588 /* Keep saved LR at 0(SP) after SP change. */
589 /* MOVW 0(SP), REGTMP; MOVW REGTMP, -8!(SP) */
590 /* TODO: Remove SP adjustments; see issue 6699. */
591 q1->as = AMOVW;
592 q1->from.type = D_OREG;
593 q1->from.reg = REGSP;
594 q1->from.offset = 0;
595 q1->reg = NREG;
596 q1->to.type = D_REG;
597 q1->to.reg = REGTMP;
598
599 /* SUB $8,SP */
600 q1 = appendp(ctxt, q1);
601 q1->as = AMOVW;
602 q1->from.type = D_REG;
603 q1->from.reg = REGTMP;
604 q1->reg = NREG;
605 q1->to.type = D_OREG;
606 q1->to.reg = REGSP;
607 q1->to.offset = -8;
608 q1->scond |= C_WBIT;
609 q1->spadj = 8;
610
611 break;
612 case AMOVW:
613 if((p->scond & C_WBIT) && p->to.type == D_OREG && p->to. reg == REGSP)
614 p->spadj = -p->to.offset;
615 if((p->scond & C_PBIT) && p->from.type == D_OREG && p->f rom.reg == REGSP && p->to.reg != REGPC)
616 p->spadj = -p->from.offset;
617 if(p->from.type == D_CONST && p->from.reg == REGSP && p- >to.type == D_REG && p->to.reg == REGSP)
618 p->spadj = -p->from.offset;
619 break;
620 }
621 }
622 }
623
624 static void
625 softfloat(Link *ctxt, LSym *cursym)
626 {
627 Prog *p, *next;
628 LSym *symsfloat;
629 int wasfloat;
630
631 if(ctxt->goarm > 5)
632 return;
633
634 symsfloat = linklookup(ctxt, "_sfloat", 0);
635
636 wasfloat = 0;
637 for(p = cursym->text; p != nil; p = p->link)
638 if(p->pcond != nil)
639 p->pcond->mark |= LABEL;
640 for(p = cursym->text; p != nil; p = p->link) {
641 switch(p->as) {
642 case AMOVW:
643 if(p->to.type == D_FREG || p->from.type == D_FREG)
644 goto soft;
645 goto notsoft;
646
647 case AMOVWD:
648 case AMOVWF:
649 case AMOVDW:
650 case AMOVFW:
651 case AMOVFD:
652 case AMOVDF:
653 case AMOVF:
654 case AMOVD:
655
656 case ACMPF:
657 case ACMPD:
658 case AADDF:
659 case AADDD:
660 case ASUBF:
661 case ASUBD:
662 case AMULF:
663 case AMULD:
664 case ADIVF:
665 case ADIVD:
666 case ASQRTF:
667 case ASQRTD:
668 case AABSF:
669 case AABSD:
670 goto soft;
671
672 default:
673 goto notsoft;
674
675 soft:
676 if (!wasfloat || (p->mark&LABEL)) {
677 next = ctxt->arch->prg();
678 *next = *p;
679
680 // BL _sfloat(SB)
681 *p = zprg;
682 p->link = next;
683 p->as = ABL;
684 p->to.type = D_BRANCH;
685 p->to.sym = symsfloat;
686 p->lineno = next->lineno;
687
688 p = next;
689 wasfloat = 1;
690 }
691 break;
692
693 notsoft:
694 wasfloat = 0;
695 }
696 }
697 }
698
699 static Prog*
700 stacksplit(Link *ctxt, Prog *p, int32 framesize)
701 {
702 int32 arg;
703
704 // MOVW g_stackguard(g), R1
705 p = appendp(ctxt, p);
706 p->as = AMOVW;
707 p->from.type = D_OREG;
708 p->from.reg = REGG;
709 p->to.type = D_REG;
710 p->to.reg = 1;
711 ········
712 if(framesize <= StackSmall) {
713 // small stack: SP < stackguard
714 // CMP stackguard, SP
715 p = appendp(ctxt, p);
716 p->as = ACMP;
717 p->from.type = D_REG;
718 p->from.reg = 1;
719 p->reg = REGSP;
720 } else if(framesize <= StackBig) {
721 // large stack: SP-framesize < stackguard-StackSmall
722 // MOVW $-framesize(SP), R2
723 // CMP stackguard, R2
724 p = appendp(ctxt, p);
725 p->as = AMOVW;
726 p->from.type = D_CONST;
727 p->from.reg = REGSP;
728 p->from.offset = -framesize;
729 p->to.type = D_REG;
730 p->to.reg = 2;
731 ················
732 p = appendp(ctxt, p);
733 p->as = ACMP;
734 p->from.type = D_REG;
735 p->from.reg = 1;
736 p->reg = 2;
737 } else {
738 // Such a large stack we need to protect against wraparound
739 // if SP is close to zero.
740 // SP-stackguard+StackGuard < framesize + (StackGuard-Stack Small)
741 // The +StackGuard on both sides is required to keep the left si de positive:
742 // SP is allowed to be slightly below stackguard. See stack.h.
743 // CMP $StackPreempt, R1
744 // MOVW.NE $StackGuard(SP), R2
745 // SUB.NE R1, R2
746 // MOVW.NE $(framesize+(StackGuard-StackSmall)), R3
747 // CMP.NE R3, R2
748 p = appendp(ctxt, p);
749 p->as = ACMP;
750 p->from.type = D_CONST;
751 p->from.offset = (uint32)StackPreempt;
752 p->reg = 1;
753
754 p = appendp(ctxt, p);
755 p->as = AMOVW;
756 p->from.type = D_CONST;
757 p->from.reg = REGSP;
758 p->from.offset = StackGuard;
759 p->to.type = D_REG;
760 p->to.reg = 2;
761 p->scond = C_SCOND_NE;
762 ················
763 p = appendp(ctxt, p);
764 p->as = ASUB;
765 p->from.type = D_REG;
766 p->from.reg = 1;
767 p->to.type = D_REG;
768 p->to.reg = 2;
769 p->scond = C_SCOND_NE;
770 ················
771 p = appendp(ctxt, p);
772 p->as = AMOVW;
773 p->from.type = D_CONST;
774 p->from.offset = framesize + (StackGuard - StackSmall);
775 p->to.type = D_REG;
776 p->to.reg = 3;
777 p->scond = C_SCOND_NE;
778 ················
779 p = appendp(ctxt, p);
780 p->as = ACMP;
781 p->from.type = D_REG;
782 p->from.reg = 3;
783 p->reg = 2;
784 p->scond = C_SCOND_NE;
785 }
786 ········
787 // MOVW.LS $framesize, R1
788 p = appendp(ctxt, p);
789 p->as = AMOVW;
790 p->scond = C_SCOND_LS;
791 p->from.type = D_CONST;
792 p->from.offset = framesize;
793 p->to.type = D_REG;
794 p->to.reg = 1;
795
796 // MOVW.LS $args, R2
797 p = appendp(ctxt, p);
798 p->as = AMOVW;
799 p->scond = C_SCOND_LS;
800 p->from.type = D_CONST;
801 arg = ctxt->cursym->text->to.offset2;
802 if(arg == 1) // special marker for known 0
803 arg = 0;
804 if(arg&3)
805 ctxt->diag("misaligned argument size in stack split");
806 p->from.offset = arg;
807 p->to.type = D_REG;
808 p->to.reg = 2;
809
810 // MOVW.LS R14, R3
811 p = appendp(ctxt, p);
812 p->as = AMOVW;
813 p->scond = C_SCOND_LS;
814 p->from.type = D_REG;
815 p->from.reg = REGLINK;
816 p->to.type = D_REG;
817 p->to.reg = 3;
818
819 // BL.LS runtime.morestack(SB) // modifies LR, returns wi th LO still asserted
820 p = appendp(ctxt, p);
821 p->as = ABL;
822 p->scond = C_SCOND_LS;
823 p->to.type = D_BRANCH;
824 p->to.sym = ctxt->symmorestack[0];
825 ········
826 // BLS start
827 p = appendp(ctxt, p);
828 p->as = ABLS;
829 p->to.type = D_BRANCH;
830 p->pcond = ctxt->cursym->text->link;
831 ········
832 return p;
833 }
834
835 static void
836 initdiv(Link *ctxt)
837 {
838 if(ctxt->sym_div != nil)
839 return;
840 ctxt->sym_div = linklookup(ctxt, "_div", 0);
841 ctxt->sym_divu = linklookup(ctxt, "_divu", 0);
842 ctxt->sym_mod = linklookup(ctxt, "_mod", 0);
843 ctxt->sym_modu = linklookup(ctxt, "_modu", 0);
844 }
845
846 static void xfol(Link*, Prog*, Prog**);
847
848 static void
849 follow(Link *ctxt, LSym *s)
850 {
851 Prog *firstp, *lastp;
852
853 ctxt->cursym = s;
854
855 firstp = ctxt->arch->prg();
856 lastp = firstp;
857 xfol(ctxt, s->text, &lastp);
858 lastp->link = nil;
859 s->text = firstp->link;
860 }
861
862 static int
863 relinv(int a)
864 {
865 switch(a) {
866 case ABEQ: return ABNE;
867 case ABNE: return ABEQ;
868 case ABCS: return ABCC;
869 case ABHS: return ABLO;
870 case ABCC: return ABCS;
871 case ABLO: return ABHS;
872 case ABMI: return ABPL;
873 case ABPL: return ABMI;
874 case ABVS: return ABVC;
875 case ABVC: return ABVS;
876 case ABHI: return ABLS;
877 case ABLS: return ABHI;
878 case ABGE: return ABLT;
879 case ABLT: return ABGE;
880 case ABGT: return ABLE;
881 case ABLE: return ABGT;
882 }
883 sysfatal("unknown relation: %s", anames5[a]);
884 return 0;
885 }
886
887 static void
888 xfol(Link *ctxt, Prog *p, Prog **last)
889 {
890 Prog *q, *r;
891 int a, i;
892
893 loop:
894 if(p == nil)
895 return;
896 a = p->as;
897 if(a == AB) {
898 q = p->pcond;
899 if(q != nil && q->as != ATEXT) {
900 p->mark |= FOLL;
901 p = q;
902 if(!(p->mark & FOLL))
903 goto loop;
904 }
905 }
906 if(p->mark & FOLL) {
907 for(i=0,q=p; i<4; i++,q=q->link) {
908 if(q == *last || q == nil)
909 break;
910 a = q->as;
911 if(a == ANOP) {
912 i--;
913 continue;
914 }
915 if(a == AB || (a == ARET && q->scond == C_SCOND_NONE) || a == ARFE || a == AUNDEF)
916 goto copy;
917 if(q->pcond == nil || (q->pcond->mark&FOLL))
918 continue;
919 if(a != ABEQ && a != ABNE)
920 continue;
921 copy:
922 for(;;) {
923 r = ctxt->arch->prg();
924 *r = *p;
925 if(!(r->mark&FOLL))
926 print("can't happen 1\n");
927 r->mark |= FOLL;
928 if(p != q) {
929 p = p->link;
930 (*last)->link = r;
931 *last = r;
932 continue;
933 }
934 (*last)->link = r;
935 *last = r;
936 if(a == AB || (a == ARET && q->scond == C_SCOND_ NONE) || a == ARFE || a == AUNDEF)
937 return;
938 r->as = ABNE;
939 if(a == ABNE)
940 r->as = ABEQ;
941 r->pcond = p->link;
942 r->link = p->pcond;
943 if(!(r->link->mark&FOLL))
944 xfol(ctxt, r->link, last);
945 if(!(r->pcond->mark&FOLL))
946 print("can't happen 2\n");
947 return;
948 }
949 }
950 a = AB;
951 q = ctxt->arch->prg();
952 q->as = a;
953 q->lineno = p->lineno;
954 q->to.type = D_BRANCH;
955 q->to.offset = p->pc;
956 q->pcond = p;
957 p = q;
958 }
959 p->mark |= FOLL;
960 (*last)->link = p;
961 *last = p;
962 if(a == AB || (a == ARET && p->scond == C_SCOND_NONE) || a == ARFE || a == AUNDEF){
963 return;
964 }
965 if(p->pcond != nil)
966 if(a != ABL && a != ABX && p->link != nil) {
967 q = brchain(ctxt, p->link);
968 if(a != ATEXT && a != ABCASE)
969 if(q != nil && (q->mark&FOLL)) {
970 p->as = relinv(a);
971 p->link = p->pcond;
972 p->pcond = q;
973 }
974 xfol(ctxt, p->link, last);
975 q = brchain(ctxt, p->pcond);
976 if(q == nil)
977 q = p->pcond;
978 if(q->mark&FOLL) {
979 p->pcond = q;
980 return;
981 }
982 p = q;
983 goto loop;
984 }
985 p = p->link;
986 goto loop;
987 }
988
989 LinkArch linkarm = {
990 .name = "arm",
991 .thechar = '5',
992
993 .addstacksplit = addstacksplit,
994 .assemble = span5,
995 .datasize = datasize,
996 .follow = follow,
997 .iscall = iscall,
998 .isdata = isdata,
999 .prg = prg,
1000 .progedit = progedit,
1001 .settextflag = settextflag,
1002 .symtype = symtype,
1003 .textflag = textflag,
1004
1005 .minlc = 4,
1006 .ptrsize = 4,
1007
1008 .D_ADDR = D_ADDR,
1009 .D_BRANCH = D_BRANCH,
1010 .D_CONST = D_CONST,
1011 .D_EXTERN = D_EXTERN,
1012 .D_FCONST = D_FCONST,
1013 .D_NONE = D_NONE,
1014 .D_PCREL = D_PCREL,
1015 .D_SCONST = D_SCONST,
1016 .D_SIZE = D_SIZE,
1017 .D_STATIC = D_STATIC,
1018
1019 .ACALL = ABL,
1020 .ADATA = ADATA,
1021 .AEND = AEND,
1022 .AFUNCDATA = AFUNCDATA,
1023 .AGLOBL = AGLOBL,
1024 .AJMP = AB,
1025 .ANOP = ANOP,
1026 .APCDATA = APCDATA,
1027 .ARET = ARET,
1028 .ATEXT = ATEXT,
1029 .ATYPE = ATYPE,
1030 .AUSEFIELD = AUSEFIELD,
1031 };
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b