~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/cmd/8l/pass.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-11-18 15:12:26 UTC
  • mfrom: (14.2.12 vivid-proposed)
  • Revision ID: package-import@ubuntu.com-20141118151226-zug7vn93mn3dtiz3
Tags: 2:1.3.2-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - Support co-installability with gccgo-go tool:
    - d/rules,golang-go.install: Rename bin/go -> bin/golang-go
    - d/golang-go.{postinst,prerm}: Install/remove /usr/bin/go using
      alternatives.
  - d/copyright: Amendments for full compiliance with copyright format.
  - d/control: Demote golang-go.tools to Suggests to support Ubuntu MIR.
  - dropped patches (now upstream):
    - d/p/issue27650045_40001_50001.diff
    - d/p/issue28050043_60001_70001.diff
    - d/p/issue54790044_100001_110001.diff

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Inferno utils/8l/pass.c
2
 
// http://code.google.com/p/inferno-os/source/browse/utils/8l/pass.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.vitanuova.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
 
// Code and data passes.
32
 
 
33
 
#include        "l.h"
34
 
#include        "../ld/lib.h"
35
 
#include "../../pkg/runtime/stack.h"
36
 
 
37
 
static void xfol(Prog*, Prog**);
38
 
 
39
 
Prog*
40
 
brchain(Prog *p)
41
 
{
42
 
        int i;
43
 
 
44
 
        for(i=0; i<20; i++) {
45
 
                if(p == P || p->as != AJMP)
46
 
                        return p;
47
 
                p = p->pcond;
48
 
        }
49
 
        return P;
50
 
}
51
 
 
52
 
void
53
 
follow(void)
54
 
{
55
 
        Prog *firstp, *lastp;
56
 
 
57
 
        if(debug['v'])
58
 
                Bprint(&bso, "%5.2f follow\n", cputime());
59
 
        Bflush(&bso);
60
 
        
61
 
        for(cursym = textp; cursym != nil; cursym = cursym->next) {
62
 
                firstp = prg();
63
 
                lastp = firstp;
64
 
                xfol(cursym->text, &lastp);
65
 
                lastp->link = nil;
66
 
                cursym->text = firstp->link;
67
 
        }
68
 
}
69
 
 
70
 
static int
71
 
nofollow(int a)
72
 
{
73
 
        switch(a) {
74
 
        case AJMP:
75
 
        case ARET:
76
 
        case AIRETL:
77
 
        case AIRETW:
78
 
        case AUNDEF:
79
 
                return 1;
80
 
        }
81
 
        return 0;
82
 
}
83
 
 
84
 
static int
85
 
pushpop(int a)
86
 
{
87
 
        switch(a) {
88
 
        case APUSHL:
89
 
        case APUSHFL:
90
 
        case APUSHW:
91
 
        case APUSHFW:
92
 
        case APOPL:
93
 
        case APOPFL:
94
 
        case APOPW:
95
 
        case APOPFW:
96
 
                return 1;
97
 
        }
98
 
        return 0;
99
 
}
100
 
 
101
 
static void
102
 
xfol(Prog *p, Prog **last)
103
 
