changelog shortlog tags branches changeset files file revisions raw help

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

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