changelog shortlog tags branches changeset files file revisions raw help

Mercurial > hg > plan9front / annotate sys/src/cmd/7l/obj.c

changeset 0: eaccc3e8d226
child: d1102fefd6c1
author: Taru Karttunen <taruti@taruti.net>
date: Wed, 30 Mar 2011 15:46:40 +0300
permissions: -rwxr-xr-x
description: Import sources from 2011-03-30 iso image
taruti@0 1
 #include	"l.h"
taruti@0 2
 #include	<ar.h>
taruti@0 3
 
taruti@0 4
 #ifndef	DEFAULT
taruti@0 5
 #define	DEFAULT	'9'
taruti@0 6
 #endif
taruti@0 7
 
taruti@0 8
 char	*noname		= "<none>";
taruti@0 9
 char	symname[]	= SYMDEF;
taruti@0 10
 char	thechar		= '7';
taruti@0 11
 char	*thestring 	= "alpha";
taruti@0 12
 
taruti@0 13
 /*
taruti@0 14
  *	-H0 -T0x12000004C -D0x140000000	is abbrev unix
taruti@0 15
  *	-H1 -T0x20000000 -R4		is bootp() format
taruti@0 16
  *	-H2 -T8224 -R8192		is plan9 format
taruti@0 17
  */
taruti@0 18
 
taruti@0 19
 void
taruti@0 20
 main(int argc, char *argv[])
taruti@0 21
 {
taruti@0 22
 	int c;
taruti@0 23
 	char *a;
taruti@0 24
 
taruti@0 25
 	Binit(&bso, 1, OWRITE);
taruti@0 26
 	cout = -1;
taruti@0 27
 	listinit();
taruti@0 28
 	outfile = 0;
taruti@0 29
 	nerrors = 0;
taruti@0 30
 	curtext = P;
taruti@0 31
 	HEADTYPE = -1;
taruti@0 32
 	INITTEXT = -1;
taruti@0 33
 	INITDAT = -1;
taruti@0 34
 	INITRND = -1;
taruti@0 35
 	INITENTRY = 0;
taruti@0 36
 
taruti@0 37
 	ARGBEGIN {
taruti@0 38
 	default:
taruti@0 39
 		c = ARGC();
taruti@0 40
 		if(c >= 0 && c < sizeof(debug))
taruti@0 41
 			debug[c]++;
taruti@0 42
 		break;
taruti@0 43
 	case 'o':
taruti@0 44
 		outfile = ARGF();
taruti@0 45
 		break;
taruti@0 46
 	case 'E':
taruti@0 47
 		a = ARGF();
taruti@0 48
 		if(a)
taruti@0 49
 			INITENTRY = a;
taruti@0 50
 		break;
taruti@0 51
 	case 'T':
taruti@0 52
 		a = ARGF();
taruti@0 53
 		if(a)
taruti@0 54
 			INITTEXT = atolwhex(a);
taruti@0 55
 		break;
taruti@0 56
 	case 'D':
taruti@0 57
 		a = ARGF();
taruti@0 58
 		if(a)
taruti@0 59
 			INITDAT = atolwhex(a);
taruti@0 60
 		break;
taruti@0 61
 	case 'R':
taruti@0 62
 		a = ARGF();
taruti@0 63
 		if(a)
taruti@0 64
 			INITRND = atolwhex(a);
taruti@0 65
 		break;
taruti@0 66
 	case 'H':
taruti@0 67
 		a = ARGF();
taruti@0 68
 		if(a)
taruti@0 69
 			HEADTYPE = atolwhex(a);
taruti@0 70
 		/* do something about setting INITTEXT */
taruti@0 71
 		break;
taruti@0 72
 	} ARGEND
taruti@0 73
 
taruti@0 74
 	USED(argc);
taruti@0 75
 
taruti@0 76
 	if(*argv == 0) {
taruti@0 77
 		diag("usage: 7l [-options] objects");
taruti@0 78
 		errorexit();
taruti@0 79
 	}
taruti@0 80
 	if(!debug['9'] && !debug['B'] && !debug['U'])
taruti@0 81
 		debug[DEFAULT] = 1;
taruti@0 82
 	if(HEADTYPE == -1) {
taruti@0 83
 		if(debug['U'])
taruti@0 84
 			HEADTYPE = 0;
taruti@0 85
 		if(debug['B'])
taruti@0 86
 			HEADTYPE = 1;
taruti@0 87
 		if(debug['9'])
taruti@0 88
 			HEADTYPE = 2;
taruti@0 89
 	}
taruti@0 90
 	switch(HEADTYPE) {
taruti@0 91
 	default:
taruti@0 92
 		diag("unknown -H option");
taruti@0 93
 		errorexit();
taruti@0 94
 
taruti@0 95
 	case 0:	/* unix simple */
taruti@0 96
 		HEADR = 32L+80L;
taruti@0 97
 		if(INITTEXT == -1)
taruti@0 98
 			INITTEXT = 0x120000070LL;		/* BUG */
taruti@0 99
 		if(INITDAT == -1)
taruti@0 100
 			INITDAT = 0x140000000LL;		/* BUG */
taruti@0 101
 		if(INITRND == -1)
taruti@0 102
 			INITRND = 0;
taruti@0 103
 		break;
taruti@0 104
 
taruti@0 105
 	case 1:	/* boot */
taruti@0 106
 		HEADR = 32L+84L;
taruti@0 107
 		if(INITTEXT == -1)
taruti@0 108
 			INITTEXT = 0x20000074L;
taruti@0 109
 		if(INITDAT == -1)
taruti@0 110
 			INITDAT = 0;
taruti@0 111
 		if(INITRND == -1)
taruti@0 112
 			INITRND = 8;
taruti@0 113
 		break;
taruti@0 114
 	case 2:	/* plan 9 */
taruti@0 115
 		HEADR = 32L;
taruti@0 116
 		if(INITTEXT == -1)
taruti@0 117
 			INITTEXT = 8224;
taruti@0 118
 		if(INITDAT == -1)
taruti@0 119
 			INITDAT = 0;
taruti@0 120
 		if(INITRND == -1)
taruti@0 121
 			INITRND = 8192;
taruti@0 122
 		break;
taruti@0 123
 	case 3:	/* ``headerless'' tftp boot -- uses branch as magic */
taruti@0 124
 		HEADR = 32L;
taruti@0 125
 		if(INITTEXT == -1)
taruti@0 126
 			INITTEXT = 0x20000020L;
taruti@0 127
 		if(INITDAT == -1)
taruti@0 128
 			INITDAT = 0;
taruti@0 129
 		if(INITRND == -1)
taruti@0 130
 			INITRND = 8;
taruti@0 131
 		break;
taruti@0 132
 	}
taruti@0 133
 	if(INITDAT != 0 && INITRND != 0)
taruti@0 134
 		print("warning: -D0x%lux is ignored because of -R0x%lux\n",
taruti@0 135
 			INITDAT, INITRND);
taruti@0 136
 	if(debug['v'])
taruti@0 137
 		Bprint(&bso, "HEADER = -H0x%d -T0x%lux -D0x%lux -R0x%lux\n",
taruti@0 138
 			HEADTYPE, INITTEXT, INITDAT, INITRND);
taruti@0 139
 	Bflush(&bso);
taruti@0 140
 	zprg.as = AGOK;
taruti@0 141
 	zprg.reg = NREG;
taruti@0 142
 	zprg.from.name = D_NONE;
taruti@0 143
 	zprg.from.type = D_NONE;
taruti@0 144
 	zprg.from.reg = NREG;
taruti@0 145
 	zprg.to = zprg.from;
taruti@0 146
 	buildop();
taruti@0 147
 	histgen = 0;
taruti@0 148
 	textp = P;
taruti@0 149
 	datap = P;
taruti@0 150
 	pc = 0;
taruti@0 151
 	dtype = 4;
taruti@0 152
 	if(outfile == 0)
taruti@0 153
 		outfile = "7.out";
taruti@0 154
 	cout = create(outfile, 1, 0775);
taruti@0 155
 	if(cout < 0) {
taruti@0 156
 		diag("%s: cannot create", outfile);
taruti@0 157
 		errorexit();
taruti@0 158
 	}
taruti@0 159
 	nuxiinit();
taruti@0 160
 
taruti@0 161
 	version = 0;
taruti@0 162
 	cbp = buf.cbuf;
taruti@0 163
 	cbc = sizeof(buf.cbuf);
taruti@0 164
 	firstp = prg();
taruti@0 165
 	lastp = firstp;
taruti@0 166
 
taruti@0 167
 	if(INITENTRY == 0) {
taruti@0 168
 		INITENTRY = "_main";
taruti@0 169
 		if(debug['p'])
taruti@0 170
 			INITENTRY = "_mainp";
taruti@0 171
 		if(!debug['l'])
taruti@0 172
 			lookup(INITENTRY, 0)->type = SXREF;
taruti@0 173
 	} else
taruti@0 174
 		lookup(INITENTRY, 0)->type = SXREF;
taruti@0 175
 
taruti@0 176
 	while(*argv)
taruti@0 177
 		objfile(*argv++);
taruti@0 178
 	if(!debug['l'])
taruti@0 179
 		loadlib();
taruti@0 180
 	firstp = firstp->link;
taruti@0 181
 	if(firstp == P)
taruti@0 182
 		goto out;
taruti@0 183
 	patch();
taruti@0 184
 	if(debug['p'])
taruti@0 185
 		if(debug['1'])
taruti@0 186
 			doprof1();
taruti@0 187
 		else
taruti@0 188
 			doprof2();
taruti@0 189
 	follow();
taruti@0 190
 	if(firstp == P)
taruti@0 191
 		goto out;
taruti@0 192
 	noops();
taruti@0 193
 	dodata();		/* is before follow() on other arch */
taruti@0 194
 	span();
taruti@0 195
 	asmb();
taruti@0 196
 	undef();
taruti@0 197
 
taruti@0 198
 out:
taruti@0 199
 	if(debug['v']) {
taruti@0 200
 		Bprint(&bso, "%5.2f cpu time\n", cputime());
taruti@0 201
 		Bprint(&bso, "%ld memory used\n", thunk);
taruti@0 202
 		Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
taruti@0 203
 		Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
taruti@0 204
 	}
taruti@0 205
 	Bflush(&bso);
taruti@0 206
 	errorexit();
taruti@0 207
 }