{
104
 
        Prog *q;
105
 
        int i;
106
 
        enum as a;
107
 
 
108
 
loop:
109
 
        if(p == P)
110
 
                return;
111
 
        if(p->as == AJMP)
112
 
        if((q = p->pcond) != P && q->as != ATEXT) {
113
 
                /* mark instruction as done and continue layout at target of jump */
114
 
                p->mark = 1;
115
 
                p = q;
116
 
                if(p->mark == 0)
117
 
                        goto loop;
118
 
        }
119
 
        if(p->mark) {
120
 
                /* 
121
 
                 * p goes here, but already used it elsewhere.
122
 
                 * copy up to 4 instructions or else branch to other copy.
123
 
                 */
124
 
                for(i=0,q=p; i<4; i++,q=q->link) {
125
 
                        if(q == P)
126
 
                                break;
127
 
                        if(q == *last)
128
 
                                break;
129
 
                        a = q->as;
130
 
                        if(a == ANOP) {
131
 
                                i--;
132
 
                                continue;
133
 
                        }
134
 
                        if(nofollow(a) || pushpop(a))   
135
 
                                break;  // NOTE(rsc): arm does goto copy
136
 
                        if(q->pcond == P || q->pcond->mark)
137
 
                                continue;
138
 
                        if(a == ACALL || a == ALOOP)
139
 
                                continue;
140
 
                        for(;;) {
141
 
                                if(p->as == ANOP) {
142
 
                                        p = p->link;
143
 
                                        continue;
144
 
                                }
145
 
                                q = copyp(p);
146
 
                                p = p->link;
147
 
                                q->mark = 1;
148
 
                                (*last)->link = q;
149
 
                                *last = q;
150
 
                                if(q->as != a || q->pcond == P || q->pcond->mark)
151
 
                                        continue;
152
 
 
153
 
                                q->as = relinv(q->as);
154
 
                                p = q->pcond;
155
 
                                q->pcond = q->link;
156
 
                                q->link = p;
157
 
                                xfol(q->link, last);
158
 
                                p = q->link;
159
 
                                if(p->mark)
160
 
                                        return;
161
 
                                goto loop;
162
 
                        }
163
 
                } /* */
164
 
                q = prg();
165
 
                q->as = AJMP;
166
 
                q->line = p->line;
167
 
                q->to.type = D_BRANCH;
168
 
                q->to.offset = p->pc;
169
 
                q->pcond = p;
170
 
                p = q;
171
 
        }
172
 
        
173
 
        /* emit p */
174
 
        p->mark = 1;
175
 
        (*last)->link = p;
176
 
        *last = p;
177
 
        a = p->as;
178
 
 
179
 
        /* continue loop with what comes after p */
180
 
        if(nofollow(a))
181
 
                return;
182
 
        if(p->pcond != P && a != ACALL) {
183
 
                /*
184
 
                 * some kind of conditional branch.
185
 
                 * recurse to follow one path.
186
 
                 * continue loop on the other.
187
 
                 */
188
 
                if((q = brchain(p->pcond)) != P)
189
 
                        p->pcond = q;
190
 
                if((q = brchain(p->link)) != P)
191
 
                        p->link = q;
192
 
                if(p->from.type == D_CONST) {
193
 
                        if(p->from.offset == 1) {
194
 
                                /*
195
 
                                 * expect conditional jump to be taken.
196
 
                                 * rewrite so that's the fall-through case.
197
 
                                 */
198
 
                                p->as = relinv(a);
199
 
                                q = p->link;
200
 
                                p->link = p->pcond;
201
 
                                p->pcond = q;
202
 
                        }
203
 
                } else {
204
 
                        q = p->link;
205
 
                        if(q->mark)
206
 
                        if(a != ALOOP) {
207
 
                                p->as = relinv(a);
208
 
                                p->link = p->pcond;
209
 
                                p->pcond = q;
210
 
                        }
211
 
                }
212
 
                xfol(p->link, last);
213
 
                if(p->pcond->mark)
214
 
                        return;
215
 
                p = p->pcond;
216
 
                goto loop;
217
 
        }
218
 
        p = p->link;
219
 
        goto loop;
220
 
}
221
 
 
222
 
int
223
 
relinv(int a)
224
 
{
225
 
 
226
 
        switch(a) {
227
 
        case AJEQ:      return AJNE;
228
 
        case AJNE:      return AJEQ;
229
 
        case AJLE:      return AJGT;
230
 
        case AJLS:      return AJHI;
231
 
        case AJLT:      return AJGE;
232
 
        case AJMI:      return AJPL;
233
 
        case AJGE:      return AJLT;
234
 
        case AJPL:      return AJMI;
235
 
        case AJGT:      return AJLE;
236
 
        case AJHI:      return AJLS;
237
 
        case AJCS:      return AJCC;
238
 
        case AJCC:      return AJCS;
239
 
        case AJPS:      return AJPC;
240
 
        case AJPC:      return AJPS;
241
 
        case AJOS:      return AJOC;
242
 
        case AJOC:      return AJOS;
243
 
        }
244
 
        diag("unknown relation: %s in %s", anames[a], TNAME);
245
 
        return a;
246
 
}
247
 
 
248
 
void
249
 
patch(void)
250
 
