diff options
Diffstat (limited to 'src/cmd/6l/pass.c')
-rw-r--r-- | src/cmd/6l/pass.c | 991 |
1 files changed, 0 insertions, 991 deletions
diff --git a/src/cmd/6l/pass.c b/src/cmd/6l/pass.c deleted file mode 100644 index 1be3c18fe..000000000 --- a/src/cmd/6l/pass.c +++ /dev/null @@ -1,991 +0,0 @@ -// Inferno utils/6l/pass.c -// http://code.google.com/p/inferno-os/source/browse/utils/6l/pass.c -// -// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. -// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) -// Portions Copyright © 1997-1999 Vita Nuova Limited -// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) -// Portions Copyright © 2004,2006 Bruce Ellis -// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) -// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others -// Portions Copyright © 2009 The Go Authors. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -// Code and data passes. - -#include "l.h" -#include "../ld/lib.h" -#include "../../pkg/runtime/stack.h" - -static void xfol(Prog*, Prog**); - -Prog* -brchain(Prog *p) -{ - int i; - - for(i=0; i<20; i++) { - if(p == P || p->as != AJMP) - return p; - p = p->pcond; - } - return P; -} - -void -follow(void) -{ - Prog *firstp, *lastp; - - if(debug['v']) - Bprint(&bso, "%5.2f follow\n", cputime()); - Bflush(&bso); - - for(cursym = textp; cursym != nil; cursym = cursym->next) { - firstp = prg(); - lastp = firstp; - xfol(cursym->text, &lastp); - lastp->link = nil; - cursym->text = firstp->link; - } -} - -static int -nofollow(int a) -{ - switch(a) { - case AJMP: - case ARET: - case AIRETL: - case AIRETQ: - case AIRETW: - case ARETFL: - case ARETFQ: - case ARETFW: - case AUNDEF: - return 1; - } - return 0; -} - -static int -pushpop(int a) -{ - switch(a) { - case APUSHL: - case APUSHFL: - case APUSHQ: - case APUSHFQ: - case APUSHW: - case APUSHFW: - case APOPL: - case APOPFL: - case APOPQ: - case APOPFQ: - case APOPW: - case APOPFW: - return 1; - } - return 0; -} - -static void -xfol(Prog *p, Prog **last) -{ - Prog *q; - int i; - enum as a; - -loop: - if(p == P) - return; - if(p->as == AJMP) - if((q = p->pcond) != P && q->as != ATEXT) { - /* mark instruction as done and continue layout at target of jump */ - p->mark = 1; - p = q; - if(p->mark == 0) - goto loop; - } - if(p->mark) { - /* - * p goes here, but already used it elsewhere. - * copy up to 4 instructions or else branch to other copy. - */ - for(i=0,q=p; i<4; i++,q=q->link) { - if(q == P) - break; - if(q == *last) - break; - a = q->as; - if(a == ANOP) { - i--; - continue; - } - if(nofollow(a) || pushpop(a)) - break; // NOTE(rsc): arm does goto copy - if(q->pcond == P || q->pcond->mark) - continue; - if(a == ACALL || a == ALOOP) - continue; - for(;;) { - if(p->as == ANOP) { - p = p->link; - continue; - } - q = copyp(p); - p = p->link; - q->mark = 1; - (*last)->link = q; - *last = q; - if(q->as != a || q->pcond == P || q->pcond->mark) - continue; - - q->as = relinv(q->as); - p = q->pcond; - q->pcond = q->link; - q->link = p; - xfol(q->link, last); - p = q->link; - if(p->mark) - return; - goto loop; - } - } /* */ - q = prg(); - q->as = AJMP; - q->line = p->line; - q->to.type = D_BRANCH; - q->to.offset = p->pc; - q->pcond = p; - p = q; - } - - /* emit p */ - p->mark = 1; - (*last)->link = p; - *last = p; - a = p->as; - - /* continue loop with what comes after p */ - if(nofollow(a)) - return; - if(p->pcond != P && a != ACALL) { - /* - * some kind of conditional branch. - * recurse to follow one path. - * continue loop on the other. - */ - if((q = brchain(p->pcond)) != P) - p->pcond = q; - if((q = brchain(p->link)) != P) - p->link = q; - if(p->from.type == D_CONST) { - if(p->from.offset == 1) { - /* - * expect conditional jump to be taken. - * rewrite so that's the fall-through case. - */ - p->as = relinv(a); - q = p->link; - p->link = p->pcond; - p->pcond = q; - } - } else { - q = p->link; - if(q->mark) - if(a != ALOOP) { - p->as = relinv(a); - p->link = p->pcond; - p->pcond = q; - } - } - xfol(p->link, last); - if(p->pcond->mark) - return; - p = p->pcond; - goto loop; - } - p = p->link; - goto loop; -} - -Prog* -byteq(int v) -{ - Prog *p; - - p = prg(); - p->as = ABYTE; - p->from.type = D_CONST; - p->from.offset = v&0xff; - return p; -} - -int -relinv(int a) -{ - - switch(a) { - case AJEQ: return AJNE; - case AJNE: return AJEQ; - case AJLE: return AJGT; - case AJLS: return AJHI; - case AJLT: return AJGE; - case AJMI: return AJPL; - case AJGE: return AJLT; - case AJPL: return AJMI; - case AJGT: return AJLE; - case AJHI: return AJLS; - case AJCS: return AJCC; - case AJCC: return AJCS; - case AJPS: return AJPC; - case AJPC: return AJPS; - case AJOS: return AJOC; - case AJOC: return AJOS; - } - diag("unknown relation: %s in %s", anames[a], TNAME); - errorexit(); - return a; -} - -void -patch(void) -{ - int32 c; - Prog *p, *q; - Sym *s; - int32 vexit; - Sym *gmsym; - - if(debug['v']) - Bprint(&bso, "%5.2f mkfwd\n", cputime()); - Bflush(&bso); - mkfwd(); - if(debug['v']) - Bprint(&bso, "%5.2f patch\n", cputime()); - Bflush(&bso); - - if(flag_shared) { - s = lookup("init_array", 0); - s->type = SINITARR; - s->reachable = 1; - s->hide = 1; - addaddr(s, lookup(INITENTRY, 0)); - } - - gmsym = lookup("runtime.tlsgm", 0); - if(linkmode != LinkExternal) - gmsym->reachable = 0; - s = lookup("exit", 0); - vexit = s->value; - for(cursym = textp; cursym != nil; cursym = cursym->next) - for(p = cursym->text; p != P; p = p->link) { - if(HEADTYPE == Hwindows) { - // Windows - // Convert - // op n(GS), reg - // to - // MOVL 0x28(GS), reg - // op n(reg), reg - // The purpose of this patch is to fix some accesses - // to extern register variables (TLS) on Windows, as - // a different method is used to access them. - if(p->from.type == D_INDIR+D_GS - && p->to.type >= D_AX && p->to.type <= D_DI - && p->from.offset <= 8) { - q = appendp(p); - q->from = p->from; - q->from.type = D_INDIR + p->to.type; - q->to = p->to; - q->as = p->as; - p->as = AMOVQ; - p->from.type = D_INDIR+D_GS; - p->from.offset = 0x28; - } - } - if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd - || HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd - || HEADTYPE == Hplan9x64 || HEADTYPE == Hdragonfly) { - // ELF uses FS instead of GS. - if(p->from.type == D_INDIR+D_GS) - p->from.type = D_INDIR+D_FS; - if(p->to.type == D_INDIR+D_GS) - p->to.type = D_INDIR+D_FS; - if(p->from.index == D_GS) - p->from.index = D_FS; - if(p->to.index == D_GS) - p->to.index = D_FS; - } - if(!flag_shared) { - // Convert g() or m() accesses of the form - // op n(reg)(GS*1), reg - // to - // op n(GS*1), reg - if(p->from.index == D_FS || p->from.index == D_GS) { - p->from.type = D_INDIR + p->from.index; - p->from.index = D_NONE; - } - // Convert g() or m() accesses of the form - // op reg, n(reg)(GS*1) - // to - // op reg, n(GS*1) - if(p->to.index == D_FS || p->to.index == D_GS) { - p->to.type = D_INDIR + p->to.index; - p->to.index = D_NONE; - } - // Convert get_tls access of the form - // op runtime.tlsgm(SB), reg - // to - // NOP - if(gmsym != S && p->from.sym == gmsym) { - p->as = ANOP; - p->from.type = D_NONE; - p->to.type = D_NONE; - p->from.sym = nil; - p->to.sym = nil; - continue; - } - } else { - // Convert TLS reads of the form - // op n(GS), reg - // to - // MOVQ $runtime.tlsgm(SB), reg - // op n(reg)(GS*1), reg - if((p->from.type == D_INDIR+D_FS || p->from.type == D_INDIR + D_GS) && p->to.type >= D_AX && p->to.type <= D_DI) { - q = appendp(p); - q->to = p->to; - q->as = p->as; - q->from.type = D_INDIR+p->to.type; - q->from.index = p->from.type - D_INDIR; - q->from.scale = 1; - q->from.offset = p->from.offset; - p->as = AMOVQ; - p->from.type = D_EXTERN; - p->from.sym = gmsym; - p->from.offset = 0; - } - } - if(p->as == ACALL || (p->as == AJMP && p->to.type != D_BRANCH) || (p->as == ARET && p->to.sym != nil)) { - s = p->to.sym; - if(s) { - if(debug['c']) - Bprint(&bso, "%s calls %s\n", TNAME, s->name); - if((s->type&SMASK) != STEXT) { - /* diag prints TNAME first */ - diag("undefined: %s", s->name); - s->type = STEXT; - s->value = vexit; - continue; // avoid more error messages - } - if(s->text == nil) - continue; - p->to.type = D_BRANCH; - p->to.offset = s->text->pc; - p->pcond = s->text; - continue; - } - } - if(p->to.type != D_BRANCH) - continue; - c = p->to.offset; - for(q = cursym->text; q != P;) { - if(c == q->pc) - break; - if(q->forwd != P && c >= q->forwd->pc) - q = q->forwd; - else - q = q->link; - } - if(q == P) { - diag("branch out of range in %s (%#ux)\n%P [%s]", - TNAME, c, p, p->to.sym ? p->to.sym->name : "<nil>"); - p->to.type = D_NONE; - } - p->pcond = q; - } - - for(cursym = textp; cursym != nil; cursym = cursym->next) - for(p = cursym->text; p != P; p = p->link) { - p->mark = 0; /* initialization for follow */ - if(p->pcond != P) { - p->pcond = brloop(p->pcond); - if(p->pcond != P) - if(p->to.type == D_BRANCH) - p->to.offset = p->pcond->pc; - } - } -} - -Prog* -brloop(Prog *p) -{ - int c; - Prog *q; - - c = 0; - for(q = p; q != P; q = q->pcond) { - if(q->as != AJMP) - break; - c++; - if(c >= 5000) - return P; - } - return q; -} - -static char* -morename[] = -{ - "runtime.morestack00", - "runtime.morestack10", - "runtime.morestack01", - "runtime.morestack11", - - "runtime.morestack8", - "runtime.morestack16", - "runtime.morestack24", - "runtime.morestack32", - "runtime.morestack40", - "runtime.morestack48", -}; -Prog* pmorestack[nelem(morename)]; -Sym* symmorestack[nelem(morename)]; -Sym* gmsym; - -static Prog* load_g_cx(Prog*); -static Prog* stacksplit(Prog*, int32, Prog**); - -void -dostkoff(void) -{ - Prog *p, *q, *q1; - int32 autoffset, deltasp; - int a, pcsize; - uint32 i; - - gmsym = lookup("runtime.tlsgm", 0); - for(i=0; i<nelem(morename); i++) { - symmorestack[i] = lookup(morename[i], 0); - if(symmorestack[i]->type != STEXT) - diag("morestack trampoline not defined - %s", morename[i]); - pmorestack[i] = symmorestack[i]->text; - } - - for(cursym = textp; cursym != nil; cursym = cursym->next) { - if(cursym->text == nil || cursym->text->link == nil) - continue; - - p = cursym->text; - parsetextconst(p->to.offset); - autoffset = textstksiz; - if(autoffset < 0) - autoffset = 0; - - if(autoffset < StackSmall && !(p->from.scale & NOSPLIT)) { - for(q = p; q != P; q = q->link) - if(q->as == ACALL) - goto noleaf; - p->from.scale |= NOSPLIT; - noleaf:; - } - - if((p->from.scale & NOSPLIT) && autoffset >= StackSmall) - diag("nosplit func likely to overflow stack"); - - q = P; - if(!(p->from.scale & NOSPLIT) || (p->from.scale & WRAPPER)) { - p = appendp(p); - p = load_g_cx(p); // load g into CX - } - if(!(cursym->text->from.scale & NOSPLIT)) - p = stacksplit(p, autoffset, &q); // emit split check - - if(autoffset) { - p = appendp(p); - p->as = AADJSP; - p->from.type = D_CONST; - p->from.offset = autoffset; - p->spadj = autoffset; - } else { - // zero-byte stack adjustment. - // Insert a fake non-zero adjustment so that stkcheck can - // recognize the end of the stack-splitting prolog. - p = appendp(p); - p->as = ANOP; - p->spadj = -PtrSize; - p = appendp(p); - p->as = ANOP; - p->spadj = PtrSize; - } - if(q != P) - q->pcond = p; - deltasp = autoffset; - - if(cursym->text->from.scale & WRAPPER) { - // g->panicwrap += autoffset + PtrSize; - p = appendp(p); - p->as = AADDL; - p->from.type = D_CONST; - p->from.offset = autoffset + PtrSize; - p->to.type = D_INDIR+D_CX; - p->to.offset = 2*PtrSize; - } - - if(debug['K'] > 1 && autoffset) { - // 6l -KK means double-check for stack overflow - // even after calling morestack and even if the - // function is marked as nosplit. - p = appendp(p); - p->as = AMOVQ; - p->from.type = D_INDIR+D_CX; - p->from.offset = 0; - p->to.type = D_BX; - - p = appendp(p); - p->as = ASUBQ; - p->from.type = D_CONST; - p->from.offset = StackSmall+32; - p->to.type = D_BX; - - p = appendp(p); - p->as = ACMPQ; - p->from.type = D_SP; - p->to.type = D_BX; - - p = appendp(p); - p->as = AJHI; - p->to.type = D_BRANCH; - q1 = p; - - p = appendp(p); - p->as = AINT; - p->from.type = D_CONST; - p->from.offset = 3; - - p = appendp(p); - p->as = ANOP; - q1->pcond = p; - } - - if(debug['Z'] && autoffset && !(cursym->text->from.scale&NOSPLIT)) { - // 6l -Z means zero the stack frame on entry. - // This slows down function calls but can help avoid - // false positives in garbage collection. - p = appendp(p); - p->as = AMOVQ; - p->from.type = D_SP; - p->to.type = D_DI; - - p = appendp(p); - p->as = AMOVQ; - p->from.type = D_CONST; - p->from.offset = autoffset/8; - p->to.type = D_CX; - - p = appendp(p); - p->as = AMOVQ; - p->from.type = D_CONST; - p->from.offset = 0; - p->to.type = D_AX; - - p = appendp(p); - p->as = AREP; - - p = appendp(p); - p->as = ASTOSQ; - } - - for(; p != P; p = p->link) { - pcsize = p->mode/8; - a = p->from.type; - if(a == D_AUTO) - p->from.offset += deltasp; - if(a == D_PARAM) - p->from.offset += deltasp + pcsize; - a = p->to.type; - if(a == D_AUTO) - p->to.offset += deltasp; - if(a == D_PARAM) - p->to.offset += deltasp + pcsize; - - switch(p->as) { - default: - continue; - case APUSHL: - case APUSHFL: - deltasp += 4; - p->spadj = 4; - continue; - case APUSHQ: - case APUSHFQ: - deltasp += 8; - p->spadj = 8; - continue; - case APUSHW: - case APUSHFW: - deltasp += 2; - p->spadj = 2; - continue; - case APOPL: - case APOPFL: - deltasp -= 4; - p->spadj = -4; - continue; - case APOPQ: - case APOPFQ: - deltasp -= 8; - p->spadj = -8; - continue; - case APOPW: - case APOPFW: - deltasp -= 2; - p->spadj = -2; - continue; - case ARET: - break; - } - - if(autoffset != deltasp) - diag("unbalanced PUSH/POP"); - - if(cursym->text->from.scale & WRAPPER) { - p = load_g_cx(p); - p = appendp(p); - // g->panicwrap -= autoffset + PtrSize; - p->as = ASUBL; - p->from.type = D_CONST; - p->from.offset = autoffset + PtrSize; - p->to.type = D_INDIR+D_CX; - p->to.offset = 2*PtrSize; - p = appendp(p); - p->as = ARET; - } - - if(autoffset) { - p->as = AADJSP; - p->from.type = D_CONST; - p->from.offset = -autoffset; - p->spadj = -autoffset; - p = appendp(p); - p->as = ARET; - // If there are instructions following - // this ARET, they come from a branch - // with the same stackframe, so undo - // the cleanup. - p->spadj = +autoffset; - } - if(p->to.sym) // retjmp - p->as = AJMP; - } - } -} - -// Append code to p to load g into cx. -// Overwrites p with the first instruction (no first appendp). -// Overwriting p is unusual but it lets use this in both the -// prologue (caller must call appendp first) and in the epilogue. -// Returns last new instruction. -static Prog* -load_g_cx(Prog *p) -{ - if(flag_shared) { - // Load TLS offset with MOVQ $runtime.tlsgm(SB), CX - p->as = AMOVQ; - p->from.type = D_EXTERN; - p->from.sym = gmsym; - p->to.type = D_CX; - p = appendp(p); - } - p->as = AMOVQ; - if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd - || HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd - || HEADTYPE == Hplan9x64 || HEADTYPE == Hdragonfly) - // ELF uses FS - p->from.type = D_INDIR+D_FS; - else - p->from.type = D_INDIR+D_GS; - if(flag_shared) { - // Add TLS offset stored in CX - p->from.index = p->from.type - D_INDIR; - p->from.type = D_INDIR + D_CX; - } - p->from.offset = tlsoffset+0; - p->to.type = D_CX; - if(HEADTYPE == Hwindows) { - // movq %gs:0x28, %rcx - // movq (%rcx), %rcx - p->as = AMOVQ; - p->from.type = D_INDIR+D_GS; - p->from.offset = 0x28; - p->to.type = D_CX; - - p = appendp(p); - p->as = AMOVQ; - p->from.type = D_INDIR+D_CX; - p->from.offset = 0; - p->to.type = D_CX; - } - return p; -} - -// Append code to p to check for stack split. -// Appends to (does not overwrite) p. -// Assumes g is in CX. -// Returns last new instruction. -// On return, *jmpok is the instruction that should jump -// to the stack frame allocation if no split is needed. -static Prog* -stacksplit(Prog *p, int32 framesize, Prog **jmpok) -{ - Prog *q, *q1; - uint32 moreconst1, moreconst2, i; - - if(debug['K']) { - // 6l -K means check not only for stack - // overflow but stack underflow. - // On underflow, INT 3 (breakpoint). - // Underflow itself is rare but this also - // catches out-of-sync stack guard info - - p = appendp(p); - p->as = ACMPQ; - p->from.type = D_INDIR+D_CX; - p->from.offset = 8; - p->to.type = D_SP; - - p = appendp(p); - p->as = AJHI; - p->to.type = D_BRANCH; - p->to.offset = 4; - q1 = p; - - p = appendp(p); - p->as = AINT; - p->from.type = D_CONST; - p->from.offset = 3; - - p = appendp(p); - p->as = ANOP; - q1->pcond = p; - } - - q = P; - q1 = P; - if(framesize <= StackSmall) { - // small stack: SP <= stackguard - // CMPQ SP, stackguard - p = appendp(p); - p->as = ACMPQ; - p->from.type = D_SP; - p->to.type = D_INDIR+D_CX; - } else if(framesize <= StackBig) { - // large stack: SP-framesize <= stackguard-StackSmall - // LEAQ -xxx(SP), AX - // CMPQ AX, stackguard - p = appendp(p); - p->as = ALEAQ; - p->from.type = D_INDIR+D_SP; - p->from.offset = -(framesize-StackSmall); - p->to.type = D_AX; - - p = appendp(p); - p->as = ACMPQ; - p->from.type = D_AX; - p->to.type = D_INDIR+D_CX; - } else { - // Such a large stack we need to protect against wraparound. - // If SP is close to zero: - // SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall) - // The +StackGuard on both sides is required to keep the left side positive: - // SP is allowed to be slightly below stackguard. See stack.h. - // - // Preemption sets stackguard to StackPreempt, a very large value. - // That breaks the math above, so we have to check for that explicitly. - // MOVQ stackguard, CX - // CMPQ CX, $StackPreempt - // JEQ label-of-call-to-morestack - // LEAQ StackGuard(SP), AX - // SUBQ CX, AX - // CMPQ AX, $(framesize+(StackGuard-StackSmall)) - - p = appendp(p); - p->as = AMOVQ; - p->from.type = D_INDIR+D_CX; - p->from.offset = 0; - p->to.type = D_SI; - - p = appendp(p); - p->as = ACMPQ; - p->from.type = D_SI; - p->to.type = D_CONST; - p->to.offset = StackPreempt; - - p = appendp(p); - p->as = AJEQ; - p->to.type = D_BRANCH; - q1 = p; - - p = appendp(p); - p->as = ALEAQ; - p->from.type = D_INDIR+D_SP; - p->from.offset = StackGuard; - p->to.type = D_AX; - - p = appendp(p); - p->as = ASUBQ; - p->from.type = D_SI; - p->to.type = D_AX; - - p = appendp(p); - p->as = ACMPQ; - p->from.type = D_AX; - p->to.type = D_CONST; - p->to.offset = framesize+(StackGuard-StackSmall); - } - - // common - p = appendp(p); - p->as = AJHI; - p->to.type = D_BRANCH; - q = p; - - // If we ask for more stack, we'll get a minimum of StackMin bytes. - // We need a stack frame large enough to hold the top-of-stack data, - // the function arguments+results, our caller's PC, our frame, - // a word for the return PC of the next call, and then the StackLimit bytes - // that must be available on entry to any function called from a function - // that did a stack check. If StackMin is enough, don't ask for a specific - // amount: then we can use the custom functions and save a few - // instructions. - moreconst1 = 0; - if(StackTop + textarg + PtrSize + framesize + PtrSize + StackLimit >= StackMin) - moreconst1 = framesize; - moreconst2 = textarg; - if(moreconst2 == 1) // special marker - moreconst2 = 0; - if((moreconst2&7) != 0) - diag("misaligned argument size in stack split"); - // 4 varieties varieties (const1==0 cross const2==0) - // and 6 subvarieties of (const1==0 and const2!=0) - p = appendp(p); - if(moreconst1 == 0 && moreconst2 == 0) { - p->as = ACALL; - p->to.type = D_BRANCH; - p->pcond = pmorestack[0]; - p->to.sym = symmorestack[0]; - } else - if(moreconst1 != 0 && moreconst2 == 0) { - p->as = AMOVL; - p->from.type = D_CONST; - p->from.offset = moreconst1; - p->to.type = D_AX; - - p = appendp(p); - p->as = ACALL; - p->to.type = D_BRANCH; - p->pcond = pmorestack[1]; - p->to.sym = symmorestack[1]; - } else - if(moreconst1 == 0 && moreconst2 <= 48 && moreconst2%8 == 0) { - i = moreconst2/8 + 3; - p->as = ACALL; - p->to.type = D_BRANCH; - p->pcond = pmorestack[i]; - p->to.sym = symmorestack[i]; - } else - if(moreconst1 == 0 && moreconst2 != 0) { - p->as = AMOVL; - p->from.type = D_CONST; - p->from.offset = moreconst2; - p->to.type = D_AX; - - p = appendp(p); - p->as = ACALL; - p->to.type = D_BRANCH; - p->pcond = pmorestack[2]; - p->to.sym = symmorestack[2]; - } else { - p->as = AMOVQ; - p->from.type = D_CONST; - p->from.offset = (uint64)moreconst2 << 32; - p->from.offset |= moreconst1; - p->to.type = D_AX; - - p = appendp(p); - p->as = ACALL; - p->to.type = D_BRANCH; - p->pcond = pmorestack[3]; - p->to.sym = symmorestack[3]; - } - - p = appendp(p); - p->as = AJMP; - p->to.type = D_BRANCH; - p->pcond = cursym->text->link; - - if(q != P) - q->pcond = p->link; - if(q1 != P) - q1->pcond = q->link; - - *jmpok = q; - return p; -} - -vlong -atolwhex(char *s) -{ - vlong n; - int f; - - n = 0; - f = 0; - while(*s == ' ' || *s == '\t') - s++; - if(*s == '-' || *s == '+') { - if(*s++ == '-') - f = 1; - while(*s == ' ' || *s == '\t') - s++; - } - if(s[0]=='0' && s[1]){ - if(s[1]=='x' || s[1]=='X'){ - s += 2; - for(;;){ - if(*s >= '0' && *s <= '9') - n = n*16 + *s++ - '0'; - else if(*s >= 'a' && *s <= 'f') - n = n*16 + *s++ - 'a' + 10; - else if(*s >= 'A' && *s <= 'F') - n = n*16 + *s++ - 'A' + 10; - else - break; - } - } else - while(*s >= '0' && *s <= '7') - n = n*8 + *s++ - '0'; - } else - while(*s >= '0' && *s <= '9') - n = n*10 + *s++ - '0'; - if(f) - n = -n; - return n; -} |