taruti@0 208
 
taruti@0 209
 void
taruti@0 210
 loadlib(void)
taruti@0 211
 {
taruti@0 212
 	int i;
taruti@0 213
 	long h;
taruti@0 214
 	Sym *s;
taruti@0 215
 
taruti@0 216
 loop:
taruti@0 217
 	xrefresolv = 0;
taruti@0 218
 	for(i=0; i<libraryp; i++) {
taruti@0 219
 		if(debug['v'])
taruti@0 220
 			Bprint(&bso, "%5.2f autolib: %s\n", cputime(), library[i]);
taruti@0 221
 		objfile(library[i]);
taruti@0 222
 	}
taruti@0 223
 	if(xrefresolv)
taruti@0 224
 	for(h=0; h<nelem(hash); h++)
taruti@0 225
 	for(s = hash[h]; s != S; s = s->link)
taruti@0 226
 		if(s->type == SXREF)
taruti@0 227
 			goto loop;
taruti@0 228
 }
taruti@0 229
 
taruti@0 230
 void
taruti@0 231
 errorexit(void)
taruti@0 232
 {
taruti@0 233
 
taruti@0 234
 	Bflush(&bso);
taruti@0 235
 	if(nerrors) {
taruti@0 236
 		if(cout >= 0)
taruti@0 237
 			remove(outfile);
taruti@0 238
 		exits("error");
taruti@0 239
 	}
taruti@0 240
 	exits(0);
taruti@0 241
 }
taruti@0 242
 
taruti@0 243
 void
taruti@0 244
 objfile(char *file)
taruti@0 245
 {
taruti@0 246
 	long off, esym, cnt, l;
taruti@0 247
 	int f, work;
taruti@0 248
 	Sym *s;
taruti@0 249
 	char magbuf[SARMAG];
taruti@0 250
 	char name[100], pname[150];
taruti@0 251
 	struct ar_hdr arhdr;
taruti@0 252
 	char *e, *start, *stop;
taruti@0 253
 
taruti@0 254
 	if(file[0] == '-' && file[1] == 'l') {
taruti@0 255
 		if(debug['9'])
taruti@0 256
 			sprint(name, "/%s/lib/lib", thestring);
taruti@0 257
 		else
taruti@0 258
 			sprint(name, "/usr/%clib/lib", thechar);
taruti@0 259
 		strcat(name, file+2);
taruti@0 260
 		strcat(name, ".a");
taruti@0 261
 		file = name;
taruti@0 262
 	}
taruti@0 263
 	if(debug['v'])
taruti@0 264
 		Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
taruti@0 265
 	Bflush(&bso);
taruti@0 266
 	f = open(file, 0);
taruti@0 267
 	if(f < 0) {
taruti@0 268
 		diag("cannot open file: %s", file);
taruti@0 269
 		errorexit();
taruti@0 270
 	}
taruti@0 271
 	l = read(f, magbuf, SARMAG);
taruti@0 272
 	if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
taruti@0 273
 		/* load it as a regular file */
taruti@0 274
 		l = seek(f, 0L, 2);
taruti@0 275
 		seek(f, 0L, 0);
taruti@0 276
 		ldobj(f, l, file);
taruti@0 277
 		close(f);
taruti@0 278
 		return;
taruti@0 279
 	}
taruti@0 280
 
taruti@0 281
 	if(debug['v'])
taruti@0 282
 		Bprint(&bso, "%5.2f ldlib: %s\n", cputime(), file);
taruti@0 283
 	l = read(f, &arhdr, SAR_HDR);
taruti@0 284
 	if(l != SAR_HDR) {
taruti@0 285
 		diag("%s: short read on archive file symbol header", file);
taruti@0 286
 		goto out;
taruti@0 287
 	}
taruti@0 288
 	if(strncmp(arhdr.name, symname, strlen(symname))) {
taruti@0 289
 		diag("%s: first entry not symbol header", file);
taruti@0 290
 		goto out;
taruti@0 291
 	}
taruti@0 292
 
taruti@0 293
 	esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
taruti@0 294
 	off = SARMAG + SAR_HDR;
taruti@0 295
 
taruti@0 296
 	/*
taruti@0 297
 	 * just bang the whole symbol file into memory
taruti@0 298
 	 */
taruti@0 299
 	seek(f, off, 0);
taruti@0 300
 	cnt = esym - off;
taruti@0 301
 	start = malloc(cnt + 10);
taruti@0 302
 	cnt = read(f, start, cnt);
taruti@0 303
 	if(cnt <= 0){
taruti@0 304
 		close(f);
taruti@0 305
 		return;
taruti@0 306
 	}
taruti@0 307
 	stop = &start[cnt];
taruti@0 308
 	memset(stop, 0, 10);
taruti@0 309
 
taruti@0 310
 	work = 1;
taruti@0 311
 	while(work){
taruti@0 312
 		if(debug['v'])
taruti@0 313
 			Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
taruti@0 314
 		Bflush(&bso);
taruti@0 315
 		work = 0;
taruti@0 316
 		for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
taruti@0 317
 			s = lookup(e+5, 0);
taruti@0 318
 			if(s->type != SXREF)
taruti@0 319
 				continue;
taruti@0 320
 			sprint(pname, "%s(%s)", file, s->name);
taruti@0 321
 			if(debug['v'])
taruti@0 322
 				Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
taruti@0 323
 			Bflush(&bso);
taruti@0 324
 			l = e[1] & 0xff;
taruti@0 325
 			l |= (e[2] & 0xff) << 8;
taruti@0 326
 			l |= (e[3] & 0xff) << 16;
taruti@0 327
 			l |= (e[4] & 0xff) << 24;
taruti@0 328
 			seek(f, l, 0);
taruti@0 329
 			l = read(f, &arhdr, SAR_HDR);
taruti@0 330
 			if(l != SAR_HDR)
taruti@0 331
 				goto bad;
taruti@0 332
 			if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
taruti@0 333
 				goto bad;
taruti@0 334
 			l = atolwhex(arhdr.size);
taruti@0 335
 			ldobj(f, l, pname);
taruti@0 336
 			if(s->type == SXREF) {
taruti@0 337
 				diag("%s: failed to load: %s", file, s->name);
taruti@0 338
 				errorexit();
taruti@0 339
 			}
taruti@0 340
 			work = 1;
taruti@0 341
 			xrefresolv = 1;
taruti@0 342
 		}