{
251
 
        int32 c;
252
 
        Prog *p, *q;
253
 
        Sym *s;
254
 
        int32 vexit;
255
 
        Sym *plan9_tos;
256
 
 
257
 
        if(debug['v'])
258
 
                Bprint(&bso, "%5.2f mkfwd\n", cputime());
259
 
        Bflush(&bso);
260
 
        mkfwd();
261
 
        if(debug['v'])
262
 
                Bprint(&bso, "%5.2f patch\n", cputime());
263
 
        Bflush(&bso);
264
 
        s = lookup("exit", 0);
265
 
        vexit = s->value;
266
 
        
267
 
        plan9_tos = S;
268
 
        if(HEADTYPE == Hplan9x32)
269
 
                plan9_tos = lookup("_tos", 0);
270
 
        
271
 
        for(cursym = textp; cursym != nil; cursym = cursym->next) {
272
 
                for(p = cursym->text; p != P; p = p->link) {
273
 
                        if(HEADTYPE == Hwindows) {
274
 
                                // Convert
275
 
                                //   op   n(GS), reg
276
 
                                // to
277
 
                                //   MOVL 0x14(FS), reg
278
 
                                //   op   n(reg), reg
279
 
                                // The purpose of this patch is to fix some accesses
280
 
                                // to extern register variables (TLS) on Windows, as
281
 
                                // a different method is used to access them.
282
 
                                if(p->from.type == D_INDIR+D_GS
283
 
                                && p->to.type >= D_AX && p->to.type <= D_DI) {
284
 
                                        q = appendp(p);
285
 
                                        q->from = p->from;
286
 
                                        q->from.type = D_INDIR + p->to.type;
287
 
                                        q->to = p->to;
288
 
                                        q->as = p->as;
289
 
                                        p->as = AMOVL;
290
 
                                        p->from.type = D_INDIR+D_FS;
291
 
                                        p->from.offset = 0x14;
292
 
                                }
293
 
                        }
294
 
                        if(HEADTYPE == Hlinux) {
295
 
                                // Running binaries under Xen requires using
296
 
                                //      MOVL 0(GS), reg
297
 
                                // and then off(reg) instead of saying off(GS) directly
298
 
                                // when the offset is negative.
299
 
                                // In external mode we just produce a reloc.
300
 
                                if(p->from.type == D_INDIR+D_GS && p->from.offset < 0
301
 
                                && p->to.type >= D_AX && p->to.type <= D_DI) {
302
 
                                        if(linkmode != LinkExternal) {
303
 
                                                q = appendp(p);
304
 
                                                q->from = p->from;
305
 
                                                q->from.type = D_INDIR + p->to.type;
306
 
                                                q->to = p->to;
307
 
                                                q->as = p->as;
308
 
                                                p->as = AMOVL;
309
 
                                                p->from.type = D_INDIR+D_GS;
310
 
                                                p->from.offset = 0;
311
 
                                        } else {
312
 
                                                // Add signals to relocate.
313
 
                                                p->from.index = D_GS;
314
 
                                                p->from.scale = 1;
315
 
                                        }
316
 
                                }
317
 
                        }
318
 
                        if(HEADTYPE == Hplan9x32) {
319
 
                                if(p->from.type == D_INDIR+D_GS
320
 
                                && p->to.type >= D_AX && p->to.type <= D_DI) {
321
 
                                        q = appendp(p);
322
 
                                        q->from = p->from;
323
 
                                        q->from.type = D_INDIR + p->to.type;
324
 
                                        q->to = p->to;
325
 
                                        q->as = p->as;
326
 
                                        p->as = AMOVL;
327
 
                                        p->from.type = D_EXTERN;
328
 
                                        p->from.sym = plan9_tos;
329
 
                                        p->from.offset = 0;
330
 
                                }
331
 
                        }
332
 
                        if((p->as == ACALL && p->to.type != D_BRANCH) || (p->as == AJMP && p->to.type != D_BRANCH) || (p->as == ARET && p->to.sym != nil)) {
333
 
                                s = p->to.sym;
334
 
                                if(p->to.type == D_INDIR+D_ADDR) {
335
 
                                         /* skip check if this is an indirect call (CALL *symbol(SB)) */
336
 
                                         continue;
337
 
                                } else if(s) {
338
 
                                        if(debug['c'])
339
 
                                                Bprint(&bso, "%s calls %s\n", TNAME, s->name);
340
 
                                        if((s->type&SMASK) != STEXT) {
341
 
                                                /* diag prints TNAME first */
342
 
                                                diag("undefined: %s", s->name);
343
 
                                                s->type = STEXT;
344
 
                                                s->value = vexit;
345
 
                                                continue;       // avoid more error messages
346
 
                                        }
347
 
                                        if(s->text == nil)
348
 
                                                continue;
349
 
                                        p->to.type = D_BRANCH;
350
 
                                        p->to.offset = s->text->pc;
351
 
                                        p->pcond = s->text;
352
 
                                        continue;
353
 
                                }
354
 
                        }
355
 
                        if(p->to.type != D_BRANCH)
356
 
                                continue;
357
 
                        c = p->to.offset;
358
 
                        for(q = cursym->text; q != P;) {
359
 
                                if(c == q->pc)
360
 
                                        break;
361
 
                                if(q->forwd != P && c >= q->forwd->pc)
362
 
                                        q = q->forwd;
363
 
                                else
364
 
                                        q = q->link;
365
 
                        }
366
 
                        if(q == P) {
367
 
                                diag("branch out of range in %s (%#ux)\n%P [%s]",
368
 
                                        TNAME, c, p, p->to.sym ? p->to.sym->name : "<nil>");
369
 
                                p->to.type = D_NONE;
370
 
                        }
371
 
                        p->pcond = q;
372
 
                }
373
 
        }
374
 
 
375
 
        for(cursym = textp; cursym != nil; cursym = cursym->next) {
376
 
                if(cursym->text == nil || cursym->p != nil)
377
 
                        continue;
378
 
 
379
 
                for(p = cursym->text; p != P; p = p->link) {
380
 
                        p->mark = 0;    /* initialization for follow */
381
 
                        if(p->pcond != P) {
382
 
                                p->pcond = brloop(p->pcond);
383
 
                                if(p->pcond != P)
384
 
                                if(p->to.type == D_BRANCH)
385
 
                                        p->to.offset = p->pcond->pc;
386
 
                        }
387
 
                }
388
 
        }
389
 
}
390
 
 
391
 
