Ejemplo n.º 1
0
Archivo: pe.c Proyecto: rosrad/go-rep
void
peinit(void)
{
	int32 l;

	switch(thechar) {
	// 64-bit architectures
	case '6':
		pe64 = 1;
		l = sizeof(oh64);
		dd = oh64.DataDirectory;
		break;
	// 32-bit architectures
	default:
		l = sizeof(oh);
		dd = oh.DataDirectory;
		break;
	}
	
	PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+l+sizeof(sh), PEFILEALIGN);
	PESECTHEADR = rnd(PEFILEHEADR, PESECTALIGN);
	nextsectoff = PESECTHEADR;
	nextfileoff = PEFILEHEADR;

	// some mingw libs depend on this symbol, for example, FindPESectionByName
	xdefine("__image_base__", SDATA, PEBASE);
	xdefine("_image_base__", SDATA, PEBASE);
}
Ejemplo n.º 2
0
void
dobss(void)
{
	int i;
	Sym *s;
	int32 t;

	if(dynptrsize > 0) {
		/* dynamic pointer section between data and bss */
		datsize = rnd(datsize, 8);
	}

	/* now the bss */
	bsssize = 0;
	for(i=0; i<NHASH; i++)
	for(s = hash[i]; s != S; s = s->link) {
		if(!s->reachable)
			continue;
		if(s->type != SBSS)
			continue;
		t = s->value;
		s->size = t;
		if(t >= 8)
			bsssize = rnd(bsssize, 8);
		s->value = bsssize + dynptrsize + datsize;
		bsssize += t;
	}

	xdefine("data", SBSS, 0);
	xdefine("edata", SBSS, datsize);
	xdefine("end", SBSS, dynptrsize + bsssize + datsize);
}
Ejemplo n.º 3
0
Archivo: data.c Proyecto: pipul/lab
// assign addresses
void
address(void)
{
	Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss;
	Sym *sym, *sub;
	uvlong va;

	va = INITTEXT;
	segtext.rwx = 05;
	segtext.vaddr = va;
	segtext.fileoff = HEADR;
	for(s=segtext.sect; s != nil; s=s->next) {
		s->vaddr = va;
		va += rnd(s->len, PtrSize);
	}
	segtext.len = va - INITTEXT;
	segtext.filelen = segtext.len;

	va = rnd(va, INITRND);

	segdata.rwx = 06;
	segdata.vaddr = va;
	segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
	segdata.filelen = 0;
	if(HEADTYPE == Hwindows)
		segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
	if(HEADTYPE == Hplan9x32)
		segdata.fileoff = segtext.fileoff + segtext.filelen;
	data = nil;
	noptr = nil;
	bss = nil;
	noptrbss = nil;
	for(s=segdata.sect; s != nil; s=s->next) {
		s->vaddr = va;
		va += s->len;
		segdata.filelen += s->len;
		segdata.len = va - segdata.vaddr;
		if(strcmp(s->name, ".data") == 0)
			data = s;
		if(strcmp(s->name, ".noptrdata") == 0)
			noptr = s;
		if(strcmp(s->name, ".bss") == 0)
			bss = s;
		if(strcmp(s->name, ".noptrbss") == 0)
			noptrbss = s;
	}
	segdata.filelen -= bss->len + noptrbss->len; // deduct .bss

	text = segtext.sect;
	rodata = text->next;
	symtab = rodata->next;
	pclntab = symtab->next;

	for(sym = datap; sym != nil; sym = sym->next) {
		cursym = sym;
		if(sym->type < SNOPTRDATA)
			sym->value += rodata->vaddr;
		else
			sym->value += segdata.sect->vaddr;
		for(sub = sym->sub; sub != nil; sub = sub->sub)
			sub->value += sym->value;
	}
	
	xdefine("text", STEXT, text->vaddr);
	xdefine("etext", STEXT, text->vaddr + text->len);
	xdefine("rodata", SRODATA, rodata->vaddr);
	xdefine("erodata", SRODATA, rodata->vaddr + rodata->len);
	xdefine("symtab", SRODATA, symtab->vaddr);
	xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
	xdefine("pclntab", SRODATA, pclntab->vaddr);
	xdefine("epclntab", SRODATA, pclntab->vaddr + pclntab->len);
	xdefine("noptrdata", SNOPTRDATA, noptr->vaddr);
	xdefine("enoptrdata", SNOPTRDATA, noptr->vaddr + noptr->len);
	xdefine("bss", SBSS, bss->vaddr);
	xdefine("ebss", SBSS, bss->vaddr + bss->len);
	xdefine("data", SDATA, data->vaddr);
	xdefine("edata", SDATA, data->vaddr + data->len);
	xdefine("noptrbss", SNOPTRBSS, noptrbss->vaddr);
	xdefine("enoptrbss", SNOPTRBSS, noptrbss->vaddr + noptrbss->len);
	xdefine("end", SBSS, segdata.vaddr + segdata.len);
}
Ejemplo n.º 4
0
Archivo: span.c Proyecto: 8l/go-learn
void
span(void)
{
	Prog *p, *q;
	int32 v, c, idat;
	int m, n, again;

	xdefine("etext", STEXT, 0L);
	idat = INITDAT;
	for(p = firstp; p != P; p = p->link) {
		if(p->as == ATEXT)
			curtext = p;
		n = 0;
		if(p->to.type == D_BRANCH)
			if(p->pcond == P)
				p->pcond = p;
		if((q = p->pcond) != P)
			if(q->back != 2)
				n = 1;
		p->back = n;
		if(p->as == AADJSP) {
			p->to.type = D_SP;
			v = -p->from.offset;
			p->from.offset = v;
			p->as = AADDL;
			if(v < 0) {
				p->as = ASUBL;
				v = -v;
				p->from.offset = v;
			}
			if(v == 0)
				p->as = ANOP;
		}
	}

	n = 0;
start:
	do{
		again = 0;
		if(debug['v'])
			Bprint(&bso, "%5.2f span %d\n", cputime(), n);
		Bflush(&bso);
		if(n > 500) {
			// TODO(rsc): figure out why nacl takes so long to converge.
			print("span must be looping - %d\n", textsize);
			errorexit();
		}
		c = INITTEXT;
		for(p = firstp; p != P; p = p->link) {
			if(p->as == ATEXT) {
				curtext = p;
				if(HEADTYPE == 8)
					c = (c+31)&~31;
			}
			if(p->to.type == D_BRANCH)
				if(p->back)
					p->pc = c;
			if(n == 0 || HEADTYPE == 8 || p->to.type == D_BRANCH) {
				if(HEADTYPE == 8)
					p->pc = c;
				asmins(p);
				m = andptr-and;
				if(p->mark != m)
					again = 1;
				p->mark = m;
			}
			if(HEADTYPE == 8) {
				c = p->pc + p->mark;
			} else {
				p->pc = c;
				c += p->mark;
			}
		}
		textsize = c;
		n++;
	}while(again);

	if(INITRND) {
		INITDAT = rnd(c, INITRND);
		if(INITDAT != idat) {
			idat = INITDAT;
			goto start;
		}
	}
	xdefine("etext", STEXT, c);
	if(debug['v'])
		Bprint(&bso, "etext = %lux\n", c);
	Bflush(&bso);
	for(p = textp; p != P; p = p->pcond)
		p->from.sym->value = p->pc;
	textsize = c - INITTEXT;
}
Ejemplo n.º 5
0
Archivo: pass.c Proyecto: 99years/plan9
void
dodata(void)
{
	int i, t;
	Sym *s;
	Prog *p, *p1;
	long orig, orig1, v;

	if(debug['v'])
		Bprint(&bso, "%5.2f dodata\n", cputime());
	Bflush(&bso);
	for(p = datap; p != P; p = p->link) {
		s = p->from.sym;
		if(p->as == ADYNT || p->as == AINIT)
			s->value = dtype;
		if(s->type == SBSS)
			s->type = SDATA;
		if(s->type != SDATA)
			diag("initialize non-data (%d): %s\n%P",
				s->type, s->name, p);
		v = p->from.offset + p->reg;
		if(v > s->value)
			diag("initialize bounds (%ld): %s\n%P",
				s->value, s->name, p);
	}

	/*
	 * pass 1
	 *	assign 'small' variables to data segment
	 *	(rational is that data segment is more easily
	 *	 addressed through offset on REGSB)
	 */
	orig = 0;
	for(i=0; i<NHASH; i++)
	for(s = hash[i]; s != S; s = s->link) {
		t = s->type;
		if(t != SDATA && t != SBSS)
			continue;
		v = s->value;
		if(v == 0) {
			diag("%s: no size", s->name);
			v = 1;
		}
		while(v & 3)
			v++;
		s->value = v;
		if(v > MINSIZ)
			continue;
		if(v >= 8)
			while(orig & 7)
				orig++;
		s->value = orig;
		orig += v;
		s->type = SDATA1;
	}
	orig1 = orig;

	/*
	 * pass 2
	 *	assign 'data' variables to data segment
	 */
	for(i=0; i<NHASH; i++)
	for(s = hash[i]; s != S; s = s->link) {
		t = s->type;
		if(t != SDATA) {
			if(t == SDATA1)
				s->type = SDATA;
			continue;
		}
		v = s->value;
		if(v >= 8)
			while(orig & 7)
				orig++;
		s->value = orig;
		orig += v;
		s->type = SDATA1;
	}

	while(orig & 7)
		orig++;
	datsize = orig;

	/*
	 * pass 3
	 *	everything else to bss segment
	 */
	for(i=0; i<NHASH; i++)
	for(s = hash[i]; s != S; s = s->link) {
		if(s->type != SBSS)
			continue;
		v = s->value;
		if(v >= 8)
			while(orig & 7)
				orig++;
		s->value = orig;
		orig += v;
	}
	while(orig & 7)
		orig++;
	bsssize = orig-datsize;

	/*
	 * pass 4
	 *	add literals to all large values.
	 *	at this time:
	 *		small data is allocated DATA
	 *		large data is allocated DATA1
	 *		large bss is allocated BSS
	 *	the new literals are loaded between
	 *	small data and large data.
	 */
	orig = 0;
	for(p = firstp; p != P; p = p->link) {
		if(p->as != AMOVW)
			continue;
		if(p->from.type != D_CONST)
			continue;
		if(s = p->from.sym) {
			t = s->type;
			if(t != SDATA && t != SDATA1 && t != SBSS)
				continue;
			t = p->from.name;
			if(t != D_EXTERN && t != D_STATIC)
				continue;
			v = s->value + p->from.offset;
			if(v >= 0 && v <= 0xffff)
				continue;
			if(!strcmp(s->name, "setSB"))
				continue;
			/* size should be 19 max */
			if(strlen(s->name) >= 10)	/* has loader address */ 
				sprint(literal, "$%p.%lux", s, p->from.offset);
			else
				sprint(literal, "$%s.%d.%lux", s->name, s->version, p->from.offset);
		} else {
			if(p->from.name != D_NONE)
				continue;
			if(p->from.reg != NREG)
				continue;
			v = p->from.offset;
			if(v >= -0x7fff-1 && v <= 0x7fff)
				continue;
			if(!(v & 0xffff))
				continue;
			if(v)
				continue;	/* quicker to build it than load it */
			/* size should be 9 max */
			sprint(literal, "$%lux", v);
		}
		s = lookup(literal, 0);
		if(s->type == 0) {
			s->type = SDATA;
			s->value = orig1+orig;
			orig += 4;
			p1 = prg();
			p1->as = ADATA;
			p1->line = p->line;
			p1->from.type = D_OREG;
			p1->from.sym = s;
			p1->from.name = D_EXTERN;
			p1->reg = 4;
			p1->to = p->from;
			p1->link = datap;
			datap = p1;
		}
		if(s->type != SDATA)
			diag("literal not data: %s", s->name);
		p->from.type = D_OREG;
		p->from.sym = s;
		p->from.name = D_EXTERN;
		p->from.offset = 0;
		continue;
	}
	while(orig & 7)
		orig++;
	/*
	 * pass 5
	 *	re-adjust offsets
	 */
	for(i=0; i<NHASH; i++)
	for(s = hash[i]; s != S; s = s->link) {
		t = s->type;
		if(t == SBSS) {
			s->value += orig;
			continue;
		}
		if(t == SDATA1) {
			s->type = SDATA;
			s->value += orig;
			continue;
		}
	}
	datsize += orig;
	xdefine("setSB", SDATA, 0L+BIG);
	xdefine("bdata", SDATA, 0L);
	xdefine("edata", SDATA, datsize);
	xdefine("end", SBSS, datsize+bsssize);
	xdefine("etext", STEXT, 0L);
}
Ejemplo n.º 6
0
void
dodata(void)
{
	int i, t;
	Sym *s;
	Prog *p;
	int32 orig, v;

	if(debug['v'])
		Bprint(&bso, "%5.2f dodata\n", cputime());
	Bflush(&bso);
	for(p = datap; p != P; p = p->link) {
		s = p->from.sym;
		if(p->as == ADYNT || p->as == AINIT)
			s->value = dtype;
		if(s->type == SBSS)
			s->type = SDATA;
		if(s->type != SDATA)
			diag("initialize non-data (%d): %s\n%P",
				s->type, s->name, p);
		v = p->from.offset + p->reg;
		if(v > s->value)
			diag("initialize bounds (%ld/%ld): %s\n%P",
				v, s->value, s->name, p);
		if((s->type == SBSS || s->type == SDATA) && (p->to.type == D_CONST || p->to.type == D_OCONST) && (p->to.name == D_EXTERN || p->to.name == D_STATIC)){
			s = p->to.sym;
			if(s != S && (s->type == STEXT || s->type == SLEAF || s->type == SCONST || s->type == SXREF))
				s->fnptr = 1;
		}
	}

	if(debug['t']) {
		/*
		 * pull out string constants
		 */
		for(p = datap; p != P; p = p->link) {
			s = p->from.sym;
			if(p->to.type == D_SCONST)
				s->type = SSTRING;
		}
	}

	/*
	 * pass 1
	 *	assign 'small' variables to data segment
	 *	(rational is that data segment is more easily
	 *	 addressed through offset on R12)
	 */
	orig = 0;
	for(i=0; i<NHASH; i++)
	for(s = hash[i]; s != S; s = s->link) {
		t = s->type;
		if(t != SDATA && t != SBSS)
			continue;
		v = s->value;
		if(v == 0) {
			diag("%s: no size", s->name);
			v = 1;
		}
		while(v & 3)
			v++;
		s->size = v;
		s->value = v;
		if(v > MINSIZ)
			continue;
		s->value = orig;
		orig += v;
		s->type = SDATA1;
	}

	/*
	 * pass 2
	 *	assign large 'data' variables to data segment
	 */
	for(i=0; i<NHASH; i++)
	for(s = hash[i]; s != S; s = s->link) {
		t = s->type;
		if(t != SDATA) {
			if(t == SDATA1)
				s->type = SDATA;
			continue;
		}
		v = s->value;
		s->size = v;
		s->value = orig;
		orig += v;
	}

	while(orig & 7)
		orig++;
	datsize = orig;

	/*
	 * pass 3
	 *	everything else to bss segment
	 */
	for(i=0; i<NHASH; i++)
	for(s = hash[i]; s != S; s = s->link) {
		if(s->type != SBSS)
			continue;
		v = s->value;
		s->size = v;
		s->value = orig;
		orig += v;
	}
	while(orig & 7)
		orig++;
	bsssize = orig-datsize;

	xdefine("setR12", SDATA, 0L+BIG);
	xdefine("bdata", SDATA, 0L);
	xdefine("data", SBSS, 0);
	xdefine("edata", SDATA, datsize);
	xdefine("end", SBSS, datsize+bsssize);
	xdefine("etext", STEXT, 0L);
}
Ejemplo n.º 7
0
Archivo: data.c Proyecto: hfeeki/golang
// assign addresses
void
address(void)
{
	Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss, *datarelro;
	Section *typelink;
	Sym *sym, *sub;
	uvlong va;
	vlong vlen;

	va = INITTEXT;
	segtext.rwx = 05;
	segtext.vaddr = va;
	segtext.fileoff = HEADR;
	for(s=segtext.sect; s != nil; s=s->next) {
		va = rnd(va, s->align);
		s->vaddr = va;
		va += s->len;
	}
	segtext.len = va - INITTEXT;
	segtext.filelen = segtext.len;

	va = rnd(va, INITRND);

	segdata.rwx = 06;
	segdata.vaddr = va;
	segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
	segdata.filelen = 0;
	if(HEADTYPE == Hwindows)
		segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
	if(HEADTYPE == Hplan9x64 || HEADTYPE == Hplan9x32)
		segdata.fileoff = segtext.fileoff + segtext.filelen;
	data = nil;
	noptr = nil;
	bss = nil;
	noptrbss = nil;
	datarelro = nil;
	for(s=segdata.sect; s != nil; s=s->next) {
		vlen = s->len;
		if(s->next)
			vlen = s->next->vaddr - s->vaddr;
		s->vaddr = va;
		va += vlen;
		segdata.len = va - segdata.vaddr;
		if(strcmp(s->name, ".data") == 0)
			data = s;
		if(strcmp(s->name, ".noptrdata") == 0)
			noptr = s;
		if(strcmp(s->name, ".bss") == 0)
			bss = s;
		if(strcmp(s->name, ".noptrbss") == 0)
			noptrbss = s;
		if(strcmp(s->name, ".data.rel.ro") == 0)
			datarelro = s;
	}
	segdata.filelen = bss->vaddr - segdata.vaddr;

	text = segtext.sect;
	rodata = text->next;
	typelink = rodata->next;
	symtab = typelink->next;
	pclntab = symtab->next;

	for(sym = datap; sym != nil; sym = sym->next) {
		cursym = sym;
		if(sym->type < SNOPTRDATA)
			sym->value += rodata->vaddr;
		else
			sym->value += segdata.sect->vaddr;
		for(sub = sym->sub; sub != nil; sub = sub->sub)
			sub->value += sym->value;
	}

	xdefine("text", STEXT, text->vaddr);
	xdefine("etext", STEXT, text->vaddr + text->len);
	xdefine("rodata", SRODATA, rodata->vaddr);
	xdefine("erodata", SRODATA, rodata->vaddr + rodata->len);
	xdefine("typelink", SRODATA, typelink->vaddr);
	xdefine("etypelink", SRODATA, typelink->vaddr + typelink->len);
	if(datarelro != nil) {
		xdefine("datarelro", SRODATA, datarelro->vaddr);
		xdefine("edatarelro", SRODATA, datarelro->vaddr + datarelro->len);
	}

	sym = lookup("gcdata", 0);
	xdefine("egcdata", STYPE, symaddr(sym) + sym->size);
	lookup("egcdata", 0)->sect = sym->sect;

	sym = lookup("gcbss", 0);
	xdefine("egcbss", STYPE, symaddr(sym) + sym->size);
	lookup("egcbss", 0)->sect = sym->sect;

	xdefine("symtab", SRODATA, symtab->vaddr);
	xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
	xdefine("pclntab", SRODATA, pclntab->vaddr);
	xdefine("epclntab", SRODATA, pclntab->vaddr + pclntab->len);
	xdefine("noptrdata", SNOPTRDATA, noptr->vaddr);
	xdefine("enoptrdata", SNOPTRDATA, noptr->vaddr + noptr->len);
	xdefine("bss", SBSS, bss->vaddr);
	xdefine("ebss", SBSS, bss->vaddr + bss->len);
	xdefine("data", SDATA, data->vaddr);
	xdefine("edata", SDATA, data->vaddr + data->len);
	xdefine("noptrbss", SNOPTRBSS, noptrbss->vaddr);
	xdefine("enoptrbss", SNOPTRBSS, noptrbss->vaddr + noptrbss->len);
	xdefine("end", SBSS, segdata.vaddr + segdata.len);
}
Ejemplo n.º 8
0
void
noops(void)
{
	Prog *p, *p1, *q, *q1;
	int o, mov, aoffset, curframe, curbecome, maxbecome;

	/*
	 * find leaf subroutines
	 * become sizes
	 * frame sizes
	 * strip NOPs
	 * expand RET
	 * expand BECOME pseudo
	 */

	if(debug['v'])
		Bprint(&bso, "%5.2f noops\n", cputime());
	Bflush(&bso);

	curframe = 0;
	curbecome = 0;
	maxbecome = 0;
	curtext = 0;
	q = P;
	for(p = firstp; p != P; p = p->link) {

		/* find out how much arg space is used in this TEXT */
		if(p->to.type == D_OREG && p->to.reg == REGSP)
			if(p->to.offset > curframe)
				curframe = p->to.offset;

		switch(p->as) {
		/* too hard, just leave alone */
		case ATEXT:
			if(curtext && curtext->from.sym) {
				curtext->from.sym->frame = curframe;
				curtext->from.sym->become = curbecome;
				if(curbecome > maxbecome)
					maxbecome = curbecome;
			}
			curframe = 0;
			curbecome = 0;

			q = p;
			p->mark |= LABEL|LEAF|SYNC;
			if(p->link)
				p->link->mark |= LABEL;
			curtext = p;
			break;

		case ANOR:
			q = p;
			if(p->to.type == D_REG)
				if(p->to.reg == REGZERO)
					p->mark |= LABEL|SYNC;
			break;

		case ALWAR:
		case ASTWCCC:
		case AECIWX:
		case AECOWX:
		case AEIEIO:
		case AICBI:
		case AISYNC:
		case ATLBIE:
		case ADCBF:
		case ADCBI:
		case ADCBST:
		case ADCBT:
		case ADCBTST:
		case ADCBZ:
		case ASYNC:
		case ATW:
		case AWORD:
		case ARFI:
		case ARFCI:
			q = p;
			p->mark |= LABEL|SYNC;
			continue;

		case AMOVW:
			q = p;
			switch(p->from.type) {
			case D_MSR:
			case D_SREG:
			case D_SPR:
			case D_FPSCR:
			case D_CREG:
			case D_DCR:
				p->mark |= LABEL|SYNC;
			}
			switch(p->to.type) {
			case D_MSR:
			case D_SREG:
			case D_SPR:
			case D_FPSCR:
			case D_CREG:
			case D_DCR:
				p->mark |= LABEL|SYNC;
			}
			continue;

		case AFABS:
		case AFABSCC:
		case AFADD:
		case AFADDCC:
		case AFCTIW:
		case AFCTIWCC:
		case AFCTIWZ:
		case AFCTIWZCC:
		case AFDIV:
		case AFDIVCC:
		case AFMADD:
		case AFMADDCC:
		case AFMOVD:
		case AFMOVDU:
		/* case AFMOVDS: */
		case AFMOVS:
		case AFMOVSU:
		/* case AFMOVSD: */
		case AFMSUB:
		case AFMSUBCC:
		case AFMUL:
		case AFMULCC:
		case AFNABS:
		case AFNABSCC:
		case AFNEG:
		case AFNEGCC:
		case AFNMADD:
		case AFNMADDCC:
		case AFNMSUB:
		case AFNMSUBCC:
		case AFRSP:
		case AFRSPCC:
		case AFSUB:
		case AFSUBCC:
			q = p;
			p->mark |= FLOAT;
			continue;

		case ABL:
		case ABCL:
			if(curtext != P)
				curtext->mark &= ~LEAF;

		case ABC:
		case ABEQ:
		case ABGE:
		case ABGT:
		case ABLE:
		case ABLT:
		case ABNE:
		case ABR:
		case ABVC:
		case ABVS:

			p->mark |= BRANCH;
			q = p;
			q1 = p->cond;
			if(q1 != P) {
				while(q1->as == ANOP) {
					q1 = q1->link;
					p->cond = q1;
				}
				if(!(q1->mark & LEAF))
					q1->mark |= LABEL;
			} else
				p->mark |= LABEL;
			q1 = p->link;
			if(q1 != P)
				q1->mark |= LABEL;
			continue;

		case AFCMPO:
		case AFCMPU:
			q = p;
			p->mark |= FCMP|FLOAT;
			continue;

		case ARETURN:
			/* special form of RETURN is BECOME */
			if(p->from.type == D_CONST)
				if(p->from.offset > curbecome)
					curbecome = p->from.offset;

			q = p;
			if(p->link != P)
				p->link->mark |= LABEL;
			continue;

		case ANOP:
			q1 = p->link;
			q->link = q1;		/* q is non-nop */
			q1->mark |= p->mark;
			continue;

		default:
			q = p;
			continue;
		}
	}
	if(curtext && curtext->from.sym) {
		curtext->from.sym->frame = curframe;
		curtext->from.sym->become = curbecome;
		if(curbecome > maxbecome)
			maxbecome = curbecome;
	}

	if(debug['b'])
		print("max become = %d\n", maxbecome);
	xdefine("ALEFbecome", STEXT, maxbecome);

	curtext = 0;
	for(p = firstp; p != P; p = p->link) {
		switch(p->as) {
		case ATEXT:
			curtext = p;
			break;

		case ABL:	/* ABCL? */
			if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
				o = maxbecome - curtext->from.sym->frame;
				if(o <= 0)
					break;
				/* calling a become or calling a variable */
				if(p->to.sym == S || p->to.sym->become) {
					curtext->to.offset += o;
					if(debug['b']) {
						curp = p;
						print("%D calling %D increase %d\n",
							&curtext->from, &p->to, o);
					}
				}
			}
			break;
		}
	}

	curtext = P;
	for(p = firstp; p != P; p = p->link) {
		o = p->as;
		switch(o) {
		case ATEXT:
			mov = AMOVW;
			aoffset = 0;
			curtext = p;
			autosize = p->to.offset + 4;
			if((p->mark & LEAF) && autosize <= 4)
				autosize = 0;
			else
				if(autosize & 4)
					autosize += 4;
			p->to.offset = autosize - 4;

			q = p;
			if(autosize) {
				/* use MOVWU to adjust R1 when saving R31, if autosize is small */
				if(!(curtext->mark & LEAF) && autosize >= -BIG && autosize <= BIG) {
					mov = AMOVWU;
					aoffset = -autosize;
				} else {
					q = prg();
					q->as = AADD;
					q->line = p->line;
					q->from.type = D_CONST;
					q->from.offset = -autosize;
					q->to.type = D_REG;
					q->to.reg = REGSP;

					q->link = p->link;
					p->link = q;
				}
			} else
			if(!(curtext->mark & LEAF)) {
				if(debug['v'])
					Bprint(&bso, "save suppressed in: %s\n",
						curtext->from.sym->name);
				curtext->mark |= LEAF;
			}

			if(curtext->mark & LEAF) {
				if(curtext->from.sym)
					curtext->from.sym->type = SLEAF;
				break;
			}

			q1 = prg();
			q1->as = mov;
			q1->line = p->line;
			q1->from.type = D_REG;
			q1->from.reg = REGTMP;
			q1->to.type = D_OREG;
			q1->to.offset = aoffset;
			q1->to.reg = REGSP;

			q1->link = q->link;
			q->link = q1;

			q1 = prg();
			q1->as = AMOVW;
			q1->line = p->line;
			q1->from.type = D_SPR;
			q1->from.offset = D_LR;
			q1->to.type = D_REG;
			q1->to.reg = REGTMP;

			q1->link = q->link;
			q->link = q1;
			break;

		case ARETURN:
			if(p->from.type == D_CONST)
				goto become;
			if(curtext->mark & LEAF) {
				if(!autosize) {
					p->as = ABR;
					p->from = zprg.from;
					p->to.type = D_SPR;
					p->to.offset = D_LR;
					p->mark |= BRANCH;
					break;
				}

				p->as = AADD;
				p->from.type = D_CONST;
				p->from.offset = autosize;
				p->to.type = D_REG;
				p->to.reg = REGSP;

				q = prg();
				q->as = ABR;
				q->line = p->line;
				q->to.type = D_SPR;
				q->to.offset = D_LR;
				q->mark |= BRANCH;

				q->link = p->link;
				p->link = q;
				break;
			}

			p->as = AMOVW;
			p->from.type = D_OREG;
			p->from.offset = 0;
			p->from.reg = REGSP;
			p->to.type = D_REG;
			p->to.reg = REGTMP;

			q = prg();
			q->as = AMOVW;
			q->line = p->line;
			q->from.type = D_REG;
			q->from.reg = REGTMP;
			q->to.type = D_SPR;
			q->to.offset = D_LR;

			q->link = p->link;
			p->link = q;
			p = q;

			if(autosize) {
				q = prg();
				q->as = AADD;
				q->line = p->line;
				q->from.type = D_CONST;
				q->from.offset = autosize;
				q->to.type = D_REG;
				q->to.reg = REGSP;

				q->link = p->link;
				p->link = q;
			}

			q1 = prg();
			q1->as = ABR;
			q1->line = p->line;
			q1->to.type = D_SPR;
			q1->to.offset = D_LR;
			q1->mark |= BRANCH;

			q1->link = q->link;
			q->link = q1;
			break;

		become:
			if(curtext->mark & LEAF) {

				q = prg();
				q->line = p->line;
				q->as = ABR;
				q->from = zprg.from;
				q->to = p->to;
				q->cond = p->cond;
				q->link = p->link;
				q->mark |= BRANCH;
				p->link = q;

				p->as = AADD;
				p->from = zprg.from;
				p->from.type = D_CONST;
				p->from.offset = autosize;
				p->to = zprg.to;
				p->to.type = D_REG;
				p->to.reg = REGSP;

				break;
			}
			q = prg();
			q->line = p->line;
			q->as = ABR;
			q->from = zprg.from;
			q->to = p->to;
			q->cond = p->cond;
			q->mark |= BRANCH;
			q->link = p->link;
			p->link = q;

			q = prg();
			q->line = p->line;
			q->as = AADD;
			q->from.type = D_CONST;
			q->from.offset = autosize;
			q->to.type = D_REG;
			q->to.reg = REGSP;
			q->link = p->link;
			p->link = q;

			q = prg();
			q->line = p->line;
			q->as = AMOVW;
			q->line = p->line;
			q->from.type = D_REG;
			q->from.reg = REGTMP;
			q->to.type = D_SPR;
			q->to.offset = D_LR;
			q->link = p->link;
			p->link = q;

			p->as = AMOVW;
			p->from = zprg.from;
			p->from.type = D_OREG;
			p->from.offset = 0;
			p->from.reg = REGSP;
			p->to = zprg.to;
			p->to.type = D_REG;
			p->to.reg = REGTMP;

			break;
		}
	}

	if(debug['Q'] == 0)
		return;

	curtext = P;
	q = P;		/* p - 1 */
	q1 = firstp;	/* top of block */
	o = 0;		/* count of instructions */
	for(p = firstp; p != P; p = p1) {
		p1 = p->link;
		o++;
		if(p->mark & NOSCHED){
			if(q1 != p){
				sched(q1, q);
			}
			for(; p != P; p = p->link){
				if(!(p->mark & NOSCHED))
					break;
				q = p;
			}
			p1 = p;
			q1 = p;
			o = 0;
			continue;
		}
		if(p->mark & (LABEL|SYNC)) {
			if(q1 != p)
				sched(q1, q);
			q1 = p;
			o = 1;
		}
		if(p->mark & (BRANCH|SYNC)) {
			sched(q1, p);
			q1 = p1;
			o = 0;
		}
		if(o >= NSCHED) {
			sched(q1, p);
			q1 = p1;
			o = 0;
		}
		q = p;
	}
}
Ejemplo n.º 9
0
Archivo: pass.c Proyecto: 99years/plan9
void
dostkoff(void)
{
    Prog *p, *q;
    long autoffset, deltasp;
    int a, f, curframe, curbecome, maxbecome;

    curframe = 0;
    curbecome = 0;
    maxbecome = 0;
    curtext = 0;
    for(p = firstp; p != P; p = p->link) {

        /* find out how much arg space is used in this TEXT */
        if(p->to.type == (D_INDIR+D_SP))
            if(p->to.offset > curframe)
                curframe = p->to.offset;

        switch(p->as) {
        case ATEXT:
            if(curtext && curtext->from.sym) {
                curtext->from.sym->frame = curframe;
                curtext->from.sym->become = curbecome;
                if(curbecome > maxbecome)
                    maxbecome = curbecome;
            }
            curframe = 0;
            curbecome = 0;

            curtext = p;
            break;

        case ARET:
            /* special form of RET is BECOME */
            if(p->from.type == D_CONST)
                if(p->from.offset > curbecome)
                    curbecome = p->from.offset;
            break;
        }
    }
    if(curtext && curtext->from.sym) {
        curtext->from.sym->frame = curframe;
        curtext->from.sym->become = curbecome;
        if(curbecome > maxbecome)
            maxbecome = curbecome;
    }

    if(debug['b'])
        print("max become = %d\n", maxbecome);
    xdefine("ALEFbecome", STEXT, maxbecome);

    curtext = 0;
    for(p = firstp; p != P; p = p->link) {
        switch(p->as) {
        case ATEXT:
            curtext = p;
            break;
        case ACALL:
            if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
                f = maxbecome - curtext->from.sym->frame;
                if(f <= 0)
                    break;
                /* calling a become or calling a variable */
                if(p->to.sym == S || p->to.sym->become) {
                    curtext->to.offset += f;
                    if(debug['b']) {
                        curp = p;
                        print("%D calling %D increase %d\n",
                              &curtext->from, &p->to, f);
                    }
                }
            }
            break;
        }
    }

    autoffset = 0;
    deltasp = 0;
    for(p = firstp; p != P; p = p->link) {
        if(p->as == ATEXT) {
            curtext = p;
            autoffset = p->to.offset;
            if(autoffset < 0)
                autoffset = 0;
            if(autoffset) {
                p = appendp(p);
                p->as = AADJSP;
                p->from.type = D_CONST;
                p->from.offset = autoffset;
            }
            deltasp = autoffset;
        }
        a = p->from.type;
        if(a == D_AUTO)
            p->from.offset += deltasp;
        if(a == D_PARAM)
            p->from.offset += deltasp + 4;
        a = p->to.type;
        if(a == D_AUTO)
            p->to.offset += deltasp;
        if(a == D_PARAM)
            p->to.offset += deltasp + 4;

        switch(p->as) {
        default:
            continue;
        case APUSHL:
        case APUSHFL:
            deltasp += 4;
            continue;
        case APUSHW:
        case APUSHFW:
            deltasp += 2;
            continue;
        case APOPL:
        case APOPFL:
            deltasp -= 4;
            continue;
        case APOPW:
        case APOPFW:
            deltasp -= 2;
            continue;
        case ARET:
            break;
        }

        if(autoffset != deltasp)
            diag("unbalanced PUSH/POP");
        if(p->from.type == D_CONST)
            goto become;

        if(autoffset) {
            q = p;
            p = appendp(p);
            p->as = ARET;

            q->as = AADJSP;
            q->from.type = D_CONST;
            q->from.offset = -autoffset;
        }
        continue;

become:
        q = p;
        p = appendp(p);
        p->as = AJMP;
        p->to = q->to;
        p->pcond = q->pcond;

        q->as = AADJSP;
        q->from = zprg.from;
        q->from.type = D_CONST;
        q->from.offset = -autoffset;
        q->to = zprg.to;
        continue;
    }
}
Ejemplo n.º 10
0
Archivo: pass.c Proyecto: 99years/plan9
void
dodata(void)
{
    int i;
    Sym *s;
    Prog *p;
    long t, u;

    if(debug['v'])
        Bprint(&bso, "%5.2f dodata\n", cputime());
    Bflush(&bso);
    for(p = datap; p != P; p = p->link) {
        s = p->from.sym;
        if(p->as == ADYNT || p->as == AINIT)
            s->value = dtype;
        if(s->type == SBSS)
            s->type = SDATA;
        if(s->type != SDATA)
            diag("initialize non-data (%d): %s\n%P",
                 s->type, s->name, p);
        t = p->from.offset + p->width;
        if(t > s->value)
            diag("initialize bounds (%ld): %s\n%P",
                 s->value, s->name, p);
    }
    /* allocate small guys */
    datsize = 0;
    for(i=0; i<NHASH; i++)
        for(s = hash[i]; s != S; s = s->link) {
            if(s->type != SDATA)
                if(s->type != SBSS)
                    continue;
            t = s->value;
            if(t == 0) {
                diag("%s: no size", s->name);
                t = 1;
            }
            t = rnd(t, 4);;
            s->value = t;
            if(t > MINSIZ)
                continue;
            s->value = datsize;
            datsize += t;
            s->type = SDATA1;
        }

    /* allocate the rest of the data */
    for(i=0; i<NHASH; i++)
        for(s = hash[i]; s != S; s = s->link) {
            if(s->type != SDATA) {
                if(s->type == SDATA1)
                    s->type = SDATA;
                continue;
            }
            t = s->value;
            s->value = datsize;
            datsize += t;
        }

    if(debug['j']) {
        /*
         * pad data with bss that fits up to next
         * 8k boundary, then push data to 8k
         */
        u = rnd(datsize, 8192);
        u -= datsize;
        for(i=0; i<NHASH; i++)
            for(s = hash[i]; s != S; s = s->link) {
                if(s->type != SBSS)
                    continue;
                t = s->value;
                if(t > u)
                    continue;
                u -= t;
                s->value = datsize;
                s->type = SDATA;
                datsize += t;
            }
        datsize += u;
    }

    /* now the bss */
    bsssize = 0;
    for(i=0; i<NHASH; i++)
        for(s = hash[i]; s != S; s = s->link) {
            if(s->type != SBSS)
                continue;
            t = s->value;
            s->value = bsssize + datsize;
            bsssize += t;
        }
    xdefine("bdata", SDATA, 0L);
    xdefine("edata", SBSS, datsize);
    xdefine("end", SBSS, bsssize + datsize);
    /* etext is defined in span.c */
}
Ejemplo n.º 11
0
void
span(void)
{
	Prog *p, *q;
	long v;
	vlong c, idat;
	int m, n, again;

	xdefine("etext", STEXT, 0L);
	idat = INITDAT;
	for(p = firstp; p != P; p = p->link) {
		if(p->as == ATEXT)
			curtext = p;
		n = 0;
		if(p->to.type == D_BRANCH)
			if(p->pcond == P)
				p->pcond = p;
		if((q = p->pcond) != P)
			if(q->back != 2)
				n = 1;
		p->back = n;
		if(p->as == AADJSP) {
			p->to.type = D_SP;
			v = -p->from.offset;
			p->from.offset = v;
			p->as = p->mode != 64? AADDL: AADDQ;
			if(v < 0) {
				p->as = p->mode != 64? ASUBL: ASUBQ;
				v = -v;
				p->from.offset = v;
			}
			if(v == 0)
				p->as = ANOP;
		}
	}
	n = 0;

start:
	if(debug['v'])
		Bprint(&bso, "%5.2f span\n", cputime());
	Bflush(&bso);
	c = INITTEXT;
	for(p = firstp; p != P; p = p->link) {
		if(p->as == ATEXT)
			curtext = p;
		if(p->to.type == D_BRANCH)
			if(p->back)
				p->pc = c;
		asmins(p);
		p->pc = c;
		m = andptr-and;
		p->mark = m;
		c += m;
	}

loop:
	n++;
	if(debug['v'])
		Bprint(&bso, "%5.2f span %d\n", cputime(), n);
	Bflush(&bso);
	if(n > 50) {
		print("span must be looping\n");
		errorexit();
	}
	again = 0;
	c = INITTEXT;
	for(p = firstp; p != P; p = p->link) {
		if(p->as == ATEXT)
			curtext = p;
		if(p->to.type == D_BRANCH || p->back & 0100) {
			if(p->back)
				p->pc = c;
			asmins(p);
			m = andptr-and;
			if(m != p->mark) {
				p->mark = m;
				again++;
			}
		}
		p->pc = c;
		c += p->mark;
	}
	if(again) {
		textsize = c;
		goto loop;
	}
	if(INITRND) {
		INITDAT = rnd(c, INITRND);
		if(INITDAT != idat) {
			idat = INITDAT;
			goto start;
		}
	}
	xdefine("etext", STEXT, c);
	if(debug['v'])
		Bprint(&bso, "etext = %llux\n", c);
	Bflush(&bso);
	for(p = textp; p != P; p = p->pcond)
		p->from.sym->value = p->pc;
	textsize = c - INITTEXT;
}
Ejemplo n.º 12
0
// assign addresses
void
address(void)
{
	Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss;
	Section *typelink;
	LSym *sym, *sub;
	uvlong va;
	vlong vlen;

	va = INITTEXT;
	segtext.rwx = 05;
	segtext.vaddr = va;
	segtext.fileoff = HEADR;
	for(s=segtext.sect; s != nil; s=s->next) {
		va = rnd(va, s->align);
		s->vaddr = va;
		va += s->len;
	}
	segtext.len = va - INITTEXT;
	segtext.filelen = segtext.len;
	if(HEADTYPE == Hnacl)
		va += 32; // room for the "halt sled"

	if(segrodata.sect != nil) {
		// align to page boundary so as not to mix
		// rodata and executable text.
		va = rnd(va, INITRND);

		segrodata.rwx = 04;
		segrodata.vaddr = va;
		segrodata.fileoff = va - segtext.vaddr + segtext.fileoff;
		segrodata.filelen = 0;
		for(s=segrodata.sect; s != nil; s=s->next) {
			va = rnd(va, s->align);
			s->vaddr = va;
			va += s->len;
		}
		segrodata.len = va - segrodata.vaddr;
		segrodata.filelen = segrodata.len;
	}

	va = rnd(va, INITRND);
	segdata.rwx = 06;
	segdata.vaddr = va;
	segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
	segdata.filelen = 0;
	if(HEADTYPE == Hwindows)
		segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
	if(HEADTYPE == Hplan9)
		segdata.fileoff = segtext.fileoff + segtext.filelen;
	data = nil;
	noptr = nil;
	bss = nil;
	noptrbss = nil;
	for(s=segdata.sect; s != nil; s=s->next) {
		vlen = s->len;
		if(s->next)
			vlen = s->next->vaddr - s->vaddr;
		s->vaddr = va;
		va += vlen;
		segdata.len = va - segdata.vaddr;
		if(strcmp(s->name, ".data") == 0)
			data = s;
		if(strcmp(s->name, ".noptrdata") == 0)
			noptr = s;
		if(strcmp(s->name, ".bss") == 0)
			bss = s;
		if(strcmp(s->name, ".noptrbss") == 0)
			noptrbss = s;
	}
	segdata.filelen = bss->vaddr - segdata.vaddr;

	text = segtext.sect;
	if(segrodata.sect)
		rodata = segrodata.sect;
	else
		rodata = text->next;
	typelink = rodata->next;
	symtab = typelink->next;
	pclntab = symtab->next;

	for(sym = datap; sym != nil; sym = sym->next) {
		ctxt->cursym = sym;
		if(sym->sect != nil)
			sym->value += sym->sect->vaddr;
		for(sub = sym->sub; sub != nil; sub = sub->sub)
			sub->value += sym->value;
	}

	xdefine("runtime.text", STEXT, text->vaddr);
	xdefine("runtime.etext", STEXT, text->vaddr + text->len);
	xdefine("runtime.rodata", SRODATA, rodata->vaddr);
	xdefine("runtime.erodata", SRODATA, rodata->vaddr + rodata->len);
	xdefine("runtime.typelink", SRODATA, typelink->vaddr);
	xdefine("runtime.etypelink", SRODATA, typelink->vaddr + typelink->len);

	sym = linklookup(ctxt, "runtime.gcdata", 0);
	xdefine("runtime.egcdata", SRODATA, symaddr(sym) + sym->size);
	linklookup(ctxt, "runtime.egcdata", 0)->sect = sym->sect;

	sym = linklookup(ctxt, "runtime.gcbss", 0);
	xdefine("runtime.egcbss", SRODATA, symaddr(sym) + sym->size);
	linklookup(ctxt, "runtime.egcbss", 0)->sect = sym->sect;

	xdefine("runtime.symtab", SRODATA, symtab->vaddr);
	xdefine("runtime.esymtab", SRODATA, symtab->vaddr + symtab->len);
	xdefine("runtime.pclntab", SRODATA, pclntab->vaddr);
	xdefine("runtime.epclntab", SRODATA, pclntab->vaddr + pclntab->len);
	xdefine("runtime.noptrdata", SNOPTRDATA, noptr->vaddr);
	xdefine("runtime.enoptrdata", SNOPTRDATA, noptr->vaddr + noptr->len);
	xdefine("runtime.bss", SBSS, bss->vaddr);
	xdefine("runtime.ebss", SBSS, bss->vaddr + bss->len);
	xdefine("runtime.data", SDATA, data->vaddr);
	xdefine("runtime.edata", SDATA, data->vaddr + data->len);
	xdefine("runtime.noptrbss", SNOPTRBSS, noptrbss->vaddr);
	xdefine("runtime.enoptrbss", SNOPTRBSS, noptrbss->vaddr + noptrbss->len);
	xdefine("runtime.end", SBSS, segdata.vaddr + segdata.len);
}
Ejemplo n.º 13
0
void
dostkoff(void)
{
	Prog *p, *q, *q1;
	int32 autoffset, deltasp;
	int a, f, curframe, curbecome, maxbecome, pcsize;
	uint32 moreconst1, moreconst2, i;

	for(i=0; i<nelem(morename); i++) {
		symmorestack[i] = lookup(morename[i], 0);
		pmorestack[i] = P;
	}

	for(p = firstp; p != P; p = p->link) {
		if(p->as == ATEXT) {
			for(i=0; i<nelem(morename); i++) {
				if(p->from.sym == symmorestack[i]) {
					pmorestack[i] = p;
					break;
				}
			}
		}
	}

	for(i=0; i<nelem(morename); i++) {
		if(pmorestack[i] == P)
			diag("morestack trampoline not defined");
	}

	curframe = 0;
	curbecome = 0;
	maxbecome = 0;
	curtext = 0;
	for(p = firstp; p != P; p = p->link) {

		/* find out how much arg space is used in this TEXT */
		if(p->to.type == (D_INDIR+D_SP))
			if(p->to.offset > curframe)
				curframe = p->to.offset;

		switch(p->as) {
		case ATEXT:
			if(curtext && curtext->from.sym) {
				curtext->from.sym->frame = curframe;
				curtext->from.sym->become = curbecome;
				if(curbecome > maxbecome)
					maxbecome = curbecome;
			}
			curframe = 0;
			curbecome = 0;

			curtext = p;
			break;

		case ARET:
			/* special form of RET is BECOME */
			if(p->from.type == D_CONST)
				if(p->from.offset > curbecome)
					curbecome = p->from.offset;
			break;
		}
	}
	if(curtext && curtext->from.sym) {
		curtext->from.sym->frame = curframe;
		curtext->from.sym->become = curbecome;
		if(curbecome > maxbecome)
			maxbecome = curbecome;
	}

	if(debug['b'])
		print("max become = %d\n", maxbecome);
	xdefine("ALEFbecome", STEXT, maxbecome);

	curtext = 0;
	for(p = firstp; p != P; p = p->link) {
		switch(p->as) {
		case ATEXT:
			curtext = p;
			break;
		case ACALL:
			if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
				f = maxbecome - curtext->from.sym->frame;
				if(f <= 0)
					break;
				/* calling a become or calling a variable */
				if(p->to.sym == S || p->to.sym->become) {
					curtext->to.offset += f;
					if(debug['b']) {
						curp = p;
						print("%D calling %D increase %d\n",
							&curtext->from, &p->to, f);
					}
				}
			}
			break;
		}
	}

	autoffset = 0;
	deltasp = 0;
	for(p = firstp; p != P; p = p->link) {
		if(p->as == ATEXT) {
			curtext = p;
			parsetextconst(p->to.offset);
			autoffset = textstksiz;
			if(autoffset < 0)
				autoffset = 0;

			q = P;
			q1 = P;
			if((p->from.scale & NOSPLIT) && autoffset >= StackSmall)
				diag("nosplit func likely to overflow stack");

			if(!(p->from.scale & NOSPLIT)) {
				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_R15;
					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;
				}

				if(autoffset < StackBig) {  // do we need to call morestack?
					if(autoffset <= StackSmall) {
						// small stack
						p = appendp(p);
						p->as = ACMPQ;
						p->from.type = D_SP;
						p->to.type = D_INDIR+D_R15;
						if(q1) {
							q1->pcond = p;
							q1 = P;
						}
					} else {
						// large stack
						p = appendp(p);
						p->as = ALEAQ;
						p->from.type = D_INDIR+D_SP;
						p->from.offset = -(autoffset-StackSmall);
						p->to.type = D_AX;
						if(q1) {
							q1->pcond = p;
							q1 = P;
						}

						p = appendp(p);
						p->as = ACMPQ;
						p->from.type = D_AX;
						p->to.type = D_INDIR+D_R15;
					}

					// common
					p = appendp(p);
					p->as = AJHI;
					p->to.type = D_BRANCH;
					p->to.offset = 4;
					q = p;
				}

				/* 160 comes from 3 calls (3*8) 4 safes (4*8) and 104 guard */
				moreconst1 = 0;
				if(autoffset+160 > 4096)
					moreconst1 = (autoffset+160) & ~7LL;
				moreconst2 = textarg;

				// 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];
					if(q1) {
						q1->pcond = p;
						q1 = P;
					}
				} else
				if(moreconst1 != 0 && moreconst2 == 0) {
					p->as = AMOVL;
					p->from.type = D_CONST;
					p->from.offset = moreconst1;
					p->to.type = D_AX;
					if(q1) {
						q1->pcond = p;
						q1 = P;
					}

					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];
					if(q1) {
						q1->pcond = p;
						q1 = P;
					}
				} else
				if(moreconst1 == 0 && moreconst2 != 0) {
					p->as = AMOVL;
					p->from.type = D_CONST;
					p->from.offset = moreconst2;
					p->to.type = D_AX;
					if(q1) {
						q1->pcond = p;
						q1 = P;
					}

					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;
					if(q1) {
						q1->pcond = p;
						q1 = P;
					}

					p = appendp(p);
					p->as = ACALL;
					p->to.type = D_BRANCH;
					p->pcond = pmorestack[3];
					p->to.sym = symmorestack[3];
				}
			}

			if(q != P)
				q->pcond = p->link;

			if(autoffset) {
				p = appendp(p);
				p->as = AADJSP;
				p->from.type = D_CONST;
				p->from.offset = autoffset;
				if(q != P)
					q->pcond = p;
			}
			deltasp = autoffset;

			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_R15;
				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;
				q1 = P;
			}
		}
		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;
			continue;
		case APUSHQ:
		case APUSHFQ:
			deltasp += 8;
			continue;
		case APUSHW:
		case APUSHFW:
			deltasp += 2;
			continue;
		case APOPL:
		case APOPFL:
			deltasp -= 4;
			continue;
		case APOPQ:
		case APOPFQ:
			deltasp -= 8;
			continue;
		case APOPW:
		case APOPFW:
			deltasp -= 2;
			continue;
		case ARET:
			break;
		}

		if(autoffset != deltasp)
			diag("unbalanced PUSH/POP");
		if(p->from.type == D_CONST)
			goto become;

		if(autoffset) {
			p->as = AADJSP;
			p->from.type = D_CONST;
			p->from.offset = -autoffset;

			p = appendp(p);
			p->as = ARET;
		}
		continue;

	become:
		q = p;
		p = appendp(p);
		p->as = AJMP;
		p->to = q->to;
		p->pcond = q->pcond;

		q->as = AADJSP;
		q->from = zprg.from;
		q->from.type = D_CONST;
		q->from.offset = -autoffset;
		q->to = zprg.to;
		continue;
	}
}