taruti@0 343
 	}
taruti@0 344
 	return;
taruti@0 345
 
taruti@0 346
 bad:
taruti@0 347
 	diag("%s: bad or out of date archive", file);
taruti@0 348
 out:
taruti@0 349
 	close(f);
taruti@0 350
 }
taruti@0 351
 
taruti@0 352
 int
taruti@0 353
 zaddr(uchar *p, Adr *a, Sym *h[])
taruti@0 354
 {
taruti@0 355
 	int i, c;
taruti@0 356
 	vlong l;
taruti@0 357
 	Sym *s;
taruti@0 358
 	Auto *u;
taruti@0 359
 
taruti@0 360
 	c = p[2];
taruti@0 361
 	if(c < 0 || c > NSYM){
taruti@0 362
 		print("sym out of range: %d\n", c);
taruti@0 363
 		p[0] = ALAST+1;
taruti@0 364
 		return 0;
taruti@0 365
 	}
taruti@0 366
 	a->type = p[0];
taruti@0 367
 	a->reg = p[1];
taruti@0 368
 	a->sym = h[p[2]];
taruti@0 369
 	a->name = p[3];
taruti@0 370
 	c = 4;
taruti@0 371
 
taruti@0 372
 	if(a->reg < 0 || a->reg > NREG) {
taruti@0 373
 		print("register out of range %d\n", a->reg);
taruti@0 374
 		p[0] = ALAST+1;
taruti@0 375
 		return 0;	/*  force real diagnostic */
taruti@0 376
 	}
taruti@0 377
 
taruti@0 378
 	switch(a->type) {
taruti@0 379
 	default:
taruti@0 380
 		print("unknown type %d\n", a->type);
taruti@0 381
 		p[0] = ALAST+1;
taruti@0 382
 		return 0;	/*  force real diagnostic */
taruti@0 383
 
taruti@0 384
 	case D_NONE:
taruti@0 385
 	case D_REG:
taruti@0 386
 	case D_FREG:
taruti@0 387
 	case D_PREG:
taruti@0 388
 	case D_FCREG:
taruti@0 389
 	case D_PCC:
taruti@0 390
 		break;
taruti@0 391
 
taruti@0 392
 	case D_BRANCH:
taruti@0 393
 	case D_OREG:
taruti@0 394
 	case D_CONST:
taruti@0 395
 		a->offset = (uvlong)p[4] | ((uvlong)p[5]<<8L) |
taruti@0 396
 			((uvlong) p[6]<<16L) | ((uvlong) p[7]<<24L) |
taruti@0 397
 			((uvlong) p[8]<<32L) | ((uvlong) p[9]<<40L) |
taruti@0 398
 			((uvlong) p[10]<<48L) | ((uvlong) p[11]<<56L);
taruti@0 399
 		c += 8;
taruti@0 400
 		break;
taruti@0 401
 
taruti@0 402
 	case D_SCONST:
taruti@0 403
 		while(nhunk < NSNAME)
taruti@0 404
 			gethunk();
taruti@0 405
 		a->sval = (char*)hunk;
taruti@0 406
 		nhunk -= NSNAME;
taruti@0 407
 		hunk += NSNAME;
taruti@0 408
 
taruti@0 409
 		memmove(a->sval, p+4, NSNAME);
taruti@0 410
 		c += NSNAME;
taruti@0 411
 		break;
taruti@0 412
 
taruti@0 413
 	case D_FCONST:
taruti@0 414
 		while(nhunk < sizeof(Ieee))
taruti@0 415
 			gethunk();
taruti@0 416
 		a->ieee = (Ieee*)hunk;
taruti@0 417
 		nhunk -= sizeof(Ieee);
taruti@0 418
 		hunk += sizeof(Ieee);
taruti@0 419
 
taruti@0 420
 		a->ieee->l = p[4] | (p[5]<<8) |
taruti@0 421
 			(p[6]<<16) | (p[7]<<24);
taruti@0 422
 		a->ieee->h = p[8] | (p[9]<<8) |
taruti@0 423
 			(p[10]<<16) | (p[11]<<24);
taruti@0 424
 		c += 8;
taruti@0 425
 		break;
taruti@0 426
 	}
taruti@0 427
 	s = a->sym;
taruti@0 428
 	if(s == S)
taruti@0 429
 		return c;
taruti@0 430
 	i = a->name;
taruti@0 431
 	if(i != D_AUTO && i != D_PARAM)
taruti@0 432
 		return c;
taruti@0 433
 
taruti@0 434
 	l = a->offset;
taruti@0 435
 	for(u=curauto; u; u=u->link)
taruti@0 436
 		if(u->sym == s)
taruti@0 437
 		if(u->type == i) {
taruti@0 438
 			if(u->offset > l)
taruti@0 439
 				u->offset = l;
taruti@0 440
 			return c;
taruti@0 441
 		}
taruti@0 442
 
taruti@0 443
 	while(nhunk < sizeof(Auto))
taruti@0 444
 		gethunk();
taruti@0 445
 	u = (Auto*)hunk;
taruti@0 446
 	nhunk -= sizeof(Auto);
taruti@0 447
 	hunk += sizeof(Auto);
taruti@0 448
 
taruti@0 449
 	u->link = curauto;
taruti@0 450
 	curauto = u;
taruti@0 451
 	u->sym = s;
taruti@0 452
 	u->offset = l;
taruti@0 453
 	u->type = i;
taruti@0 454
 	return c;
taruti@0 455
 }
taruti@0 456
 
taruti@0 457
 void
taruti@0 458
 addlib(char *obj)
taruti@0 459
 {
taruti@0 460
 	char name[1024], comp[256], *p;
taruti@0 461
 	int i;
taruti@0 462
 
taruti@0 463
 	if(histfrogp <= 0)
taruti@0 464
 		return;
taruti@0 465
 
taruti@0 466
 	if(histfrog[0]->name[1] == '/') {
taruti@0 467
 		sprint(name, "");
taruti@0 468
 		i = 1;
taruti@0 469
 	} else
taruti@0 470
 	if(histfrog[0]->name[1] == '.') {
taruti@0 471
 		sprint(name, ".");
taruti@0 472
 		i = 0;
taruti@0 473
 	} else {
taruti@0 474
 		if(debug['9'])
taruti@0 475
 			sprint(name, "/%s/lib", thestring);
taruti@0 476
 		else
taruti@0 477
 			sprint(name, "/usr/%clib", thechar);
taruti@0 478
 		i = 0;
taruti@0 479
 	}
taruti@0 480
 
taruti@0 481
 	for(; i<histfrogp; i++) {
taruti@0 482
 		snprint(comp, sizeof comp, histfrog[i]->name+1);
taruti@0 483
 		for(;;) {
taruti@0 484
 			p = strstr(comp, "$O");
taruti@0 485
 			if(p == 0)
taruti@0 486
 				break;
taruti@0 487
 			memmove(p+1, p+2, strlen(p+2)+1);
taruti@0 488
 			p[0] = thechar;
taruti@0 489
 		}
taruti@0 490
 		for(;;) {
taruti@0 491
 			p = strstr(comp, "$M");
taruti@0 492
 			if(p == 0)
taruti@0 493
 				break;
taruti@0 494
 			if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
taruti@0 495
 				diag("library component too long");
taruti@0 496
 				return;
taruti@0 497
 			}
taruti@0 498
 			memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
taruti@0 499
 			memmove(p, thestring, strlen(thestring));
taruti@0 500
 		}
taruti@0 501
 		if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
taruti@0 502
 			diag("library component too long");
taruti@0 503
 			return;
taruti@0 504
 		}