Prog*
392
 
brloop(Prog *p)
393
 
{
394
 
        int c;
395
 
        Prog *q;
396
 
 
397
 
        c = 0;
398
 
        for(q = p; q != P; q = q->pcond) {
399
 
                if(q->as != AJMP)
400
 
                        break;
401
 
                c++;
402
 
                if(c >= 5000)
403
 
                        return P;
404
 
        }
405
 
        return q;
406
 
}
407
 
 
408
 
static Prog*    load_g_cx(Prog*);
409
 
static Prog*    stacksplit(Prog*, int32, Prog**);
410
 
 
411
 
static Sym *plan9_tos;
412
 
static Prog *pmorestack;
413
 
static Sym *symmorestack;
414
 
 
415
 
void
416
 
dostkoff(void)
417
 
{
418
 
        Prog *p, *q;
419
 
        int32 autoffset, deltasp;
420
 
        int a;
421
 
 
422
 
        pmorestack = P;
423
 
        symmorestack = lookup("runtime.morestack", 0);
424
 
 
425
 
        if(symmorestack->type != STEXT)
426
 
                diag("runtime.morestack not defined");
427
 
        else {
428
 
                pmorestack = symmorestack->text;
429
 
                symmorestack->text->from.scale |= NOSPLIT;
430
 
        }
431
 
        
432
 
        plan9_tos = S;
433
 
        if(HEADTYPE == Hplan9x32)
434
 
                plan9_tos = lookup("_tos", 0);
435
 
 
436
 
        for(cursym = textp; cursym != nil; cursym = cursym->next) {
437
 
                if(cursym->text == nil || cursym->text->link == nil)
438
 
                        continue;
439
 
 
440
 
                p = cursym->text;
441
 
                autoffset = p->to.offset;
442
 
                if(autoffset < 0)
443
 
                        autoffset = 0;
444
 
 
445
 
                q = P;
446
 
 
447
 
                if(!(p->from.scale & NOSPLIT) || (p->from.scale & WRAPPER)) {
448
 
                        p = appendp(p);
449
 
                        p = load_g_cx(p); // load g into CX
450
 
                }
451
 
                if(!(cursym->text->from.scale & NOSPLIT))
452
 
                        p = stacksplit(p, autoffset, &q); // emit split check
453
 
 
454
 
                if(autoffset) {
455
 
                        p = appendp(p);
456
 
                        p->as = AADJSP;
457
 
                        p->from.type = D_CONST;
458
 
                        p->from.offset = autoffset;
459
 
                        p->spadj = autoffset;
460
 
                } else {
461
 
                        // zero-byte stack adjustment.
462
 
                        // Insert a fake non-zero adjustment so that stkcheck can
463
 
                        // recognize the end of the stack-splitting prolog.
464
 
                        p = appendp(p);
465
 
                        p->as = ANOP;
466
 
                        p->spadj = -PtrSize;
467
 
                        p = appendp(p);
468
 
                        p->as = ANOP;
469
 
                        p->spadj = PtrSize;
470
 
                }
471
 
                if(q != P)
472
 
                        q->pcond = p;
473
 
                deltasp = autoffset;
474
 
                
475
 
                if(cursym->text->from.scale & WRAPPER) {
476
 
                        // g->panicwrap += autoffset + PtrSize;
477
 
                        p = appendp(p);
478
 
                        p->as = AADDL;
479
 
                        p->from.type = D_CONST;
480
 
                        p->from.offset = autoffset + PtrSize;
481
 
                        p->to.type = D_INDIR+D_CX;
482
 
                        p->to.offset = 2*PtrSize;
483
 
                }
484
 
                
485
 
                if(debug['Z'] && autoffset && !(cursym->text->from.scale&NOSPLIT)) {
486
 
                        // 8l -Z means zero the stack frame on entry.
487
 
                        // This slows down function calls but can help avoid
488
 
                        // false positives in garbage collection.
489
 
                        p = appendp(p);
490
 
                        p->as = AMOVL;
491
 
                        p->from.type = D_SP;
492
 
                        p->to.type = D_DI;
493
 
                        
494
 
                        p = appendp(p);
495
 
                        p->as = AMOVL;
496
 
                        p->from.type = D_CONST;
497
 
                        p->from.offset = autoffset/4;
498
 
                        p->to.type = D_CX;
499
 
                        
500
 
                        p = appendp(p);
501
 
                        p->as = AMOVL;
502
 
                        p->from.type = D_CONST;
503
 
                        p->from.offset = 0;
504
 
                        p->to.type = D_AX;
505
 
                        
506
 
                        p = appendp(p);
507
 
                        p->as = AREP;
508
 
                        
509
 
                        p = appendp(p);
510
 
                        p->as = ASTOSL;
511
 
                }
512
 
                
513
 
                for(; p != P; p = p->link) {
514
 
                        a = p->from.type;
515
 
                        if(a == D_AUTO)
516
 
                                p->from.offset += deltasp;
517
 
                        if(a == D_PARAM)
518
 
                                p->from.offset += deltasp + 4;
519
 
                        a = p->to.type;
520
 
                        if(a == D_AUTO)
521
 
                                p->to.offset += deltasp;
522
 
                        if(a == D_PARAM)
523
 
                                p->to.offset += deltasp + 4;
524
 
        
525
 
                        switch(p->as) {
526
 
                        default:
527
 
                                continue;
528
 
                        case APUSHL:
529
 
                        case APUSHFL:
530
 
                                deltasp += 4;
531
 
                                p->spadj = 4;
532
 
                                continue;
533
 
                        case APUSHW:
534
 
                        case APUSHFW:
535
 
                                deltasp += 2;
536
 
                                p->spadj = 2;
537
 
                                continue;
538
 
                        case APOPL:
539
 
                        case APOPFL:
540
 
                                deltasp -= 4;
541
 
                                p->spadj = -4;
542
 
                                continue;
543
 
                        case APOPW:
544
 
                        case APOPFW:
545
 
                                deltasp -= 2;
546
 
                                p->spadj = -2;
547
 
                                continue;
548
 
                        case ARET:
549
 
                                break;
550
 
                        }
551
 
        
552
 
                        if(autoffset != deltasp)
553
 
                                diag("unbalanced PUSH/POP");
554
 
 
555
 
                        if(cursym->text->from.scale & WRAPPER) {
556
 
                                p = load_g_cx(p);
557
 
                                p = appendp(p);
558
 
                                // g->panicwrap -= autoffset + PtrSize;
559
 
                                p->as = ASUBL;
560
 
                                p->from.type = D_CONST;
561
 
                                p->from.offset = autoffset + PtrSize;
562
 
                                p->to.type = D_INDIR+D_CX;
563
 
                                p->to.offset = 2*PtrSize;
564
 
                                p = appendp(p);
565
 
                                p->as = ARET;
566
 
                        }
567
 
        
568
 
                        if(autoffset) {
569
 
                                p->as = AADJSP;
570
 
                                p->from.type = D_CONST;
571
 
                                p->from.offset = -autoffset;
572
 
                                p->spadj = -autoffset;
573
 
                                p = appendp(p);
574
 
                                p->as = ARET;
575
 
                                // If there are instructions following
576
 
                                // this ARET, they come from a branch
577
 
                                // with the same stackframe, so undo
578
 
                                // the cleanup.
579
 
                                p->spadj = +autoffset;
580
 
                        }
581
 
                        if(p->to.sym) // retjmp
582
 
                                p->as = AJMP;
583
 
                }
584
 
        }
585
 
}
586
 
 
587
 
