xref: /plan9-contrib/sys/src/cmd/vi/vi.c (revision bb43afe423a7a925fe6bf0f50e9f0e6b24a63d80)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 #include <tos.h>
6 #define Extern
7 #include "mips.h"
8 
9 char	*file = "v.out";
10 int	datasize;
11 ulong	textbase;
12 Biobuf	bp, bi;
13 Fhdr	fhdr;
14 
15 void
main(int argc,char ** argv)16 main(int argc, char **argv)
17 {
18 	int pid;
19 
20 	argc--;
21 	argv++;
22 
23 	bioout = &bp;
24 	bin = &bi;
25 	Binit(bioout, 1, OWRITE);
26 	Binit(bin, 0, OREAD);
27 
28 	tlb.on = 1;
29 	tlb.tlbsize = 24;
30 
31 	if(argc) {
32 		pid = atoi(argv[0]);
33 		if(pid != 0) {
34 			procinit(pid);
35 			cmd();
36 		}
37 		file = argv[0];
38 	}
39 	argc--;
40 	argv++;
41 
42 	text = open(file, OREAD);
43 	if(text < 0)
44 		fatal(1, "open text '%s'", file);
45 
46 	Bprint(bioout, "vi\n");
47 	inithdr(text);
48 	initstk(argc, argv);
49 
50 	reg.fd[dreg(24)] = 0.0;		/* Normally initialised by the kernel */
51 	reg.ft[24] = FPd;
52 	reg.fd[dreg(26)] = 0.5;
53 	reg.ft[26] = FPd;
54 	reg.fd[dreg(28)] = 1.0;
55 	reg.ft[28] = FPd;
56 	reg.fd[dreg(30)] = 2.0;
57 	reg.ft[30] = FPd;
58 	cmd();
59 }
60 
61 void
initmap()62 initmap()
63 {
64 	ulong t, d, b, bssend;
65 	Segment *s;
66 
67 	t = (fhdr.txtaddr+fhdr.txtsz+(BY2PG-1)) & ~(BY2PG-1);
68 	d = (t + fhdr.datsz + (BY2PG-1)) & ~(BY2PG-1);
69 	bssend = t + fhdr.datsz + fhdr.bsssz;
70 	b = (bssend + (BY2PG-1)) & ~(BY2PG-1);
71 
72 	s = &memory.seg[Text];
73 	s->type = Text;
74 	s->base = fhdr.txtaddr - fhdr.hdrsz;
75 	s->end = t;
76 	s->fileoff = fhdr.txtoff - fhdr.hdrsz;
77 	s->fileend = s->fileoff + fhdr.txtsz;
78 	s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
79 
80 	iprof = emalloc(((s->end-s->base)/PROFGRAN)*sizeof(long));
81 	textbase = s->base;
82 
83 	s = &memory.seg[Data];
84 	s->type = Data;
85 	s->base = t;
86 	s->end = t+(d-t);
87 	s->fileoff = fhdr.datoff;
88 	s->fileend = s->fileoff + fhdr.datsz;
89 	datasize = fhdr.datsz;
90 	s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
91 
92 	s = &memory.seg[Bss];
93 	s->type = Bss;
94 	s->base = d;
95 	s->end = d+(b-d);
96 	s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
97 
98 	s = &memory.seg[Stack];
99 	s->type = Stack;
100 	s->base = STACKTOP-STACKSIZE;
101 	s->end = STACKTOP;
102 	s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
103 
104 	reg.pc = fhdr.entry;
105 }
106 
107 void
inithdr(int fd)108 inithdr(int fd)
109 {
110 	Symbol s;
111 
112 	extern Machdata mipsmach;
113 
114 	seek(fd, 0, 0);
115 	if (!crackhdr(fd, &fhdr))
116 		fatal(0, "read text header");
117 
118 	if(fhdr.type != FMIPS && fhdr.type != FMIPS2BE)
119 		fatal(0, "bad magic number: %d %d", fhdr.type, FMIPS);
120 
121 	if (syminit(fd, &fhdr) < 0)
122 		fatal(0, "%r\n");
123 
124 	symmap = loadmap(symmap, fd, &fhdr);
125 	if (mach->sbreg && lookup(0, mach->sbreg, &s))
126 		mach->sb = s.value;
127 	machdata = &mipsmach;
128 }
129 
130 ulong
greg(int f,ulong off)131 greg(int f, ulong off)
132 {
133 	int n;
134 	ulong l;
135 	uchar wd[BY2WD];
136 
137 	seek(f, off, 0);
138 	n = read(f, wd, BY2WD);
139 	if(n != BY2WD)
140 		fatal(1, "read register");
141 
142 	l  = wd[0]<<24;
143 	l |= wd[1]<<16;
144 	l |= wd[2]<<8;
145 	l |= wd[3];
146 	return l;
147 }
148 
149 ulong
150 roff[] = {
151 	REGOFF(r1),	REGOFF(r2),	REGOFF(r3),
152 	REGOFF(r4),	REGOFF(r5),	REGOFF(r6),
153 	REGOFF(r7),	REGOFF(r8),	REGOFF(r9),
154 	REGOFF(r10),	REGOFF(r11),	REGOFF(r12),
155 	REGOFF(r13),	REGOFF(r14),	REGOFF(r15),
156 	REGOFF(r16),	REGOFF(r17),	REGOFF(r18),
157 	REGOFF(r19),	REGOFF(r20),	REGOFF(r21),
158 	REGOFF(r22),	REGOFF(r23),	REGOFF(r24),
159 	REGOFF(r25),	REGOFF(r26),	REGOFF(r27),
160 	REGOFF(r28)
161 };
162 
163 void
seginit(int fd,Segment * s,int idx,ulong vastart,ulong vaend)164 seginit(int fd, Segment *s, int idx, ulong vastart, ulong vaend)
165 {
166 	int n;
167 
168 	while(vastart < vaend) {
169 		seek(fd, vastart, 0);
170 		s->table[idx] = emalloc(BY2PG);
171 		n = read(fd, s->table[idx], BY2PG);
172 		if(n != BY2PG)
173 			fatal(1, "data read");
174 		vastart += BY2PG;
175 		idx++;
176 	}
177 }
178 
179 void
procinit(int pid)180 procinit(int pid)
181 {
182 	char *p;
183 	Segment *s;
184 	int n, m, sg, i;
185 	ulong vastart, vaend;
186 	char mfile[128], tfile[128], sfile[1024];
187 
188 	sprint(mfile, "/proc/%d/mem", pid);
189 	sprint(tfile, "/proc/%d/text", pid);
190 	sprint(sfile, "/proc/%d/segment", pid);
191 
192 	text = open(tfile, OREAD);
193 	if(text < 0)
194 		fatal(1, "open text %s", tfile);
195 	inithdr(text);
196 
197 	sg = open(sfile, OREAD);
198 	if(sg < 0)
199 		fatal(1, "open text %s", sfile);
200 
201 	n = read(sg, sfile, sizeof(sfile));
202 	if(n >= sizeof(sfile))
203 		fatal(0, "segment file buffer too small");
204 	close(sg);
205 
206 	m = open(mfile, OREAD);
207 	if(m < 0)
208 		fatal(1, "open %s", mfile);
209 
210 	initmap();
211 	p = strstr(sfile, "Data");
212 	if(p == 0)
213 		fatal(0, "no data");
214 
215 	vastart = strtoul(p+9, 0, 16);
216 	vaend = strtoul(p+18, 0, 16);
217 	s = &memory.seg[Data];
218 	if(s->base != vastart || s->end != vaend) {
219 		s->base = vastart;
220 		s->end = vaend;
221 		free(s->table);
222 		s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
223 	}
224 	seginit(m, s, 0, vastart, vaend);
225 
226 	p = strstr(sfile, "Bss");
227 	if(p == 0)
228 		fatal(0, "no bss");
229 
230 	vastart = strtoul(p+9, 0, 16);
231 	vaend = strtoul(p+18, 0, 16);
232 	s = &memory.seg[Bss];
233 	if(s->base != vastart || s->end != vaend) {
234 		s->base = vastart;
235 		s->end = vaend;
236 		free(s->table);
237 		s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
238 	}
239 	seginit(m, s, 0, vastart, vaend);
240 
241 	reg.pc = greg(m, REGOFF(pc));
242 	reg.r[29] = greg(m, REGOFF(sp));
243 	reg.r[30] = greg(m, REGOFF(r30));
244 	reg.r[31] = greg(m, REGOFF(r31));
245 
246 	reg.mhi = greg(m, REGOFF(hi));
247 	reg.mlo = greg(m, REGOFF(lo));
248 
249 	for(i = 1; i < 29; i++)
250 		reg.r[i] = greg(m, roff[i-1]);
251 
252 	s = &memory.seg[Stack];
253 	vastart = reg.r[29] & ~(BY2PG-1);
254 	seginit(m, s, (vastart-s->base)/BY2PG, vastart, STACKTOP);
255 	close(m);
256 	Bprint(bioout, "vi\n");
257 }
258 
259 void
reset(void)260 reset(void)
261 {
262 	int i, l, m;
263 	Segment *s;
264 	Breakpoint *b;
265 
266 	memset(&reg, 0, sizeof(Registers));
267 	reg.fd[dreg(24)] = 0.0;		/* Normally initialised by the kernel */
268 	reg.ft[24] = FPd;
269 	reg.fd[dreg(26)] = 0.5;
270 	reg.ft[26] = FPd;
271 	reg.fd[dreg(28)] = 1.0;
272 	reg.ft[28] = FPd;
273 	reg.fd[dreg(30)] = 2.0;
274 	reg.ft[30] = FPd;
275 
276 	for(i = 0; i > Nseg; i++) {
277 		s = &memory.seg[i];
278 		l = ((s->end-s->base)/BY2PG)*sizeof(uchar*);
279 		for(m = 0; m < l; m++)
280 			if(s->table[m])
281 				free(s->table[m]);
282 		free(s->table);
283 	}
284 	free(iprof);
285 	memset(&memory, 0, sizeof(memory));
286 
287 	for(b = bplist; b; b = b->next)
288 		b->done = b->count;
289 }
290 
291 void
initstk(int argc,char * argv[])292 initstk(int argc, char *argv[])
293 {
294 	ulong size;
295 	ulong sp, ap, tos;
296 	int i;
297 	char *p;
298 
299 	initmap();
300 	tos = STACKTOP - sizeof(Tos)*2;	/* we'll assume twice the host's is big enough */
301 	sp = tos;
302 	for (i = 0; i < sizeof(Tos)*2; i++)
303 		putmem_b(tos + i, 0);
304 
305 	/*
306 	 * pid is second word from end of tos and needs to be set for nsec().
307 	 * we know mips is a 32-bit cpu, so we'll assume knowledge of the Tos
308 	 * struct for now, and use our pid.
309 	 */
310 	putmem_w(tos + 4*4 + 2*sizeof(ulong) + 3*sizeof(uvlong), getpid());
311 
312 	/* Build exec stack */
313 	size = strlen(file)+1+BY2WD+BY2WD+BY2WD;
314 	for(i = 0; i < argc; i++)
315 		size += strlen(argv[i])+BY2WD+1;
316 
317 	sp -= size;
318 	sp &= ~3;
319 	reg.r[29] = sp;
320 	reg.r[1] = tos;			/* Plan 9 profiling clock, etc. */
321 
322 	/* Push argc */
323 	putmem_w(sp, argc+1);
324 	sp += BY2WD;
325 
326 	/* Compute sizeof(argv) and push argv[0] */
327 	ap = sp+((argc+1)*BY2WD)+BY2WD;
328 	putmem_w(sp, ap);
329 	sp += BY2WD;
330 
331 	/* Build argv[0] string into stack */
332 	for(p = file; *p; p++)
333 		putmem_b(ap++, *p);
334 
335 	putmem_b(ap++, '\0');
336 
337 	/* Loop through pushing the arguments */
338 	for(i = 0; i < argc; i++) {
339 		putmem_w(sp, ap);
340 		sp += BY2WD;
341 		for(p = argv[i]; *p; p++)
342 			putmem_b(ap++, *p);
343 		putmem_b(ap++, '\0');
344 	}
345 	/* Null terminate argv */
346 	putmem_w(sp, 0);
347 
348 }
349 
350 void
fatal(int syserr,char * fmt,...)351 fatal(int syserr, char *fmt, ...)
352 {
353 	char buf[ERRMAX], *s;
354 	va_list arg;
355 
356 	va_start(arg, fmt);
357 	vseprint(buf, buf+sizeof(buf), fmt, arg);
358 	va_end(arg);
359 	s = "vi: %s\n";
360 	if(syserr)
361 		s = "vi: %s: %r\n";
362 	fprint(2, s, buf);
363 	exits(buf);
364 }
365 
366 void
itrace(char * fmt,...)367 itrace(char *fmt, ...)
368 {
369 	char buf[128];
370 	va_list arg;
371 
372 	va_start(arg, fmt);
373 	vseprint(buf, buf+sizeof(buf), fmt, arg);
374 	va_end(arg);
375 	Bprint(bioout, "%8lux %.8lux %s\n", reg.pc, reg.ir, buf);
376 }
377 
378 void
dumpreg(void)379 dumpreg(void)
380 {
381 	int i;
382 
383 	Bprint(bioout, "PC  #%-8lux SP  #%-8lux HI  #%-8lux LO  #%-8lux\n",
384 				reg.pc, reg.r[29], reg.mhi, reg.mlo);
385 
386 	for(i = 0; i < 32; i++) {
387 		if((i%4) == 0 && i != 0)
388 			Bprint(bioout, "\n");
389 		Bprint(bioout, "R%-2d #%-8lux ", i, reg.r[i]);
390 	}
391 	Bprint(bioout, "\n");
392 }
393 
394 void
dumpfreg(void)395 dumpfreg(void)
396 {
397 	int i;
398 	char buf[64];
399 
400 	i = 0;
401 	while(i < 32) {
402 		ieeesftos(buf, sizeof(buf), reg.di[i]);
403 		Bprint(bioout, "F%-2d %s\t", i, buf);
404 		i++;
405 
406 		ieeesftos(buf, sizeof(buf), reg.di[i]);
407 		Bprint(bioout, "\t\t\tF%-2d %s\n", i, buf);
408 		i++;
409 	}
410 }
411 
412 void
dumpdreg(void)413 dumpdreg(void)
414 {
415 	int i;
416 	char buf[64];
417 
418 	i = 0;
419 	while(i < 32) {
420 		if(reg.ft[i] == FPd)
421 			ieeedftos(buf, sizeof(buf), reg.di[i] ,reg.di[i+1]);
422 		else
423 			ieeedftos(buf, sizeof(buf), reg.di[i+1] ,reg.di[i]);
424 		Bprint(bioout, "F%-2d %s\t\t\t", i, buf);
425 		i += 2;
426 
427 		if(reg.ft[i] == FPd)
428 			ieeedftos(buf, sizeof(buf), reg.di[i] ,reg.di[i+1]);
429 		else
430 			ieeedftos(buf, sizeof(buf), reg.di[i+1] ,reg.di[i]);
431 		Bprint(bioout, "F%-2d %s\n", i, buf);
432 		i += 2;
433 	}
434 }
435 
436 void *
emalloc(ulong size)437 emalloc(ulong size)
438 {
439 	void *a;
440 
441 	a = malloc(size);
442 	if(a == 0)
443 		fatal(0, "no memory");
444 
445 	memset(a, 0, size);
446 	return a;
447 }
448 
449 void *
erealloc(void * a,ulong oldsize,ulong size)450 erealloc(void *a, ulong oldsize, ulong size)
451 {
452 	void *n;
453 
454 	n = malloc(size);
455 	if(n == 0)
456 		fatal(0, "no memory");
457 	memset(n, 0, size);
458 	if(size > oldsize)
459 		size = oldsize;
460 	memmove(n, a, size);
461 	return n;
462 }
463 
464 Mulu
mulu(ulong u1,ulong u2)465 mulu(ulong u1, ulong u2)
466 {
467 	ulong lo1, lo2, hi1, hi2, lo, hi, t1, t2, t;
468 
469 	lo1 = u1 & 0xffff;
470 	lo2 = u2 & 0xffff;
471 	hi1 = u1 >> 16;
472 	hi2 = u2 >> 16;
473 
474 	lo = lo1 * lo2;
475 	t1 = lo1 * hi2;
476 	t2 = lo2 * hi1;
477 	hi = hi1 * hi2;
478 	t = lo;
479 	lo += t1 << 16;
480 	if(lo < t)
481 		hi++;
482 	t = lo;
483 	lo += t2 << 16;
484 	if(lo < t)
485 		hi++;
486 	hi += (t1 >> 16) + (t2 >> 16);
487 	return (Mulu){lo, hi};
488 }
489 
490 Mul
mul(long l1,long l2)491 mul(long l1, long l2)
492 {
493 	Mulu m;
494 	ulong t, lo, hi;
495 	int sign;
496 
497 	sign = 0;
498 	if(l1 < 0){
499 		sign ^= 1;
500 		l1 = -l1;
501 	}
502 	if(l2 < 0){
503 		sign ^= 1;
504 		l2 = -l2;
505 	}
506 	m = mulu(l1, l2);
507 	lo = m.lo;
508 	hi = m.hi;
509 	if(sign){
510 		t = lo = ~lo;
511 		hi = ~hi;
512 		lo++;
513 		if(lo < t)
514 			hi++;
515 	}
516 	return (Mul){lo, hi};
517 }
518 
519