taruti@0 505
 		strcat(name, "/");
taruti@0 506
 		strcat(name, comp);
taruti@0 507
 	}
taruti@0 508
 	for(i=0; i<libraryp; i++)
taruti@0 509
 		if(strcmp(name, library[i]) == 0)
taruti@0 510
 			return;
taruti@0 511
 	if(libraryp == nelem(library)){
taruti@0 512
 		diag("too many autolibs; skipping %s", name);
taruti@0 513
 		return;
taruti@0 514
 	}
taruti@0 515
 
taruti@0 516
 	p = malloc(strlen(name) + 1);
taruti@0 517
 	strcpy(p, name);
taruti@0 518
 	library[libraryp] = p;
taruti@0 519
 	p = malloc(strlen(obj) + 1);
taruti@0 520
 	strcpy(p, obj);
taruti@0 521
 	libraryobj[libraryp] = p;
taruti@0 522
 	libraryp++;
taruti@0 523
 }
taruti@0 524
 
taruti@0 525
 void
taruti@0 526
 addhist(long line, int type)
taruti@0 527
 {
taruti@0 528
 	Auto *u;
taruti@0 529
 	Sym *s;
taruti@0 530
 	int i, j, k;
taruti@0 531
 
taruti@0 532
 	u = malloc(sizeof(Auto));
taruti@0 533
 	s = malloc(sizeof(Sym));
taruti@0 534
 	s->name = malloc(2*(histfrogp+1) + 1);
taruti@0 535
 
taruti@0 536
 	u->sym = s;
taruti@0 537
 	u->type = type;
taruti@0 538
 	u->offset = line;
taruti@0 539
 	u->link = curhist;
taruti@0 540
 	curhist = u;
taruti@0 541
 
taruti@0 542
 	j = 1;
taruti@0 543
 	for(i=0; i<histfrogp; i++) {
taruti@0 544
 		k = histfrog[i]->value;
taruti@0 545
 		s->name[j+0] = k>>8;
taruti@0 546
 		s->name[j+1] = k;
taruti@0 547
 		j += 2;
taruti@0 548
 	}
taruti@0 549
 }
taruti@0 550
 
taruti@0 551
 void
taruti@0 552
 histtoauto(void)
taruti@0 553
 {
taruti@0 554
 	Auto *l;
taruti@0 555
 
taruti@0 556
 	while(l = curhist) {
taruti@0 557
 		curhist = l->link;
taruti@0 558
 		l->link = curauto;
taruti@0 559
 		curauto = l;
taruti@0 560
 	}
taruti@0 561
 }
taruti@0 562
 
taruti@0 563
 void
taruti@0 564
 collapsefrog(Sym *s)
taruti@0 565
 {
taruti@0 566
 	int i;
taruti@0 567
 
taruti@0 568
 	/*
taruti@0 569
 	 * bad encoding of path components only allows
taruti@0 570
 	 * MAXHIST components. if there is an overflow,
taruti@0 571
 	 * first try to collapse xxx/..
taruti@0 572
 	 */
taruti@0 573
 	for(i=1; i<histfrogp; i++)
taruti@0 574
 		if(strcmp(histfrog[i]->name+1, "..") == 0) {
taruti@0 575
 			memmove(histfrog+i-1, histfrog+i+1,
taruti@0 576
 				(histfrogp-i-1)*sizeof(histfrog[0]));
taruti@0 577
 			histfrogp--;
taruti@0 578
 			goto out;
taruti@0 579
 		}
taruti@0 580
 
taruti@0 581
 	/*
taruti@0 582
 	 * next try to collapse .
taruti@0 583
 	 */
taruti@0 584
 	for(i=0; i<histfrogp; i++)
taruti@0 585
 		if(strcmp(histfrog[i]->name+1, ".") == 0) {
taruti@0 586
 			memmove(histfrog+i, histfrog+i+1,
taruti@0 587
 				(histfrogp-i-1)*sizeof(histfrog[0]));
taruti@0 588
 			goto out;
taruti@0 589
 		}
taruti@0 590
 
taruti@0 591
 	/*
taruti@0 592
 	 * last chance, just truncate from front
taruti@0 593
 	 */
taruti@0 594
 	memmove(histfrog+0, histfrog+1,
taruti@0 595
 		(histfrogp-1)*sizeof(histfrog[0]));
taruti@0 596
 
taruti@0 597
 out:
taruti@0 598
 	histfrog[histfrogp-1] = s;
taruti@0 599
 }
taruti@0 600
 
taruti@0 601
 void
taruti@0 602
 nopout(Prog *p)
taruti@0 603
 {
taruti@0 604
 	p->as = ANOP;
taruti@0 605
 	p->from.type = D_NONE;
taruti@0 606
 	p->to.type = D_NONE;
taruti@0 607
 }
taruti@0 608
 
taruti@0 609
 uchar*
taruti@0 610
 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
taruti@0 611
 {
taruti@0 612
 	int n;
taruti@0 613
 
taruti@0 614
 	n = stop - good;
taruti@0 615
 	memmove(buf, good, stop - good);
taruti@0 616
 	stop = buf + n;
taruti@0 617
 	n = MAXIO - n;
taruti@0 618
 	if(n > max)
taruti@0 619
 		n = max;
taruti@0 620
 	n = read(f, stop, n);
taruti@0 621
 	if(n <= 0)
taruti@0 622
 		return 0;
taruti@0 623
 	return stop + n;
taruti@0 624
 }
taruti@0 625
 
taruti@0 626
 void
taruti@0 627
 ldobj(int f, long c, char *pn)