// Append code to p to load g into cx.
588
 
// Overwrites p with the first instruction (no first appendp).
589
 
// Overwriting p is unusual but it lets use this in both the
590
 
// prologue (caller must call appendp first) and in the epilogue.
591
 
// Returns last new instruction.
592
 
static Prog*
593
 
load_g_cx(Prog *p)
594
 
{
595
 
        switch(HEADTYPE) {
596
 
        case Hwindows:
597
 
                p->as = AMOVL;
598
 
                p->from.type = D_INDIR+D_FS;
599
 
                p->from.offset = 0x14;
600
 
                p->to.type = D_CX;
601
 
 
602
 
                p = appendp(p);
603
 
                p->as = AMOVL;
604
 
                p->from.type = D_INDIR+D_CX;
605
 
                p->from.offset = 0;
606
 
                p->to.type = D_CX;
607
 
                break;
608
 
        
609
 
        case Hlinux:
610
 
                if(linkmode != LinkExternal) {
611
 
                        p->as = AMOVL;
612
 
                        p->from.type = D_INDIR+D_GS;
613
 
                        p->from.offset = 0;
614
 
                        p->to.type = D_CX;
615
 
 
616
 
                        p = appendp(p);
617
 
                        p->as = AMOVL;
618
 
                        p->from.type = D_INDIR+D_CX;
619
 
                        p->from.offset = tlsoffset + 0;
620
 
                        p->to.type = D_CX;
621
 
                } else {
622
 
                        p->as = AMOVL;
623
 
                        p->from.type = D_INDIR+D_GS;
624
 
                        p->from.offset = tlsoffset + 0;
625
 
                        p->to.type = D_CX;
626
 
                        p->from.index = D_GS;
627
 
                        p->from.scale = 1;
628
 
                }
629
 
                break;
630
 
        
631
 
        case Hplan9x32:
632
 
                p->as = AMOVL;
633
 
                p->from.type = D_EXTERN;
634
 
                p->from.sym = plan9_tos;
635
 
                p->to.type = D_CX;
636
 
                
637
 
                p = appendp(p);
638
 
                p->as = AMOVL;
639
 
                p->from.type = D_INDIR+D_CX;
640
 
                p->from.offset = tlsoffset + 0;
641
 
                p->to.type = D_CX;                              
642
 
                break;
643
 
        
644
 
        default:
645
 
                p->as = AMOVL;
646
 
                p->from.type = D_INDIR+D_GS;
647
 
                p->from.offset = tlsoffset + 0;
648
 
                p->to.type = D_CX;
649
 
        }
650
 
        return p;
651
 
}
652
 
 
653
 