taruti@0 628
 {
taruti@0 629
 	long ipc;
taruti@0 630
 	Prog *p, *t;
taruti@0 631
 	uchar *bloc, *bsize, *stop;
taruti@0 632
 	Sym *h[NSYM], *s, *di;
taruti@0 633
 	int v, o, r, skip;
taruti@0 634
 
taruti@0 635
 	bsize = buf.xbuf;
taruti@0 636
 	bloc = buf.xbuf;
taruti@0 637
 	di = S;
taruti@0 638
 
taruti@0 639
 newloop:
taruti@0 640
 	memset(h, 0, sizeof(h));
taruti@0 641
 	version++;
taruti@0 642
 	histfrogp = 0;
taruti@0 643
 	ipc = pc;
taruti@0 644
 	skip = 0;
taruti@0 645
 
taruti@0 646
 loop:
taruti@0 647
 	if(c <= 0)
taruti@0 648
 		goto eof;
taruti@0 649
 	r = bsize - bloc;
taruti@0 650
 	if(r < 100 && r < c) {		/* enough for largest prog */
taruti@0 651
 		bsize = readsome(f, buf.xbuf, bloc, bsize, c);
taruti@0 652
 		if(bsize == 0)
taruti@0 653
 			goto eof;
taruti@0 654
 		bloc = buf.xbuf;
taruti@0 655
 		goto loop;
taruti@0 656
 	}
taruti@0 657
 	o = bloc[0];		/* as */
taruti@0 658
 	if(o <= AXXX || o >= ALAST) {
taruti@0 659
 		diag("%s: line %ld: opcode out of range %d", pn, pc-ipc, o);
taruti@0 660
 		print("	probably not a .7 file\n");
taruti@0 661
 		errorexit();
taruti@0 662
 	}
taruti@0 663
 	if(o == ANAME) {
taruti@0 664
 		stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
taruti@0 665
 		if(stop == 0){
taruti@0 666
 			bsize = readsome(f, buf.xbuf, bloc, bsize, c);
taruti@0 667
 			if(bsize == 0)
taruti@0 668
 				goto eof;
taruti@0 669
 			bloc = buf.xbuf;
taruti@0 670
 			stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
taruti@0 671
 			if(stop == 0){
taruti@0 672
 				fprint(2, "%s: name too long\n", pn);
taruti@0 673
 				errorexit();
taruti@0 674
 			}
taruti@0 675
 		}
taruti@0 676
 		v = bloc[1];	/* type */
taruti@0 677
 		o = bloc[2];	/* sym */
taruti@0 678
 		bloc += 3;
taruti@0 679
 		c -= 3;
taruti@0 680
 
taruti@0 681
 		r = 0;
taruti@0 682
 		if(v == D_STATIC)
taruti@0 683
 			r = version;
taruti@0 684
 		s = lookup((char*)bloc, r);
taruti@0 685
 		c -= &stop[1] - bloc;
taruti@0 686
 		bloc = stop + 1;
taruti@0 687
 
taruti@0 688
 		if(debug['W'])
taruti@0 689
 			print("	ANAME	%s\n", s->name);
taruti@0 690
 		h[o] = s;
taruti@0 691
 		if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
taruti@0 692
 			s->type = SXREF;
taruti@0 693
 		if(v == D_FILE) {
taruti@0 694
 			if(s->type != SFILE) {
taruti@0 695
 				histgen++;
taruti@0 696
 				s->type = SFILE;
taruti@0 697
 				s->value = histgen;
taruti@0 698
 			}
taruti@0 699
 			if(histfrogp < MAXHIST) {
taruti@0 700
 				histfrog[histfrogp] = s;
taruti@0 701
 				histfrogp++;
taruti@0 702
 			} else
taruti@0 703
 				collapsefrog(s);
taruti@0 704
 		}
taruti@0 705
 		goto loop;
taruti@0 706
 	}
taruti@0 707
 
taruti@0 708
 	if(nhunk < sizeof(Prog))
taruti@0 709
 		gethunk();
taruti@0 710
 	p = (Prog*)hunk;
taruti@0 711
 	nhunk -= sizeof(Prog);
taruti@0 712
 	hunk += sizeof(Prog);
taruti@0 713
 
taruti@0 714
 	p->as = o;
taruti@0 715
 	p->reg = bloc[1] & 0x7f;
taruti@0 716
 	if(bloc[1] & 0x80)
taruti@0 717
 		p->mark = NOSCHED;
taruti@0 718
 	p->line = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
taruti@0 719
 
taruti@0 720
 	r = zaddr(bloc+6, &p->from, h) + 6;
taruti@0 721
 	r += zaddr(bloc+r, &p->to, h);
taruti@0 722
 	bloc += r;
taruti@0 723
 	c -= r;
taruti@0 724
 
taruti@0 725
 	if(p->reg < 0 || p->reg > NREG)
taruti@0 726
 		diag("register out of range %d", p->reg);
taruti@0 727
 
taruti@0 728
 	p->link = P;
taruti@0 729
 	p->cond = P;
taruti@0 730
 
taruti@0 731
 	if(debug['W'])
taruti@0 732
 		print("%P\n", p);
taruti@0 733
 
taruti@0 734
 	switch(o) {
taruti@0 735
 	case AHISTORY:
taruti@0 736
 		if(p->to.offset == -1) {
taruti@0 737
 			addlib(pn);
taruti@0 738
 			histfrogp = 0;
taruti@0 739
 			goto loop;
taruti@0 740
 		}
taruti@0 741
 		addhist(p->line, D_FILE);		/* 'z' */
taruti@0 742
 		if(p->to.offset)
taruti@0 743
 			addhist(p->to.offset, D_PREG);	/* 'Z' */
taruti@0 744
 		histfrogp = 0;
taruti@0 745
 		goto loop;
taruti@0 746
 
taruti@0 747
 	case AEND:
taruti@0 748
 		histtoauto();
taruti@0 749
 		if(curtext != P)
taruti@0 750
 			curtext->to.autom = curauto;
taruti@0 751
 		curauto = 0;
taruti@0 752
 		curtext = P;
taruti@0 753
 		if(c)
taruti@0 754
 			goto newloop;
taruti@0 755
 		return;
taruti@0 756
 
taruti@0 757
 	case AGLOBL:
taruti@0 758
 		s = p->from.sym;
taruti@0 759
 		if(s == S) {
taruti@0 760
 			diag("GLOBL must have a name\n%P", p);
taruti@0 761
 			errorexit();
taruti@0 762
 		}
taruti@0 763
 		if(s->type == 0 || s->type == SXREF) {
taruti@0 764
 			s->type = SBSS;
taruti@0 765
 			s->value = 0;
taruti@0 766
 		}
taruti@0 767
 		if(s->type != SBSS) {
taruti@0 768
 			diag("redefinition: %s\n%P", s->name, p);
taruti@0 769
 			s->type = SBSS;
taruti@0 770
 			s->value = 0;
taruti@0 771
 		}
taruti@0 772
 		if(p->to.offset > s->value)
taruti@0 773
 			s->value = p->to.offset;
taruti@0 774
 		break;
taruti@0 775
 
taruti@0 776
 	case ADYNT:
taruti@0 777
 		if(p->to.sym == S) {
taruti@0 778
 			diag("DYNT without a sym\n%P", p);
taruti@0 779
 			break;
taruti@0 780
 		}
taruti@0 781
 		di = p->to.sym;
taruti@0 782
 		p->reg = 4;
taruti@0 783
 		if(di->type == SXREF) {
taruti@0 784
 			if(debug['z'])
taruti@0 785
 				Bprint(&bso, "%P set to %d\n", p, dtype);
taruti@0 786
 			di->type = SCONST;
taruti@0 787
 			di->value = dtype;
taruti@0 788
 			dtype += 4;
taruti@0 789
 		}
taruti@0 790
 		if(p->from.sym == S)
taruti@0 791
 			break;
taruti@0 792
 
taruti@0 793
 		p->from.offset = di->value;
taruti@0 794
 		p->from.sym->type = SDATA;
taruti@0 795
 		if(curtext == P) {
taruti@0 796
 			diag("DYNT not in text: %P", p);
taruti@0 797
 			break;
taruti@0 798
 		}
taruti@0 799
 		p->to.sym = curtext->from.sym;
taruti@0 800
 		p->to.type = D_CONST;
taruti@0 801
 		p->link = datap;
taruti@0 802
 		datap = p;
taruti@0 803
 		break;
taruti@0 804
 
taruti@0 805
 	case AINIT:
taruti@0 806
 		if(p->from.sym == S) {
taruti@0 807
 			diag("INIT without a sym\n%P", p);
taruti@0 808
 			break;
taruti@0 809
 		}
taruti@0 810
 		if(di == S) {
taruti@0 811
 			diag("INIT without previous DYNT\n%P", p);
taruti@0 812
 			break;
taruti@0 813
 		}
taruti@0 814
 		p->from.offset = di->value;
taruti@0 815
 		p->from.sym->type = SDATA;
taruti@0 816
 		p->link = datap;
taruti@0 817
 		datap = p;
taruti@0 818
 		break;
taruti@0 819
 	
taruti@0 820
 	case ADATA:
taruti@0 821
 		if(p->from.sym == S) {
taruti@0 822
 			diag("DATA without a sym\n%P", p);
taruti@0 823
 			break;
taruti@0 824
 		}
taruti@0 825
 		p->link = datap;
taruti@0 826
 		datap = p;
taruti@0 827
 		break;
taruti@0 828
 
taruti@0 829
 	case AGOK:
taruti@0 830
 		diag("unknown opcode\n%P", p);
taruti@0 831
 		p->pc = pc;
taruti@0 832
 		pc++;
taruti@0 833
 		break;
taruti@0 834
 
taruti@0 835
 	case ATEXT:
taruti@0 836
 		if(curtext != P) {
taruti@0 837
 			histtoauto();
taruti@0 838
 			curtext->to.autom = curauto;
taruti@0 839
 			curauto = 0;
taruti@0 840
 		}
taruti@0 841
 		skip = 0;
taruti@0 842
 		curtext = p;
taruti@0 843
 		autosize = (p->to.offset+3L) & ~3L;
taruti@0 844
 		if (autosize & 4)
taruti@0 845
 			autosize += 4;
taruti@0 846
 		p->to.offset = autosize;
taruti@0 847
 		autosize += 8;
taruti@0 848
 		s = p->from.sym;
taruti@0 849
 		if(s == S) {
taruti@0 850
 			diag("TEXT must have a name\n%P", p);
taruti@0 851
 			errorexit();
taruti@0 852
 		}
taruti@0 853
 		if(s->type != 0 && s->type != SXREF) {
taruti@0 854
 			if(p->reg & DUPOK) {
taruti@0 855
 				skip = 1;
taruti@0 856
 				goto casedef;
taruti@0 857
 			}
taruti@0 858
 			diag("redefinition: %s\n%P", s->name, p);
taruti@0 859
 		}
taruti@0 860
 		s->type = STEXT;
taruti@0 861
 		s->value = pc;
taruti@0 862
 		lastp->link = p;
taruti@0 863
 		lastp = p;
taruti@0 864
 		p->pc = pc;
taruti@0 865
 		pc++;
taruti@0 866
 		if(textp == P) {
taruti@0 867
 			textp = p;
taruti@0 868
 			etextp = p;
taruti@0 869
 			goto loop;
taruti@0 870
 		}
taruti@0 871
 		etextp->cond = p;
taruti@0 872
 		etextp = p;
taruti@0 873
 		break;
taruti@0 874
 
taruti@0 875
 	case AMOVS:
taruti@0 876
 		if(skip)
taruti@0 877
 			goto casedef;
taruti@0 878
 
taruti@0 879
 		if(p->from.type == D_FCONST) {
taruti@0 880
 			/* size sb 9 max */
taruti@0 881
 			sprint(literal, "$%lux", ieeedtof(p->from.ieee));
taruti@0 882
 			s = lookup(literal, 0);
taruti@0 883
 			if(s->type == 0) {
taruti@0 884
 				s->type = SBSS;
taruti@0 885
 				s->value = 4;
taruti@0 886
 				t = prg();
taruti@0 887
 				t->as = ADATA;
taruti@0 888
 				t->line = p->line;
taruti@0 889
 				t->from.type = D_OREG;
taruti@0 890
 				t->from.sym = s;
taruti@0 891
 				t->from.name = D_EXTERN;
taruti@0 892
 				t->reg = 4;
taruti@0 893
 				t->to = p->from;
taruti@0 894
 				t->link = datap;
taruti@0 895
 				datap = t;
taruti@0 896
 			}
taruti@0 897
 			p->from.type = D_OREG;
taruti@0 898
 			p->from.sym = s;
taruti@0 899
 			p->from.name = D_EXTERN;
taruti@0 900
 			p->from.offset = 0;
taruti@0 901
 		}
taruti@0 902
 		goto casedef;
taruti@0 903
 
taruti@0 904
 	case AMOVT:
taruti@0 905
 		if(skip)
taruti@0 906
 			goto casedef;
taruti@0 907
 
taruti@0 908
 		if(p->from.type == D_FCONST) {
taruti@0 909
 			/* size sb 18 max */
taruti@0 910
 			sprint(literal, "$%lux.%lux",
taruti@0 911
 				p->from.ieee->l, p->from.ieee->h);
taruti@0 912
 			s = lookup(literal, 0);
taruti@0 913
 			if(s->type == 0) {
taruti@0 914
 				s->type = SBSS;
taruti@0 915
 				s->value = 8;
taruti@0 916
 				t = prg();
taruti@0 917
 				t->as = ADATA;
taruti@0 918
 				t->line = p->line;
taruti@0 919
 				t->from.type = D_OREG;
taruti@0 920
 				t->from.sym = s;
taruti@0 921
 				t->from.name = D_EXTERN;
taruti@0 922
 				t->reg = 8;
taruti@0 923
 				t->to = p->from;
taruti@0 924
 				t->link = datap;
taruti@0 925
 				datap = t;
taruti@0 926
 			}
taruti@0 927
 			p->from.type = D_OREG;
taruti@0 928
 			p->from.sym = s;
taruti@0 929
 			p->from.name = D_EXTERN;
taruti@0 930
 			p->from.offset = 0;
taruti@0 931
 		}
taruti@0 932
 		goto casedef;
taruti@0 933
 
taruti@0 934
 	case AMOVQ:
taruti@0 935
 		if(skip)
taruti@0 936
 			goto casedef;
taruti@0 937
 
taruti@0 938
 		if (p->from.type == D_FREG || p->to.type == D_FREG)
taruti@0 939
 			p->as = AMOVT;		/* stupid compiler optimiser kkludge */
taruti@0 940
 
taruti@0 941
 	case AMOVL:
taruti@0 942
 	case AMOVW:
taruti@0 943
 	case AMOVB:
taruti@0 944
 		/* BOTCH */
taruti@0 945
 		if (p->from.type == D_CONST)
taruti@0 946
 		if (p->from.offset == 0LL && p->from.name == D_NONE) {
taruti@0 947
 			p->from.type = D_REG;
taruti@0 948
 			p->from.reg = REGZERO;
taruti@0 949
 		}
taruti@0 950
 		goto casedef;
taruti@0 951
 
taruti@0 952
 	default:
taruti@0 953
 	casedef:
taruti@0 954
 		if(skip)
taruti@0 955
 			nopout(p);
taruti@0 956
 
taruti@0 957
 		if(p->to.type == D_BRANCH)
taruti@0 958
 			p->to.offset += ipc;
taruti@0 959
 		lastp->link = p;
taruti@0 960
 		lastp = p;
taruti@0 961
 		p->pc = pc;
taruti@0 962
 		pc++;
taruti@0 963
 		break;
taruti@0 964
 	}
taruti@0 965
 	goto loop;
taruti@0 966
 
taruti@0 967
 eof:
taruti@0 968
 	diag("truncated object file: %s", pn);
taruti@0 969
 }
taruti@0 970
 
taruti@0 971
 Sym*
taruti@0 972
 lookup(char *symb, int v)
taruti@0 973
 {
taruti@0 974
 	Sym *s;
taruti@0 975
 	char *p;
taruti@0 976
 	long h;
taruti@0 977
 	int c0, l;
taruti@0 978
 
taruti@0 979
 	h = v;
taruti@0 980
 	for(p=symb; c0 = *p; p++)
taruti@0 981
 		h = h+h+h + c0;
taruti@0 982
 	l = (p - symb) + 1;
taruti@0 983
 	if(h < 0)
taruti@0 984
 		h = ~h;
taruti@0 985
 	h %= NHASH;
taruti@0 986
 	for(s = hash[h]; s != S; s = s->link)
taruti@0 987
 		if(s->version == v)
taruti@0 988
 		if(memcmp(s->name, symb, l) == 0)
taruti@0 989
 			return s;
taruti@0 990
 
taruti@0 991
 	while(nhunk < sizeof(Sym))
taruti@0 992
 		gethunk();
taruti@0 993
 	s = (Sym*)hunk;
taruti@0 994
 	nhunk -= sizeof(Sym);
taruti@0 995
 	hunk += sizeof(Sym);
taruti@0 996
 
taruti@0 997
 	s->name = malloc(l);
taruti@0 998
 	memmove(s->name, symb, l);
taruti@0 999
 
taruti@0 1000
 	s->link = hash[h];
taruti@0 1001
 	s->type = 0;
taruti@0 1002
 	s->version = v;
taruti@0 1003
 	s->value = 0;
taruti@0 1004
 	hash[h] = s;
taruti@0 1005
 	return s;
taruti@0 1006
 }
taruti@0 1007
 
taruti@0 1008
 Prog*
taruti@0 1009
 prg(void)
taruti@0 1010
 {
taruti@0 1011
 	Prog *p;
taruti@0 1012
 
taruti@0 1013
 	while(nhunk < sizeof(Prog))
taruti@0 1014
 		gethunk();
taruti@0 1015
 	p = (Prog*)hunk;
taruti@0 1016
 	nhunk -= sizeof(Prog);
taruti@0 1017
 	hunk += sizeof(Prog);
taruti@0 1018
 
taruti@0 1019
 	*p = zprg;
taruti@0 1020
 	return p;
taruti@0 1021
 }
taruti@0 1022
 
taruti@0 1023
 void
taruti@0 1024
 gethunk(void)