// Append code to p to check for stack split.
654
 
// Appends to (does not overwrite) p.
655
 
// Assumes g is in CX.
656
 
// Returns last new instruction.
657
 
// On return, *jmpok is the instruction that should jump
658
 
// to the stack frame allocation if no split is needed.
659
 
static Prog*
660
 
stacksplit(Prog *p, int32 framesize, Prog **jmpok)
661
 
{
662
 
        Prog *q, *q1;
663
 
        int arg;
664
 
 
665
 
        if(debug['K']) {
666
 
                // 8l -K means check not only for stack
667
 
                // overflow but stack underflow.
668
 
                // On underflow, INT 3 (breakpoint).
669
 
                // Underflow itself is rare but this also
670
 
                // catches out-of-sync stack guard info.
671
 
                p = appendp(p);
672
 
                p->as = ACMPL;
673
 
                p->from.type = D_INDIR+D_CX;
674
 
                p->from.offset = 4;
675
 
                p->to.type = D_SP;
676
 
 
677
 
                p = appendp(p);
678
 
                p->as = AJCC;
679
 
                p->to.type = D_BRANCH;
680
 
                p->to.offset = 4;
681
 
                q1 = p;
682
 
 
683
 
                p = appendp(p);
684
 
                p->as = AINT;
685
 
                p->from.type = D_CONST;
686
 
                p->from.offset = 3;
687
 
                
688
 
                p = appendp(p);
689
 
                p->as = ANOP;
690
 
                q1->pcond = p;
691
 
        }
692
 
        q1 = P;
693
 
 
694
 
        if(framesize <= StackSmall) {
695
 
                // small stack: SP <= stackguard
696
 
                //      CMPL SP, stackguard
697
 
                p = appendp(p);
698
 
                p->as = ACMPL;
699
 
                p->from.type = D_SP;
700
 
                p->to.type = D_INDIR+D_CX;
701
 
        } else if(framesize <= StackBig) {
702
 
                // large stack: SP-framesize <= stackguard-StackSmall
703
 
                //      LEAL -(framesize-StackSmall)(SP), AX
704
 
                //      CMPL AX, stackguard
705
 
                p = appendp(p);
706
 
                p->as = ALEAL;
707
 
                p->from.type = D_INDIR+D_SP;
708
 
                p->from.offset = -(framesize-StackSmall);
709
 
                p->to.type = D_AX;
710
 
 
711
 
                p = appendp(p);
712
 
                p->as = ACMPL;
713
 
                p->from.type = D_AX;
714
 
                p->to.type = D_INDIR+D_CX;
715
 
        } else {
716
 
                // Such a large stack we need to protect against wraparound
717
 
                // if SP is close to zero.
718
 
                //      SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
719
 
                // The +StackGuard on both sides is required to keep the left side positive:
720
 
                // SP is allowed to be slightly below stackguard. See stack.h.
721
 
                //
722
 
                // Preemption sets stackguard to StackPreempt, a very large value.
723
 
                // That breaks the math above, so we have to check for that explicitly.
724
 
                //      MOVL    stackguard, CX
725
 
                //      CMPL    CX, $StackPreempt
726
 
                //      JEQ     label-of-call-to-morestack
727
 
                //      LEAL    StackGuard(SP), AX
728
 
                //      SUBL    stackguard, AX
729
 
                //      CMPL    AX, $(framesize+(StackGuard-StackSmall))
730
 
                p = appendp(p);
731
 
                p->as = AMOVL;
732
 
                p->from.type = D_INDIR+D_CX;
733
 
                p->from.offset = 0;
734
 
                p->to.type = D_SI;
735
 
 
736
 
                p = appendp(p);
737
 
                p->as = ACMPL;
738
 
                p->from.type = D_SI;
739
 
                p->to.type = D_CONST;
740
 
                p->to.offset = (uint32)StackPreempt;
741
 
 
742
 
                p = appendp(p);
743
 
                p->as = AJEQ;
744
 
                p->to.type = D_BRANCH;
745
 
                q1 = p;
746
 
 
747
 
                p = appendp(p);
748
 
                p->as = ALEAL;
749
 
                p->from.type = D_INDIR+D_SP;
750
 
                p->from.offset = StackGuard;
751
 
                p->to.type = D_AX;
752
 
                
753
 
                p = appendp(p);
754
 
                p->as = ASUBL;
755
 
                p->from.type = D_SI;
756
 
                p->from.offset = 0;
757
 
                p->to.type = D_AX;
758
 
                
759
 
                p = appendp(p);
760
 
                p->as = ACMPL;
761
 
                p->from.type = D_AX;
762
 
                p->to.type = D_CONST;
763
 
                p->to.offset = framesize+(StackGuard-StackSmall);
764
 
        }               
765
 
                        
766
 
        // common
767
 
        p = appendp(p);
768
 
        p->as = AJHI;
769
 
        p->to.type = D_BRANCH;
770
 
        p->to.offset = 4;
771
 
        q = p;
772
 
 
773
 
        p = appendp(p); // save frame size in DI
774
 
        p->as = AMOVL;
775
 
        p->to.type = D_DI;
776
 
        p->from.type = D_CONST;
777
 
 
778
 
        // If we ask for more stack, we'll get a minimum of StackMin bytes.
779
 
        // We need a stack frame large enough to hold the top-of-stack data,
780
 
        // the function arguments+results, our caller's PC, our frame,
781
 
        // a word for the return PC of the next call, and then the StackLimit bytes
782
 
        // that must be available on entry to any function called from a function
783
 
        // that did a stack check.  If StackMin is enough, don't ask for a specific
784
 
        // amount: then we can use the custom functions and save a few
785
 
        // instructions.
786
 
        if(StackTop + cursym->text->to.offset2 + PtrSize + framesize + PtrSize + StackLimit >= StackMin)
787
 
                p->from.offset = (framesize+7) & ~7LL;
788
 
 
789
 
        arg = cursym->text->to.offset2;
790
 
        if(arg == 1) // special marker for known 0
791
 
                arg = 0;
792
 
        if(arg&3)
793
 
                diag("misaligned argument size in stack split");
794
 
        p = appendp(p); // save arg size in AX
795
 
        p->as = AMOVL;
796
 
        p->to.type = D_AX;
797
 
        p->from.type = D_CONST;
798
 
        p->from.offset = arg;
799
 
 
800
 
        p = appendp(p);
801
 
        p->as = ACALL;
802
 
        p->to.type = D_BRANCH;
803
 
        p->pcond = pmorestack;
804
 
        p->to.sym = symmorestack;
805
 
 
806
 
        p = appendp(p);
807
 
        p->as = AJMP;
808
 
        p->to.type = D_BRANCH;
809
 
        p->pcond = cursym->text->link;
810
 
 
811
 
        if(q != P)
812
 
                q->pcond = p->link;
813
 
        if(q1 != P)
814
 
                q1->pcond = q->link;
815
 
        
816
 
        *jmpok = q;
817
 
        return p;
818
 
}
819
 
 
820
 
int32
821
 
atolwhex(char *s)
822
 
{
823
 
        int32 n;
824
 
        int f;
825
 
 
826
 
        n = 0;
827
 
        f = 0;
828
 
        while(*s == ' ' || *s == '\t')
829
 
                s++;
830
 
        if(*s == '-' || *s == '+') {
831
 
                if(*s++ == '-')
832
 
                        f = 1;
833
 
                while(*s == ' ' || *s == '\t')
834
 
                        s++;
835
 
        }
836
 
        if(s[0]=='0' && s[1]){
837
 
                if(s[1]=='x' || s[1]=='X'){
838
 
                        s += 2;
839
 
                        for(;;){
840
 
                                if(*s >= '0' && *s <= '9')
841
 
                                        n = n*16 + *s++ - '0';
842
 
                                else if(*s >= 'a' && *s <= 'f')
843
 
                                        n = n*16 + *s++ - 'a' + 10;
844
 
                                else if(*s >= 'A' && *s <= 'F')
845
 
                                        n = n*16 + *s++ - 'A' + 10;
846
 
                                else
847
 
                                        break;
848
 
                        }
849
 
                } else
850
 
                        while(*s >= '0' && *s <= '7')
851
 
                                n = n*8 + *s++ - '0';
852
 
        } else
853
 
                while(*s >= '0' && *s <= '9')
854
 
                        n = n*10 + *s++ - '0';
855
 
        if(f)
856
 
                n = -n;
857
 
        return n;
858
 
}