taruti@0 1025
 {
taruti@0 1026
 	char *h;
taruti@0 1027
 	long nh;
taruti@0 1028
 
taruti@0 1029
 	nh = NHUNK;
taruti@0 1030
 	if(thunk >= 5L*NHUNK) {
taruti@0 1031
 		nh = 5L*NHUNK;
taruti@0 1032
 		if(thunk >= 25L*NHUNK)
taruti@0 1033
 			nh = 25L*NHUNK;
taruti@0 1034
 	}
taruti@0 1035
 	h = mysbrk(nh);
taruti@0 1036
 	if(h == (char*)-1) {
taruti@0 1037
 		diag("out of memory");
taruti@0 1038
 		errorexit();
taruti@0 1039
 	}
taruti@0 1040
 	hunk = h;
taruti@0 1041
 	nhunk = nh;
taruti@0 1042
 	thunk += nh;
taruti@0 1043
 }
taruti@0 1044
 
taruti@0 1045
 void
taruti@0 1046
 doprof1(void)
taruti@0 1047
 {
taruti@0 1048
 	Sym *s;
taruti@0 1049
 	long n;
taruti@0 1050
 	Prog *p, *q;
taruti@0 1051
 
taruti@0 1052
 	if(debug['v'])
taruti@0 1053
 		Bprint(&bso, "%5.2f profile 1\n", cputime());
taruti@0 1054
 	Bflush(&bso);
taruti@0 1055
 	s = lookup("__mcount", 0);
taruti@0 1056
 	n = 1;
taruti@0 1057
 	for(p = firstp->link; p != P; p = p->link) {
taruti@0 1058
 		if(p->as == ATEXT) {
taruti@0 1059
 			q = prg();
taruti@0 1060
 			q->line = p->line;
taruti@0 1061
 			q->link = datap;
taruti@0 1062
 			datap = q;
taruti@0 1063
 			q->as = ADATA;
taruti@0 1064
 			q->from.type = D_OREG;
taruti@0 1065
 			q->from.name = D_EXTERN;
taruti@0 1066
 			q->from.offset = n*4;
taruti@0 1067
 			q->from.sym = s;
taruti@0 1068
 			q->reg = 4;
taruti@0 1069
 			q->to = p->from;
taruti@0 1070
 			q->to.type = D_CONST;
taruti@0 1071
 
taruti@0 1072
 			q = prg();
taruti@0 1073
 			q->line = p->line;
taruti@0 1074
 			q->pc = p->pc;
taruti@0 1075
 			q->link = p->link;
taruti@0 1076
 			p->link = q;
taruti@0 1077
 			p = q;
taruti@0 1078
 			p->as = AMOVL;
taruti@0 1079
 			p->from.type = D_OREG;
taruti@0 1080
 			p->from.name = D_EXTERN;
taruti@0 1081
 			p->from.sym = s;
taruti@0 1082
 			p->from.offset = n*4 + 4;
taruti@0 1083
 			p->to.type = D_REG;
taruti@0 1084
 			p->to.reg = REGTMP;
taruti@0 1085
 
taruti@0 1086
 			q = prg();
taruti@0 1087
 			q->line = p->line;
taruti@0 1088
 			q->pc = p->pc;
taruti@0 1089
 			q->link = p->link;
taruti@0 1090
 			p->link = q;
taruti@0 1091
 			p = q;
taruti@0 1092
 			p->as = AADDQ;
taruti@0 1093
 			p->from.type = D_CONST;
taruti@0 1094
 			p->from.offset = 1;
taruti@0 1095
 			p->to.type = D_REG;
taruti@0 1096
 			p->to.reg = REGTMP;
taruti@0 1097
 
taruti@0 1098
 			q = prg();
taruti@0 1099
 			q->line = p->line;
taruti@0 1100
 			q->pc = p->pc;
taruti@0 1101
 			q->link = p->link;
taruti@0 1102
 			p->link = q;
taruti@0 1103
 			p = q;
taruti@0 1104
 			p->as = AMOVL;
taruti@0 1105
 			p->from.type = D_REG;
taruti@0 1106
 			p->from.reg = REGTMP;
taruti@0 1107
 			p->to.type = D_OREG;
taruti@0 1108
 			p->to.name = D_EXTERN;
taruti@0 1109
 			p->to.sym = s;
taruti@0 1110
 			p->to.offset = n*4 + 4;
taruti@0 1111
 
taruti@0 1112
 			n += 2;
taruti@0 1113
 			continue;
taruti@0 1114
 		}
taruti@0 1115
 	}
taruti@0 1116
 	q = prg();
taruti@0 1117
 	q->line = 0;
taruti@0 1118
 	q->link = datap;
taruti@0 1119
 	datap = q;
taruti@0 1120
 
taruti@0 1121
 	q->as = ADATA;
taruti@0 1122
 	q->from.type = D_OREG;
taruti@0 1123
 	q->from.name = D_EXTERN;
taruti@0 1124
 	q->from.sym = s;
taruti@0 1125
 	q->reg = 4;
taruti@0 1126
 	q->to.type = D_CONST;
taruti@0 1127
 	q->to.offset = n;
taruti@0 1128
 
taruti@0 1129
 	s->type = SBSS;
taruti@0 1130
 	s->value = n*4;
taruti@0 1131
 }
taruti@0 1132
 
taruti@0 1133
 void
taruti@0 1134
 doprof2(void)
taruti@0 1135
 {
taruti@0 1136
 	Sym *s2, *s4;
taruti@0 1137
 	Prog *p, *q, *q2, *ps2, *ps4;
taruti@0 1138
 
taruti@0 1139
 	if(debug['v'])
taruti@0 1140
 		Bprint(&bso, "%5.2f profile 2\n", cputime());
taruti@0 1141
 	Bflush(&bso);
taruti@0 1142
 
taruti@0 1143
 	if(debug['e']){
taruti@0 1144
 		s2 = lookup("_tracein", 0);
taruti@0 1145
 		s4 = lookup("_traceout", 0);
taruti@0 1146
 	}else{
taruti@0 1147
 		s2 = lookup("_profin", 0);
taruti@0 1148
 		s4 = lookup("_profout", 0);
taruti@0 1149
 	}
taruti@0 1150
 	if(s2->type != STEXT || s4->type != STEXT) {
taruti@0 1151
 		if(debug['e'])
taruti@0 1152
 			diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
taruti@0 1153
 		else
taruti@0 1154
 			diag("_profin/_profout not defined");
taruti@0 1155
 		return;
taruti@0 1156
 	}
taruti@0 1157
 
taruti@0 1158
 	ps2 = P;
taruti@0 1159
 	ps4 = P;
taruti@0 1160
 	for(p = firstp; p != P; p = p->link) {
taruti@0 1161
 		if(p->as == ATEXT) {
taruti@0 1162
 			if(p->from.sym == s2) {
taruti@0 1163
 				ps2 = p;
taruti@0 1164
 				p->reg = 1;
taruti@0 1165
 			}
taruti@0 1166
 			if(p->from.sym == s4) {
taruti@0 1167
 				ps4 = p;
taruti@0 1168
 				p->reg = 1;
taruti@0 1169
 			}
taruti@0 1170
 		}
taruti@0 1171
 	}
taruti@0 1172
 	for(p = firstp; p != P; p = p->link) {
taruti@0 1173
 		if(p->as == ATEXT) {
taruti@0 1174
 			if(p->reg != NREG) {
taruti@0 1175
 				for(;;) {
taruti@0 1176
 					q = p->link;
taruti@0 1177
 					if(q == P)
taruti@0 1178
 						break;
taruti@0 1179
 					if(q->as == ATEXT)
taruti@0 1180
 						break;
taruti@0 1181
 					p = q;
taruti@0 1182
 				}
taruti@0 1183
 				continue;
taruti@0 1184
 			}
taruti@0 1185
 
taruti@0 1186
 			/*
taruti@0 1187
 			 * JSR	profin, R2
taruti@0 1188
 			 */
taruti@0 1189
 			q = prg();
taruti@0 1190
 			q->line = p->line;
taruti@0 1191
 			q->pc = p->pc;
taruti@0 1192
 			q->link = p->link;
taruti@0 1193
 			if(debug['e']){		/* embedded tracing */
taruti@0 1194
 				q2 = prg();
taruti@0 1195
 				p->link = q2;
taruti@0 1196
 				q2->link = q;
taruti@0 1197
 
taruti@0 1198
 				q2->line = p->line;
taruti@0 1199
 				q2->pc = p->pc;
taruti@0 1200
 
taruti@0 1201
 				q2->as = AJMP;
taruti@0 1202
 				q2->to.type = D_BRANCH;
taruti@0 1203
 				q2->to.sym = p->to.sym;
taruti@0 1204
 				q2->cond = q->link;
taruti@0 1205
 			}else
taruti@0 1206
 				p->link = q;
taruti@0 1207
 			p = q;
taruti@0 1208
 			p->as = AJSR;
taruti@0 1209
 			p->to.type = D_BRANCH;
taruti@0 1210
 			p->cond = ps2;
taruti@0 1211
 			p->to.sym = s2;
taruti@0 1212
 
taruti@0 1213
 			continue;
taruti@0 1214
 		}
taruti@0 1215
 		if(p->as == ARET) {
taruti@0 1216
 			/*
taruti@0 1217
 			 * JSR (default)
taruti@0 1218
 			 */
taruti@0 1219
 			if(debug['e']){		/* embedded tracing */
taruti@0 1220
 				q = prg();
taruti@0 1221
 				q->line = p->line;
taruti@0 1222
 				q->pc = p->pc;
taruti@0 1223
 				q->link = p->link;
taruti@0 1224
 				p->link = q;
taruti@0 1225
 				p = q;
taruti@0 1226
 			}
taruti@0 1227
 			/*
taruti@0 1228
 			 * JSR	profout
taruti@0 1229
 			 */
taruti@0 1230
 			p->as = AJSR;
taruti@0 1231
 			p->to.type = D_BRANCH;
taruti@0 1232
 			p->cond = ps4;
taruti@0 1233
 			p->to.sym = s4;
taruti@0 1234
 
taruti@0 1235
 			
taruti@0 1236
 			/*
taruti@0 1237
 			 * RET
taruti@0 1238
 			 */
taruti@0 1239
 			q = prg();
taruti@0 1240
 			q->line = p->line;
taruti@0 1241
 			q->pc = p->pc;
taruti@0 1242
 			q->link = p->link;
taruti@0 1243
 			p->link = q;
taruti@0 1244
 			p = q;
taruti@0 1245
 			p->as = ARET;
taruti@0 1246
 
taruti@0 1247
 			continue;
taruti@0 1248
 		}
taruti@0 1249
 	}
taruti@0 1250
 }
taruti@0 1251
 
taruti@0 1252
 void
taruti@0 1253
 nuxiinit(void)
taruti@0 1254
 {
taruti@0 1255
 	int i, c;
taruti@0 1256
 
taruti@0 1257
 	for(i=0; i<4; i++) {
taruti@0 1258
 		c = find1(0x04030201L, i+1);
taruti@0 1259
 		if(i <= 4)
taruti@0 1260
 			inuxi4[i] = c;
taruti@0 1261
 		if(i <= 2)
taruti@0 1262
 			inuxi2[i] = c;
taruti@0 1263
 		if(i <= 1)
taruti@0 1264
 			inuxi1[i] = c;
taruti@0 1265
 	}
taruti@0 1266
 	for (i = 0; i < 4; i++) {
taruti@0 1267
 		c = find1(0x04030201L, i+1);
taruti@0 1268
 		fnuxi8[i] = c;
taruti@0 1269
 		fnuxi8[i+4] = c + sizeof(long);
taruti@0 1270
 	}
taruti@0 1271
 
taruti@0 1272
 	if(debug['v']) {
taruti@0 1273
 		Bprint(&bso, "inuxi = ");
taruti@0 1274
 		for(i=0; i<1; i++)
taruti@0 1275
 			Bprint(&bso, "%d", inuxi1[i]);
taruti@0 1276
 		Bprint(&bso, " ");
taruti@0 1277
 		for(i=0; i<2; i++)
taruti@0 1278
 			Bprint(&bso, "%d", inuxi2[i]);
taruti@0 1279
 		Bprint(&bso, " ");
taruti@0 1280
 		for(i=0; i<4; i++)
taruti@0 1281
 			Bprint(&bso, "%d", inuxi4[i]);
taruti@0 1282
 		Bprint(&bso, " ");
taruti@0 1283
 		Bprint(&bso, "\nfnuxi = ");
taruti@0 1284
 		for(i=0; i<8; i++)
taruti@0 1285
 			Bprint(&bso, "%d", fnuxi8[i]);
taruti@0 1286
 		Bprint(&bso, "\n");
taruti@0 1287
 	}
taruti@0 1288
 	Bflush(&bso);
taruti@0 1289
 }
taruti@0 1290
 
taruti@0 1291
 find1(long l, int c)
taruti@0 1292
 {
taruti@0 1293
 	char *p;
taruti@0 1294
 	int i;
taruti@0 1295
 
taruti@0 1296
 	p = (char*)&l;
taruti@0 1297
 	for(i=0; i<4; i++)
taruti@0 1298
 		if(*p++ == c)
taruti@0 1299
 			return i;
taruti@0 1300
 	return 0;
taruti@0 1301
 }
taruti@0 1302
 
taruti@0 1303
 long
taruti@0 1304
 ieeedtof(Ieee *ieee)
taruti@0 1305
 {
taruti@0 1306
 	int exp;
taruti@0 1307
 	long v;
taruti@0 1308
 
taruti@0 1309
 	if(ieee->h == 0)
taruti@0 1310
 		return 0;
taruti@0 1311
 	exp = (ieee->h>>20) & ((1L<<11)-1L);
taruti@0 1312
 	exp -= (1L<<10) - 2L;
taruti@0 1313
 	v = (ieee->h & 0xfffffL) << 3;
taruti@0 1314
 	v |= (ieee->l >> 29) & 0x7L;
taruti@0 1315
 	if((ieee->l >> 28) & 1) {
taruti@0 1316
 		v++;
taruti@0 1317
 		if(v & 0x800000L) {
taruti@0 1318
 			v = (v & 0x7fffffL) >> 1;
taruti@0 1319
 			exp++;
taruti@0 1320
 		}
taruti@0 1321
 	}
taruti@0 1322
 	if(exp <= -126 || exp >= 130)
taruti@0 1323
 		diag("double fp to single fp overflow");
taruti@0 1324
 	v |= ((exp + 126) & 0xffL) << 23;
taruti@0 1325
 	v |= ieee->h & 0x80000000L;
taruti@0 1326
 	return v;
taruti@0 1327
 }
taruti@0 1328
 
taruti@0 1329
 double
taruti@0 1330
 ieeedtod(Ieee *ieee)
taruti@0 1331
 {
taruti@0 1332
 	Ieee e;
taruti@0 1333
 	double fr;
taruti@0 1334
 	int exp;
taruti@0 1335
 
taruti@0 1336
 	if(ieee->h & (1L<<31)) {
taruti@0 1337
 		e.h = ieee->h & ~(1L<<31);
taruti@0 1338
 		e.l = ieee->l;
taruti@0 1339
 		return -ieeedtod(&e);
taruti@0 1340
 	}
taruti@0 1341
 	if(ieee->l == 0 && ieee->h == 0)
taruti@0 1342
 		return 0;
taruti@0 1343
 	fr = ieee->l & ((1L<<16)-1L);
taruti@0 1344
 	fr /= 1L<<16;
taruti@0 1345
 	fr += (ieee->l>>16) & ((1L<<16)-1L);
taruti@0 1346
 	fr /= 1L<<16;
taruti@0 1347
 	fr += (ieee->h & (1L<<20)-1L) | (1L<<20);
taruti@0 1348
 	fr /= 1L<<21;
taruti@0 1349
 	exp = (ieee->h>>20) & ((1L<<11)-1L);
taruti@0 1350
 	exp -= (1L<<10) - 2L;
taruti@0 1351
 	return ldexp(fr, exp);
taruti@0 1352
 }