xref: /plan9-contrib/sys/src/libaml/aml.c (revision ebd848c130c5a90707793ad058d6d29ac82262e7)
1 #include <u.h>
2 #include <libc.h>
3 #include <aml.h>
4 
5 typedef struct Interp Interp;
6 typedef struct Frame Frame;
7 typedef struct Heap Heap;
8 
9 typedef struct Method Method;
10 typedef struct Region Region;
11 typedef struct Field Field;
12 
13 typedef struct Name Name;
14 typedef struct Ref Ref;
15 typedef struct Env Env;
16 typedef struct Op Op;
17 
18 struct Heap {
19 	Heap	*link;
20 	short	size;
21 	uchar	mark;
22 	char	tag;
23 };
24 
25 #define H2D(h)	(((Heap*)(h))+1)
26 #define D2H(d)	(((Heap*)(d))-1)
27 #define TAG(d)	D2H(d)->tag
28 #define SIZE(d)	D2H(d)->size
29 
30 static char *spacename[] = {
31 	"Mem",
32 	"Io",
33 	"Pcicfg",
34 	"Ebctl",
35 	"Smbus",
36 	"Cmos",
37 	"Pcibar",
38 	"Ipmi",
39 };
40 
41 /* field flags */
42 enum {
43 	AnyAcc		= 0x00,
44 	ByteAcc		= 0x01,
45 	WordAcc		= 0x02,
46 	DWordAcc	= 0x03,
47 	QWordAcc	= 0x04,
48 	BufferAcc	= 0x05,
49 	AccMask		= 0x07,
50 
51 	NoLock		= 0x10,
52 
53 	Preserve	= 0x00,
54 	WriteAsOnes	= 0x20,
55 	WriteAsZeros	= 0x40,
56 	UpdateMask	= 0x60,
57 };
58 
59 struct Method {
60 	Name	*name;
61 	int	narg;
62 	void*	(*eval)(void);
63 	uchar	*start;
64 	uchar	*end;
65 };
66 
67 struct Region {
68 	Amlio;
69 	char	mapped;
70 };
71 
72 struct Field {
73 	void	*reg;	/* Buffer or Region */
74 	Field	*index;
75 	void	*indexv;
76 	int	flags;
77 	int	bitoff;
78 	int	bitlen;
79 };
80 
81 struct Name {
82 	void	*v;
83 
84 	Name	*up;
85 	Name	*next;
86 	Name	*fork;
87 	Name	*down;
88 
89 	char	seg[4];
90 };
91 
92 struct Ref {
93 	void	*ref;
94 	void	**ptr;
95 };
96 
97 struct Env {
98 	void	*loc[8];
99 	void	*arg[8];
100 };
101 
102 struct Op {
103 	char	*name;
104 	char	*sequence;
105 	void*	(*eval)(void);
106 };
107 
108 struct Frame {
109 	int	tag;
110 	int	cond;
111 	char	*phase;
112 	uchar	*start;
113 	uchar	*end;
114 	Op	*op;
115 	Env	*env;
116 	Name	*dot;
117 	void	*ref;
118 	void	*aux;
119 	int	narg;
120 	void	*arg[8];
121 };
122 
123 struct Interp {
124 	uchar	*pc;
125 	Frame	*fp;
126 };
127 
128 static Interp	interp;
129 static Frame	stack[32];
130 
131 #define PC	interp.pc
132 #define	FP	interp.fp
133 #define FB	stack
134 #define FT	&stack[nelem(stack)]
135 
136 static Heap *hp;
137 
138 enum {
139 	Obad, Onop, Odebug,
140 	Ostr, Obyte, Oword, Odword, Oqword, Oconst,
141 	Onamec, Oname, Oscope, Oalias,
142 	Oreg, Ofld, Oxfld, Opkg, Ovpkg, Oenv, Obuf, Omet,
143 	Odev, Ocpu, Othz, Oprc,
144 	Oadd, Osub, Omod, Omul, Odiv, Oshl, Oshr, Oand, Onand, Oor,
145 	Onor, Oxor, Onot, Olbit, Orbit, Oinc, Odec,
146 	Oland, Olor, Olnot, Oleq, Olgt, Ollt,
147 	Oindex, Omutex, Oevent,
148 	Ocfld, Ocfld0, Ocfld1, Ocfld2, Ocfld4, Ocfld8,
149 	Oif, Oelse, Owhile, Obreak, Oret, Ocall,
150 	Ostore, Oderef, Osize, Oref, Ocref, Ocat,
151 	Oacq, Orel, Ostall, Osleep, Oload, Ounload,
152 };
153 
154 static Op optab[];
155 static uchar octab1[];
156 static uchar octab2[];
157 
158 static Name*
rootname(Name * dot)159 rootname(Name *dot)
160 {
161 	while(dot != dot->up)
162 		dot = dot->up;
163 	return dot;
164 }
165 
166 static void
gcmark(void * p)167 gcmark(void *p)
168 {
169 	int i;
170 	Env *e;
171 	Field *f;
172 	Heap *h;
173 	Name *n, *d;
174 
175 	if(p == nil)
176 		return;
177 	h = D2H(p);
178 	if(h->mark & 1)
179 		return;
180 	h->mark |= 1;
181 	switch(h->tag){
182 	case 'E':
183 		e = p;
184 		for(i=0; i<nelem(e->loc); i++)
185 			gcmark(e->loc[i]);
186 		for(i=0; i<nelem(e->arg); i++)
187 			gcmark(e->arg[i]);
188 		break;
189 	case 'R':
190 	case 'A':
191 	case 'L':
192 		gcmark(((Ref*)p)->ref);
193 		break;
194 	case 'N':
195 		n = p;
196 		gcmark(n->v);
197 		for(d = n->down; d; d = d->next)
198 			gcmark(d);
199 		gcmark(n->fork);
200 		gcmark(n->up);
201 		break;
202 	case 'p':
203 		for(i=0; i<(SIZE(p)/sizeof(void*)); i++)
204 			gcmark(((void**)p)[i]);
205 		break;
206 	case 'r':
207 		gcmark(((Region*)p)->name);
208 		break;
209 	case 'm':
210 		gcmark(((Method*)p)->name);
211 		break;
212 	case 'f':
213 	case 'u':
214 		f = p;
215 		gcmark(f->reg);
216 		gcmark(f->index);
217 		gcmark(f->indexv);
218 		break;
219 	}
220 }
221 
222 static int
gc(void)223 gc(void)
224 {
225 	int i;
226 	Heap *h, **hh;
227 	Frame *f;
228 
229 	for(h = hp; h; h = h->link)
230 		h->mark &= ~1;
231 
232 	for(h = hp; h; h = h->link)
233 		if(h->mark & 2)
234 			gcmark(H2D(h));
235 
236 	for(f = FP; f >= FB; f--){
237 		for(i=0; i<f->narg; i++)
238 			gcmark(f->arg[i]);
239 		gcmark(f->env);
240 		gcmark(f->dot);
241 		gcmark(f->ref);
242 	}
243 
244 	gcmark(amlroot);
245 
246 	i = 0;
247 	hh = &hp;
248 	while(h = *hh){
249 		if(h->mark){
250 			hh = &h->link;
251 			continue;
252 		}
253 		*hh = h->link;
254 		if(h->tag == 'r'){
255 			Region *r = (void*)H2D(h);
256 			if(r->mapped > 0){
257 				if(amldebug)
258 					print("\namlunmapio(%N): %-8s %llux - %llux\n",
259 						(Name*)r->name, spacename[r->space],
260 						r->off, r->off + r->len);
261 				amlunmapio(r);
262 			}
263 			r->mapped = 0;
264 			r->write = nil;
265 			r->read = nil;
266 			r->aux = nil;
267 			r->va = nil;
268 		}
269 		memset(h, ~0, sizeof(Heap)+h->size);
270 		amlfree(h);
271 		i++;
272 	}
273 
274 	return i;
275 }
276 
277 static void*
mk(int tag,int size)278 mk(int tag, int size)
279 {
280 	Heap *h;
281 	int a;
282 
283 	a = sizeof(Heap) + size;
284 	h = amlalloc(a);
285 	h->size = size;
286 	h->tag = tag;
287 	h->link = hp;
288 	hp = h;
289 	return h+1;
290 }
291 
292 static uvlong*
mki(uvlong i)293 mki(uvlong i)
294 {
295 	uvlong *v;
296 
297 	v = mk('i', sizeof(uvlong));
298 	*v = i;
299 	return v;
300 }
301 
302 static char*
mks(char * s)303 mks(char *s)
304 {
305 	char *r = mk('s', strlen(s)+1);
306 	strcpy(r, s);
307 	return r;
308 }
309 
310 static int
pkglen(uchar * p,uchar * e,uchar ** np)311 pkglen(uchar *p, uchar *e, uchar **np)
312 {
313 	ulong n;
314 	uchar b;
315 
316 	if(p >= e)
317 		return -1;
318 	b = *p++;
319 	if(b <= 0x3F)
320 		n = b;
321 	else {
322 		n = b & 0xF;
323 		if(p >= e)
324 			return -1;
325 		n += *p++ << 4;
326 		if(b >= 0x80){
327 			if(p >= e)
328 				return -1;
329 			n += *p++ << 12;
330 		}
331 		if(b >= 0xC0){
332 			if(p >= e)
333 				return -1;
334 			n += *p++ << 20;
335 		}
336 	}
337 	if(np)
338 		*np = p;
339 	return n;
340 }
341 
342 static Name*
forkname(Name * dot)343 forkname(Name *dot)
344 {
345 	Name *n;
346 
347 	n = mk('N', sizeof(Name));
348 	*n = *dot;
349 	n->fork = dot;
350 	n->next = n->down = nil;
351 	if(dot->v == dot)
352 		n->v = n;
353 	if(dot->up == dot)
354 		n->up = n;
355 	else {
356 		if(n->up = forkname(dot->up))
357 			n->up->down = n;
358 	}
359 	return n;
360 }
361 
362 static Name*
getseg(Name * dot,void * seg,int new)363 getseg(Name *dot, void *seg, int new)
364 {
365 	Name *n, *l;
366 
367 	for(n = l = nil; dot; dot = dot->fork){
368 		for(n = dot->down; n; n = n->next){
369 			if(memcmp(seg, n->seg, 4) == 0)
370 				return n;
371 			l = n;
372 		}
373 		if(new){
374 			n = mk('N', sizeof(Name));
375 			memmove(n->seg, seg, sizeof(n->seg));
376 			n->up = dot;
377 			if(l == nil)
378 				dot->down = n;
379 			else
380 				l->next = n;
381 			n->v = n;
382 			break;
383 		}
384 	}
385 	return n;
386 }
387 
388 Name*
getname(Name * dot,char * path,int new)389 getname(Name *dot, char *path, int new)
390 {
391 	char seg[4];
392 	int i, s;
393 	Name *x;
394 
395 	s = !new;
396 	if(*path == '\\'){
397 		path++;
398 		dot = rootname(dot);
399 		s = 0;
400 	}
401 	while(*path == '^'){
402 		path++;
403 		dot = dot->up;
404 		s = 0;
405 	}
406 	do {
407 		for(i=0; i<4; i++){
408 			if(*path == 0 || *path == '.')
409 				break;
410 			seg[i] = *path++;
411 		}
412 		if(i == 0)
413 			break;
414 		while(i < 4)
415 			seg[i++] = '_';
416 		if(s && *path == 0){
417 			for(;;){
418 				if(x = getseg(dot, seg, 0))
419 					break;
420 				if(dot == dot->up)
421 					break;
422 				dot = dot->up;
423 			}
424 			return x;
425 		}
426 		s = 0;
427 		dot = getseg(dot, seg, new);
428 	} while(*path++ == '.');
429 
430 	return dot;
431 }
432 
433 static int
fixnames(void * dot,void * arg)434 fixnames(void *dot, void *arg)
435 {
436 	void **r, *v;
437 	int i;
438 
439 	if(arg == nil)
440 		r = &((Name*)dot)->v;
441 	else
442 		r = arg;
443 	v = *r;
444 	if(v == nil || v == dot)
445 		return 0;
446 	if(TAG(v) == 'p'){
447 		r = (void**)v;
448 		for(i=0; i<(SIZE(r)/sizeof(void*)); i++)
449 			fixnames(dot, r+i);
450 		return 0;
451 	}
452 	if(TAG(v) == 'n' && (v = getname(dot, v, 0)) != nil)
453 		*r = v;
454 	return 0;
455 }
456 
457 static uvlong
getle(uchar * p,int len)458 getle(uchar *p, int len)
459 {
460 	uvlong v;
461 	int i;
462 
463 	v = 0ULL;
464 	for(i=0; i<len; i++)
465 		v |= ((uvlong)p[i]) << i*8;
466 	return v;
467 }
468 
469 static void
putle(uchar * p,int len,uvlong v)470 putle(uchar *p, int len, uvlong v)
471 {
472 	int i;
473 
474 	for(i=0; i<len; i++){
475 		p[i] = v;
476 		v >>= 8;
477 	}
478 }
479 
480 static uvlong
rwreg(void * reg,int off,int len,uvlong v,int write)481 rwreg(void *reg, int off, int len, uvlong v, int write)
482 {
483 	uchar buf[8], *p;
484 	Region *r;
485 
486 	switch(TAG(reg)){
487 	case 'b':
488 		p = reg;
489 		if((off+len) > SIZE(p))
490 			break;
491 		p += off;
492 		if(write)
493 			putle(p, len, v);
494 		else
495 			v = getle(p, len);
496 		return v;
497 
498 	case 'r':
499 		r = reg;
500 		if((off+len) > r->len)
501 			break;
502 		if(r->mapped == 0){
503 			if(amldebug)
504 				print("\namlmapio(%N): %-8s %llux - %llux\n",
505 					(Name*)r->name, spacename[r->space],
506 					r->off, r->off + r->len);
507 			r->mapped = 1;
508 			if(amlmapio(r) < 0)
509 				r->mapped = -1;
510 		}
511 		if(r->mapped <= 0)
512 			break;
513 
514 		if(r->va != nil)
515 			p = r->va + off;
516 		else {
517 			if(len > sizeof(buf))
518 				break;
519 			p = buf;
520 		}
521 
522 		if(write){
523 			if(amldebug)
524 				print("\nrwreg(%N): %-8s [%llux+%x]/%d <- %llux\n",
525 					(Name*)r->name, spacename[r->space],
526 					r->off, off, len, v);
527 			putle(p, len, v);
528 			if(r->write != nil){
529 				if((*r->write)(r, p, len, off) != len)
530 					break;
531 			} else if(p == buf)
532 				break;
533 		} else {
534 			if(r->read != nil){
535 				if((*r->read)(r, p, len, off) != len)
536 					break;
537 			} else if(p == buf)
538 				break;
539 			v = getle(p, len);
540 			if(amldebug)
541 				print("\nrwreg(%N): %-8s [%llux+%x]/%d -> %llux\n",
542 					(Name*)r->name, spacename[r->space],
543 					r->off, off, len, v);
544 		}
545 		return v;
546 	}
547 
548 	return ~0;
549 }
550 
551 static uvlong
ival(void * p)552 ival(void *p)
553 {
554 	int n;
555 
556 	if(p != nil){
557 		switch(TAG(p)){
558 		case 'i':
559 			return *((uvlong*)p);
560 		case 's':
561 			if(*((char*)p) == 0)
562 				break;
563 			return strtoull((char*)p, 0, 16);
564 		case 'b':
565 			n = SIZE(p);
566 			if(n > 0){
567 				if(n > 8) n = 8;
568 				return rwreg(p, 0, n, 0, 0);
569 			}
570 		}
571 	}
572 	return 0;
573 }
574 
575 static void *deref(void *p);
576 static void *store(void *s, void *d);
577 
578 static int
fieldalign(int flags)579 fieldalign(int flags)
580 {
581 	switch(flags & AccMask){
582 	default:
583 	case AnyAcc:
584 	case ByteAcc:
585 	case BufferAcc:
586 		return 1;
587 	case WordAcc:
588 		return 2;
589 	case DWordAcc:
590 		return 4;
591 	case QWordAcc:
592 		return 8;
593 	}
594 }
595 
596 static void*
rwfield(Field * f,void * v,int write)597 rwfield(Field *f, void *v, int write)
598 {
599 	int boff, blen, wo, ws, wl, wa, wd, i;
600 	uvlong w, m;
601 	void *reg;
602 	uchar *b;
603 
604 	if(f == nil || (reg = deref(f->reg)) == nil)
605 		return nil;
606 	if(f->index)
607 		store(f->indexv, f->index);
608 	blen = f->bitlen;
609 	if(write){
610 		if(v && TAG(v) == 'b'){
611 			b = v;
612 			if(SIZE(b)*8 < blen)
613 				blen = SIZE(b)*8;
614 		} else {
615 			w = ival(v);
616 			b = mk('b', (blen+7)/8);
617 			putle(b, SIZE(b), w);
618 		}
619 	} else
620 		b = mk('b', (blen+7)/8);
621 	wa = fieldalign(f->flags);
622 	wd = wa*8;
623 	boff = 0;
624 	while((wl = (blen-boff)) > 0){
625 		wo = (f->bitoff+boff) / wd;
626 		ws = (f->bitoff+boff) % wd;
627 		if(wl > (wd - ws))
628 			wl = wd - ws;
629 		if(write){
630 			w = 0;
631 			for(i = 0; i < wl; i++, boff++)
632 				if(b[boff/8] & (1<<(boff%8)))
633 					w |= 1ULL<<i;
634 			w <<= ws;
635 			if(wl != wd){
636 				m = ((1ULL<<wl)-1) << ws;
637 				w |= rwreg(reg, wo*wa, wa, 0, 0) & ~m;
638 			}
639 			rwreg(reg, wo*wa, wa, w, 1);
640 		} else {
641 			w = rwreg(reg, wo*wa, wa, 0, 0) >> ws;
642 			for(i = 0; i < wl; i++, boff++){
643 				b[boff/8] |= (w&1)<<(boff%8);
644 				w >>= 1;
645 			}
646 		}
647 	}
648 	if(write)
649 		return nil;
650 	if(blen > 64)
651 		return b;
652 	w = getle(b, SIZE(b));
653 	return mki(w);
654 }
655 
656 static void*
deref(void * p)657 deref(void *p)
658 {
659 	if(p) switch(TAG(p)){
660 	case 'N':
661 		return ((Name*)p)->v;
662 	case 'R': case 'A': case 'L':
663 		return *((Ref*)p)->ptr;
664 	case 'f': case 'u':
665 		return rwfield(p, nil, 0);
666 	}
667 	return p;
668 }
669 
670 static void*
copy(int tag,void * s)671 copy(int tag, void *s)
672 {
673 	static char hex[] = "0123456789ABCDEF";
674 	uvlong v;
675 	void *d;
676 	int i, n;
677 
678 	if(tag == 0){
679 		if(s == nil)
680 			return nil;
681 		tag = TAG(s);
682 	}
683 	if(s == nil || TAG(s) == 'i'){
684 		n = 4;
685 		v = ival(s);
686 		if(v > 0xFFFFFFFFULL)
687 			n <<= 1;
688 		switch(tag){
689 		case 'b':
690 			d = mk(tag, n);
691 			rwreg(d, 0, n, v, 1);
692 			return d;
693 		case 's':
694 			n <<= 1;
695 			d = mk(tag, n+1);
696 			((char*)d)[n] = 0;
697 			while(n > 0){
698 				((char*)d)[--n] = hex[v & 0xF];
699 				v >>= 4;
700 			}
701 			return d;
702 		case 'i':
703 			if(v == 0ULL)
704 				return nil;
705 			return mki(v);
706 		}
707 	} else {
708 		n = SIZE(s);
709 		switch(tag){
710 		case 's':
711 			if(TAG(s) == 'b'){
712 				d = mk(tag, n*3 + 1);
713 				for(i=0; i<n; i++){
714 					((char*)d)[i*3 + 0] = hex[((uchar*)s)[i] >> 4];
715 					((char*)d)[i*3 + 1] = hex[((uchar*)s)[i] & 0xF];
716 					((char*)d)[i*3 + 2] = ' ';
717 				}
718 				((char*)d)[n*3] = 0;
719 				return d;
720 			}
721 			/* no break */
722 		case 'b':
723 			if(TAG(s) == 's'){
724 				n = strlen(s);
725 				/* zero length string is converted to zero length buffer */
726 				if(n > 0) n++;
727 			}
728 			d = mk(tag, n);
729 			memmove(d, s, n);
730 			return d;
731 		}
732 	}
733 	return s;
734 }
735 
736 static void*
store(void * s,void * d)737 store(void *s, void *d)
738 {
739 	void *p, **pp;
740 
741 	if(d == nil)
742 		return nil;
743 	switch(TAG(d)){
744 	default:
745 		return nil;
746 	case 'A':
747 		s = deref(s);
748 		/* no break */
749 	case 'R': case 'L':
750 		pp = ((Ref*)d)->ptr;
751 		while((p = *pp) != nil){
752 			switch(TAG(p)){
753 			case 'R': case 'A': case 'L':
754 				pp = ((Ref*)p)->ptr;
755 				break;
756 			case 'N':
757 				pp = &((Name*)p)->v;
758 				break;
759 			}
760 			if(*pp == p)
761 				break;
762 		}
763 		break;
764 	case 'N':
765 		pp = &((Name*)d)->v;
766 		break;
767 	}
768 	p = *pp;
769 	if(p != nil && TAG(p) != 'N'){
770 		switch(TAG(p)){
771 		case 'f':
772 		case 'u':
773 			rwfield(p, s, 1);
774 			return d;
775 		}
776 		if(TAG(d) != 'A' && TAG(d) != 'L'){
777 			*pp = copy(TAG(p), s);
778 			return d;
779 		}
780 	}
781 	*pp = copy(0, s);
782 	return d;
783 }
784 
785 static int
Nfmt(Fmt * f)786 Nfmt(Fmt *f)
787 {
788 	char buf[5];
789 	int i;
790 	Name *n;
791 
792 	n = va_arg(f->args, Name*);
793 	if(n == nil)
794 		return fmtprint(f, "?NIL");
795 	if(n == n->up)
796 		return fmtprint(f, "\\");
797 	strncpy(buf, n->seg, 4);
798 	buf[4] = 0;
799 	for(i=3; i>0; i--){
800 		if(buf[i] != '_')
801 			break;
802 		buf[i] = 0;
803 	}
804 	if(n->up == n->up->up)
805 		return fmtprint(f, "\\%s", buf);
806 	return fmtprint(f, "%N.%s", n->up, buf);
807 }
808 
809 static int
Vfmt(Fmt * f)810 Vfmt(Fmt *f)
811 {
812 	void *p;
813 	int i, n, c;
814 	Env *e;
815 	Field *l;
816 	Name *nm;
817 	Method *m;
818 	Region *g;
819 	Ref *r;
820 
821 	p = va_arg(f->args, void*);
822 	if(p == nil)
823 		return fmtprint(f, "nil");
824 	c = TAG(p);
825 	switch(c){
826 	case 'N':
827 		nm = p;
828 		if(nm->v != nm)
829 			return fmtprint(f, "%N=%V", nm, nm->v);
830 		return fmtprint(f, "%N=*", nm);
831 	case 'A':
832 	case 'L':
833 		r = p;
834 		e = r->ref;
835 		if(c == 'A')
836 			return fmtprint(f, "Arg%ld=%V", r->ptr - e->arg, *r->ptr);
837 		if(c == 'L')
838 			return fmtprint(f, "Local%ld=%V", r->ptr - e->loc, *r->ptr);
839 	case 'n':
840 		return fmtprint(f, "%s", (char*)p);
841 	case 's':
842 		return fmtprint(f, "\"%s\"", (char*)p);
843 	case 'i':
844 		return fmtprint(f, "%#llux", *((uvlong*)p));
845 	case 'p':
846 		n = SIZE(p)/sizeof(void*);
847 		fmtprint(f, "Package(%d){", n);
848 		for(i=0; i<n; i++){
849 			if(i > 0)
850 				fmtprint(f, ", ");
851 			fmtprint(f, "%V", ((void**)p)[i]);
852 		}
853 		fmtprint(f, "}");
854 		return 0;
855 	case 'b':
856 		n = SIZE(p);
857 		fmtprint(f, "Buffer(%d){", n);
858 		for(i=0; i<n; i++){
859 			if(i > 0)
860 				fmtprint(f, ", ");
861 			fmtprint(f, "%.2uX", ((uchar*)p)[i]);
862 		}
863 		fmtprint(f, "}");
864 		return 0;
865 	case 'r':
866 		g = p;
867 		return fmtprint(f, "Region(%s, %#llux, %#llux)",
868 			spacename[g->space & 7], g->off, g->len);
869 	case 'm':
870 		m = p;
871 		fmtprint(f, "%N(", m->name);
872 		for(i=0; i < m->narg; i++){
873 			if(i > 0)
874 				fmtprint(f, ", ");
875 			fmtprint(f, "Arg%d", i);
876 		}
877 		fmtprint(f, ")");
878 		return 0;
879 	case 'u':
880 		fmtprint(f, "Buffer");
881 		/* no break */
882 	case 'f':
883 		l = p;
884 		if(l->index)
885 			return fmtprint(f, "IndexField(%x, %x, %x) @ %V[%V]",
886 				l->flags, l->bitoff, l->bitlen, l->index, l->indexv);
887 		return fmtprint(f, "Field(%x, %x, %x) @ %V",
888 			l->flags, l->bitoff, l->bitlen, l->reg);
889 	default:
890 		return fmtprint(f, "%c:%p", c, p);
891 	}
892 }
893 
894 static void
dumpregs(void)895 dumpregs(void)
896 {
897 	Frame *f;
898 	Env *e;
899 	int i;
900 
901 	print("\n*** dumpregs: PC=%p FP=%p\n", PC, FP);
902 	e = nil;
903 	for(f = FP; f >= FB; f--){
904 		print("%.8p.%.2lx: %-8s %N\t", f->start, f-FB, f->phase, f->dot);
905 		if(f->op)
906 			print("%s", f->op->name);
907 		print("(");
908 		for(i=0; i<f->narg; i++){
909 			if(i > 0)
910 				print(", ");
911 			print("%V", f->arg[i]);
912 		}
913 		print(")\n");
914 		if(e == f->env)
915 			continue;
916 		if(e = f->env){
917 			for(i=0; i<nelem(e->arg); i++)
918 				print("Arg%d=%V ", i, e->arg[i]);
919 			print("\n");
920 			for(i=0; i<nelem(e->loc); i++)
921 				print("Local%d=%V ", i, e->loc[i]);
922 			print("\n");
923 		}
924 	}
925 }
926 
927 static int
xec(uchar * pc,uchar * end,Name * dot,Env * env,void ** pret)928 xec(uchar *pc, uchar *end, Name *dot, Env *env, void **pret)
929 {
930 	static int loop;
931 	int i, c;
932 	void *r;
933 
934 	PC = pc;
935 	FP = FB;
936 
937 	FP->tag = 0;
938 	FP->cond = 0;
939 	FP->narg = 0;
940 	FP->phase = "}";
941 	FP->start = PC;
942 	FP->end = end;
943 	FP->aux = end;
944 	FB->ref = nil;
945 	FP->dot = dot;
946 	FP->env = env;
947 	FP->op = nil;
948 
949 	for(;;){
950 		if((++loop & 127) == 0)
951 			gc();
952 		if(amldebug)
953 			print("\n%.8p.%.2lx %-8s\t%N\t", PC, FP - FB, FP->phase, FP->dot);
954 		r = nil;
955 		c = *FP->phase++;
956 		switch(c){
957 		default:
958 			if(PC >= FP->end){
959 			Overrun:
960 				print("aml: PC overrun frame end");
961 				goto Out;
962 			}
963 			FP++;
964 			if(FP >= FT){
965 				print("aml: frame stack overflow");
966 				goto Out;
967 			}
968 			*FP = FP[-1];
969 			FP->aux = nil;
970 			FP->ref = nil;
971 			FP->tag = c;
972 			FP->start = PC;
973 			c = *PC++;
974 			if(amldebug) print("%.2X", c);
975 			if(c == '['){
976 				if(PC >= FP->end)
977 					goto Overrun;
978 				c = *PC++;
979 				if(amldebug) print("%.2X", c);
980 				c = octab2[c];
981 			}else
982 				c = octab1[c];
983 			FP->op = &optab[c];
984 			FP->narg = 0;
985 			FP->phase = FP->op->sequence;
986 			if(amldebug) print("\t%s %s", FP->op->name, FP->phase);
987 			continue;
988 		case '{':
989 			end = PC;
990 			c = pkglen(PC, FP->end, &PC);
991 			end += c;
992 			if(c < 0 || end > FP->end)
993 				goto Overrun;
994 			FP->end = end;
995 			continue;
996 		case ',':
997 			FP->start = PC;
998 			continue;
999 		case 's':
1000 			if(end = memchr(PC, 0, FP->end - PC))
1001 				end++;
1002 			else
1003 				end = FP->end;
1004 			c = end - PC;
1005 			r = mk('s', c+1);
1006 			memmove(r, PC, c);
1007 			((uchar*)r)[c] = 0;
1008 			PC = end;
1009 			break;
1010 		case '1':
1011 		case '2':
1012 		case '4':
1013 		case '8':
1014 			end = PC+(c-'0');
1015 			if(end > FP->end)
1016 				goto Overrun;
1017 			else {
1018 				r = mki(*PC++);
1019 				for(i = 8; PC < end; i += 8)
1020 					*((uvlong*)r) |= ((uvlong)*PC++) << i;
1021 			}
1022 			break;
1023 		case '}':
1024 		case 0:
1025 			if(FP->op){
1026 				if(amldebug){
1027 					print("*%p,%V\t%s(", FP->aux, FP->ref, FP->op->name);
1028 					for(i = 0; i < FP->narg; i++){
1029 						if(i > 0)
1030 							print(", ");
1031 						print("%V", FP->arg[i]);
1032 					}
1033 					print(")");
1034 				}
1035 				for(i = FP->narg; i < nelem(FP->arg); i++)
1036 					FP->arg[i] = nil;
1037 				r = FP->op->eval();
1038 				if(amldebug)
1039 					print(" -> %V", r);
1040 			}
1041 
1042 			c = FP->phase[-1];
1043 			if(c == '}' && PC < FP->end){
1044 				FP->narg = 0;
1045 				FP->phase = "*}";
1046 				continue;
1047 			}
1048 
1049 			if(r) switch(FP->tag){
1050 			case '@':
1051 				break;
1052 			case 'n':
1053 			case 'N':
1054 				if(TAG(r) != 'N')
1055 					r = nil;
1056 				break;
1057 			default:
1058 				if((r = deref(r)) == nil)
1059 					break;
1060 				switch(TAG(r)){
1061 				case 'f': case 'u':
1062 					r = rwfield(r, nil, 0);
1063 					break;
1064 				case 'm': {
1065 					Method *m = r;
1066 					FP->ref = m;
1067 					FP->narg = 0;
1068 					FP->phase = "********}" + (8 - m->narg);
1069 					FP->op = &optab[Ocall];
1070 					continue;
1071 					}
1072 				}
1073 			}
1074 			FP--;
1075 			break;
1076 		}
1077 		if(FP < FB){
1078 			if(pret){
1079 				if(amldebug) print(" -> %V\n", r);
1080 				*pret = r;
1081 			}
1082 			return 0;
1083 		}
1084 		FP->arg[FP->narg++] = r;
1085 	}
1086 Out:
1087 	if(amldebug)
1088 		dumpregs();
1089 	return -1;
1090 }
1091 
1092 static void*
evalnamec(void)1093 evalnamec(void)
1094 {
1095 	static char name[1024];
1096 	char *d;
1097 	void *r;
1098 	int c;
1099 
1100 	c = 1;
1101 	d = name;
1102 	PC = FP->start;
1103 	if(*PC == '\\')
1104 		*d++ = *PC++;
1105 	while(*PC == '^'){
1106 		if(d >= &name[sizeof(name)-1]){
1107 		Toolong:
1108 			*d = 0;
1109 			print("aml: name too long: %s\n", name);
1110 			PC = FP->end;
1111 			return nil;
1112 		}
1113 		*d++ = *PC++;
1114 	}
1115 	if(*PC == '.'){
1116 		PC++;
1117 		c = 2;
1118 	} else if(*PC == '/'){
1119 		PC++;
1120 		c = *PC++;
1121 	} else if(*PC == 0){
1122 		PC++;
1123 		c = 0;
1124 	}
1125 	while(c > 0){
1126 		if(d >= &name[sizeof(name)-5])
1127 			goto Toolong;
1128 		*d++ = *PC++;
1129 		*d++ = *PC++;
1130 		*d++ = *PC++;
1131 		*d++ = *PC++;
1132 		while((d > &name[0]) && (d[-1] == '_' || d[-1] == 0))
1133 			d--;
1134 		if(--c > 0)
1135 			*d++ = '.';
1136 	}
1137 	*d = 0;
1138 	if((r = getname(FP->dot, name, FP->tag == 'N')) == nil){
1139 		r = mks(name);
1140 		D2H(r)->tag = 'n';	/* unresolved name */
1141 	}
1142 	return r;
1143 }
1144 
1145 static void*
evaliarg0(void)1146 evaliarg0(void)
1147 {
1148 	return FP->arg[0];
1149 }
1150 
1151 static void*
evalconst(void)1152 evalconst(void)
1153 {
1154 	switch(FP->start[0]){
1155 	case 0x01:
1156 		return mki(1);
1157 	case 0xFF:
1158 		return mki(-1);
1159 	}
1160 	return nil;
1161 }
1162 
1163 static void*
evalbuf(void)1164 evalbuf(void)
1165 {
1166 	int n, m;
1167 	uchar *p;
1168 
1169 	n = ival(FP->arg[0]);
1170 	p = mk('b', n);
1171 	m = FP->end - PC;
1172 	if(m > n)
1173 		m = n;
1174 	memmove(p, PC, m);
1175 	PC = FP->end;
1176 	return p;
1177 }
1178 
1179 static void*
evalpkg(void)1180 evalpkg(void)
1181 {
1182 	void **p, **x;
1183 	int n;
1184 
1185 	if((p = FP->ref) != nil){
1186 		x = FP->aux;
1187 		if(x >= p && x < (p+(SIZE(p)/sizeof(void*)))){
1188 			*x++ = FP->arg[0];
1189 			FP->aux = x;
1190 		}
1191 	}else {
1192 		n = ival(FP->arg[0]);
1193 		if(n < 0) n = 0;
1194 		p = mk('p', n*sizeof(void*));
1195 		FP->aux = p;
1196 		FP->ref = p;
1197 	}
1198 	return p;
1199 }
1200 
1201 static void*
evalname(void)1202 evalname(void)
1203 {
1204 	Name *n;
1205 
1206 	if(n = FP->arg[0])
1207 		n->v = FP->arg[1];
1208 	else
1209 		PC = FP->end;
1210 	return nil;
1211 }
1212 
1213 static void*
evalscope(void)1214 evalscope(void)
1215 {
1216 	Name *n;
1217 
1218 	if(n = FP->arg[0])
1219 		FP->dot = n;
1220 	else
1221 		PC = FP->end;
1222 	FP->op = nil;
1223 	return nil;
1224 }
1225 
1226 static void*
evalalias(void)1227 evalalias(void)
1228 {
1229 	Name *n;
1230 
1231 	if(n = FP->arg[1])
1232 		n->v = deref(FP->arg[0]);
1233 	return nil;
1234 }
1235 
1236 static void*
evalmet(void)1237 evalmet(void)
1238 {
1239 	Name *n;
1240 	Method *m;
1241 
1242 	if((n = FP->arg[0]) != nil){
1243 		m = mk('m', sizeof(Method));
1244 		m->narg = ival(FP->arg[1]) & 7;
1245 		m->start = PC;
1246 		m->end = FP->end;
1247 		m->name = n;
1248 		n->v = m;
1249 	}
1250 	PC = FP->end;
1251 	return nil;
1252 }
1253 
1254 static void*
evalreg(void)1255 evalreg(void)
1256 {
1257 	Name *n;
1258 	Region *r;
1259 
1260 	if((n = FP->arg[0]) != nil){
1261 		r = mk('r', sizeof(Region));
1262 		r->space = ival(FP->arg[1]);
1263 		r->off = ival(FP->arg[2]);
1264 		r->len = ival(FP->arg[3]);
1265 		r->name = n;
1266 		r->va = nil;
1267 		n->v = r;
1268 	}
1269 	return nil;
1270 }
1271 
1272 static void*
evalcfield(void)1273 evalcfield(void)
1274 {
1275 	void *r;
1276 	Field *f;
1277 	Name *n;
1278 	int c;
1279 
1280 	r = FP->arg[0];
1281 	if(r == nil || (TAG(r) != 'b' && TAG(r) != 'r'))
1282 		return nil;
1283 	c = FP->op - optab;
1284 	if(c == Ocfld)
1285 		n = FP->arg[3];
1286 	else
1287 		n = FP->arg[2];
1288 	if(n == nil || TAG(n) != 'N')
1289 		return nil;
1290 	if(TAG(r) == 'b')
1291 		f = mk('u', sizeof(Field));
1292 	else
1293 		f = mk('f', sizeof(Field));
1294 	switch(c){
1295 	case Ocfld:
1296 		f->bitoff = ival(FP->arg[1]);
1297 		f->bitlen = ival(FP->arg[2]);
1298 		break;
1299 	case Ocfld0:
1300 		f->bitoff = ival(FP->arg[1]);
1301 		f->bitlen = 1;
1302 		break;
1303 	case Ocfld1:
1304 	case Ocfld2:
1305 	case Ocfld4:
1306 	case Ocfld8:
1307 		f->bitoff = 8*ival(FP->arg[1]);
1308 		f->bitlen = 8*(c - Ocfld0);
1309 		break;
1310 	}
1311 	f->reg = r;
1312 	n->v = f;
1313 	return nil;
1314 }
1315 
1316 static void*
evalfield(void)1317 evalfield(void)
1318 {
1319 	int flags, bitoff, wa, n;
1320 	Field *f, *df;
1321 	Name *d;
1322 	uchar *p;
1323 
1324 	df = nil;
1325 	flags = 0;
1326 	bitoff = 0;
1327 	switch(FP->op - optab){
1328 	case Ofld:
1329 		flags = ival(FP->arg[1]);
1330 		break;
1331 	case Oxfld:
1332 		df = deref(FP->arg[1]);
1333 		if(df == nil || TAG(df) != 'f')
1334 			goto Out;
1335 		flags = ival(FP->arg[2]);
1336 		break;
1337 	}
1338 	p = PC;
1339 	if(p >= FP->end)
1340 		return nil;
1341 	while(p < FP->end){
1342 		if(*p == 0x00){
1343 			p++;
1344 			if((n = pkglen(p, FP->end, &p)) < 0)
1345 				break;
1346 			bitoff += n;
1347 			continue;
1348 		}
1349 		if(*p == 0x01){
1350 			p++;
1351 			flags = *p;
1352 			p += 2;
1353 			continue;
1354 		}
1355 		if(p+4 >= FP->end)
1356 			break;
1357 		if((d = getseg(FP->dot, p, 1)) == nil)
1358 			break;
1359 		if((n = pkglen(p+4, FP->end, &p)) < 0)
1360 			break;
1361 		f = mk('f', sizeof(Field));
1362 		f->flags = flags;
1363 		f->bitlen = n;
1364 		switch(FP->op - optab){
1365 		case Ofld:
1366 			f->reg = FP->arg[0];
1367 			f->bitoff = bitoff;
1368 			break;
1369 		case Oxfld:
1370 			wa = fieldalign(df->flags);
1371 			f->reg = df->reg;
1372 			f->bitoff = df->bitoff + (bitoff % (wa*8));
1373 			f->indexv = mki((bitoff/(wa*8))*wa);
1374 			f->index = FP->arg[0];
1375 			break;
1376 		}
1377 		bitoff += n;
1378 		d->v = f;
1379 	}
1380 Out:
1381 	PC = FP->end;
1382 	return nil;
1383 }
1384 
1385 static void*
evalnop(void)1386 evalnop(void)
1387 {
1388 	return nil;
1389 }
1390 
1391 static void*
evalbad(void)1392 evalbad(void)
1393 {
1394 	int i;
1395 
1396 	print("aml: bad opcode %p: ", PC);
1397 	for(i=0; i < 8 && (FP->start+i) < FP->end; i++){
1398 		if(i > 0)
1399 			print(" ");
1400 		print("%.2X", FP->start[i]);
1401 	}
1402 	if((FP->start+i) < FP->end)
1403 		print("...");
1404 	print("\n");
1405 	PC = FP->end;
1406 	return nil;
1407 }
1408 
1409 static void*
evalcond(void)1410 evalcond(void)
1411 {
1412 	switch(FP->op - optab){
1413 	case Oif:
1414 		if(FP <= FB)
1415 			break;
1416 		FP[-1].cond = ival(FP->arg[0]) != 0;
1417 		if(!FP[-1].cond)
1418 			PC = FP->end;
1419 		break;
1420 	case Oelse:
1421 		if(FP <= FB)
1422 			break;
1423 		if(FP[-1].cond)
1424 			PC = FP->end;
1425 		break;
1426 	case Owhile:
1427 		if(FP->aux){
1428 			if(PC >= FP->end){
1429 				PC = FP->start;
1430 				FP->aux = nil;
1431 			}
1432 			return nil;
1433 		}
1434 		FP->aux = FP->end;
1435 		if(ival(FP->arg[0]) == 0){
1436 			PC = FP->end;
1437 			break;
1438 		}
1439 		return nil;
1440 	}
1441 	FP->op = nil;
1442 	return nil;
1443 }
1444 
1445 static void*
evalcmp(void)1446 evalcmp(void)
1447 {
1448 	void *a, *b;
1449 	int tag, c;
1450 
1451 	a = FP->arg[0];
1452 	b = FP->arg[1];
1453 	if(a == nil || TAG(a) == 'i'){
1454 		c = ival(a) - ival(b);
1455 	} else {
1456 		tag = TAG(a);
1457 		if(b == nil || TAG(b) != tag)
1458 			b = copy(tag, b);
1459 		if(TAG(b) != tag)
1460 			return nil;	/* botch */
1461 		switch(tag){
1462 		default:
1463 			return nil;	/* botch */
1464 		case 's':
1465 			c = strcmp((char*)a, (char*)b);
1466 			break;
1467 		case 'b':
1468 			if((c = SIZE(a) - SIZE(b)) == 0)
1469 				c = memcmp(a, b, SIZE(a));
1470 			break;
1471 		}
1472 	}
1473 
1474 	switch(FP->op - optab){
1475 	case Oleq:
1476 		if(c == 0) return mki(1);
1477 		break;
1478 	case Olgt:
1479 		if(c > 0) return mki(1);
1480 		break;
1481 	case Ollt:
1482 		if(c < 0) return mki(1);
1483 		break;
1484 	}
1485 	return nil;
1486 }
1487 
1488 static void*
evalcall(void)1489 evalcall(void)
1490 {
1491 	Method *m;
1492 	Env *e;
1493 	int i;
1494 
1495 	if(FP->aux){
1496 		if(PC >= FP->end){
1497 			PC = FP->aux;
1498 			FP->end = PC;
1499 		}
1500 		return nil;
1501 	}
1502 	m = FP->ref;
1503 	e = mk('E', sizeof(Env));
1504 	for(i=0; i<FP->narg; i++)
1505 		e->arg[i] = deref(FP->arg[i]);
1506 	FP->env = e;
1507 	FP->narg = 0;
1508 	FP->dot = m->name;
1509 	if(m->eval != nil){
1510 		FP->op = nil;
1511 		FP->end = PC;
1512 		return (*m->eval)();
1513 	}
1514 	FP->dot = forkname(FP->dot);
1515 	FP->aux = PC;
1516 	FP->start = m->start;
1517 	FP->end = m->end;
1518 	PC = FP->start;
1519 	return nil;
1520 }
1521 
1522 static void*
evalret(void)1523 evalret(void)
1524 {
1525 	void *r = FP->arg[0];
1526 	int brk = (FP->op - optab) != Oret;
1527 	while(--FP >= FB){
1528 		switch(FP->op - optab){
1529 		case Owhile:
1530 			if(!brk)
1531 				continue;
1532 			PC = FP->end;
1533 			return nil;
1534 		case Ocall:
1535 			PC = FP->aux;
1536 			return r;
1537 		}
1538 	}
1539 	FP = FB;
1540 	PC = FB->end;
1541 	return r;
1542 }
1543 
1544 static void*
evalenv(void)1545 evalenv(void)
1546 {
1547 	Ref *r;
1548 	Env *e;
1549 	int c;
1550 
1551 	if((e = FP->env) == nil)
1552 		return nil;
1553 	c = FP->start[0];
1554 	if(c >= 0x60 && c <= 0x67){
1555 		r = mk('L', sizeof(Ref));
1556 		r->ptr = &e->loc[c - 0x60];
1557 	} else if(c >= 0x68 && c <= 0x6E){
1558 		r = mk('A', sizeof(Ref));
1559 		r->ptr = &e->arg[c - 0x68];
1560 	} else
1561 		return nil;
1562 	r->ref = e;
1563 	return r;
1564 }
1565 
1566 static void*
evalstore(void)1567 evalstore(void)
1568 {
1569 	return store(FP->arg[0], FP->arg[1]);
1570 }
1571 
1572 static void*
evalcat(void)1573 evalcat(void)
1574 {
1575 	void *r, *a, *b;
1576 	int tag, n, m;
1577 
1578 	a = FP->arg[0];
1579 	b = FP->arg[1];
1580 	if(a == nil || TAG(a) == 'i')
1581 		a = copy('b', a);	/* Concat(Int, ???) -> Buf */
1582 	tag = TAG(a);
1583 	if(b == nil || TAG(b) != tag)
1584 		b = copy(tag, b);
1585 	if(TAG(b) != tag)
1586 		return nil;	/* botch */
1587 	switch(tag){
1588 	default:
1589 		return nil;	/* botch */
1590 	case 'b':
1591 		n = SIZE(a);
1592 		m = SIZE(b);
1593 		r = mk('b', n + m);
1594 		memmove(r, a, n);
1595 		memmove((uchar*)r + n, b, m);
1596 		break;
1597 	case 's':
1598 		n = strlen((char*)a);
1599 		m = strlen((char*)b);
1600 		r = mk('s', n + m + 1);
1601 		memmove(r, a, n);
1602 		memmove((char*)r + n, b, m);
1603 		((char*)r)[n+m] = 0;
1604 		break;
1605 	}
1606 	store(r, FP->arg[2]);
1607 	return r;
1608 }
1609 
1610 static void*
evalindex(void)1611 evalindex(void)
1612 {
1613 	Field *f;
1614 	void *p;
1615 	Ref *r;
1616 	int x;
1617 
1618 	x = ival(FP->arg[1]);
1619 	if(p = deref(FP->arg[0])) switch(TAG(p)){
1620 	case 's':
1621 		if(x >= strlen((char*)p))
1622 			break;
1623 		/* no break */
1624 	case 'b':
1625 		if(x < 0 || x >= SIZE(p))
1626 			break;
1627 		f = mk('u', sizeof(Field));
1628 		f->reg = p;
1629 		f->bitlen = 8;
1630 		f->bitoff = 8*x;
1631 		store(f, FP->arg[2]);
1632 		return f;
1633 	case 'p':
1634 		if(x < 0 || x >= (SIZE(p)/sizeof(void*)))
1635 			break;
1636 		if(TAG(FP->arg[0]) == 'A' || TAG(FP->arg[0]) == 'L')
1637 			r = mk(TAG(FP->arg[0]), sizeof(Ref));
1638 		else
1639 			r = mk('R', sizeof(Ref));
1640 		r->ref = p;
1641 		r->ptr = ((void**)p) + x;
1642 		store(r, FP->arg[2]);
1643 		return r;
1644 	}
1645 	return nil;
1646 }
1647 
1648 static void*
evalcondref(void)1649 evalcondref(void)
1650 {
1651 	void *s;
1652 	if((s = FP->arg[0]) == nil)
1653 		return nil;
1654 	store(s, FP->arg[1]);
1655 	return mki(1);
1656 }
1657 
1658 static void*
evalsize(void)1659 evalsize(void)
1660 {
1661 	return mki(amllen(FP->arg[0]));
1662 }
1663 
1664 static void*
evalderef(void)1665 evalderef(void)
1666 {
1667 	void *p;
1668 
1669 	if(p = FP->arg[0]){
1670 		if(TAG(p) == 's' || TAG(p) == 'n')
1671 			p = getname(FP->dot, (char*)p, 0);
1672 		p = deref(p);
1673 	}
1674 	return p;
1675 }
1676 
1677 static void*
evalarith(void)1678 evalarith(void)
1679 {
1680 	uvlong v, d;
1681 	void *r;
1682 	int i;
1683 
1684 	r = nil;
1685 	switch(FP->op - optab){
1686 	case Oadd:
1687 		r = mki(ival(FP->arg[0]) + ival(FP->arg[1]));
1688 		break;
1689 	case Osub:
1690 		r = mki(ival(FP->arg[0]) - ival(FP->arg[1]));
1691 		break;
1692 	case Omul:
1693 		r = mki(ival(FP->arg[0]) * ival(FP->arg[1]));
1694 		break;
1695 	case Omod:
1696 	case Odiv:
1697 		v = ival(FP->arg[0]);
1698 		d = ival(FP->arg[1]);
1699 		if(d == 0){
1700 			print("aml: division by zero: PC=%#p\n", PC);
1701 			return nil;
1702 		}
1703 		r = mki(v % d);
1704 		store(r, FP->arg[2]);
1705 		if((FP->op - optab) != Odiv)
1706 			return r;
1707 		r = mki(v / d);
1708 		store(r, FP->arg[3]);
1709 		return r;
1710 	case Oshl:
1711 		r = mki(ival(FP->arg[0]) << ival(FP->arg[1]));
1712 		break;
1713 	case Oshr:
1714 		r = mki(ival(FP->arg[0]) >> ival(FP->arg[1]));
1715 		break;
1716 	case Oand:
1717 		r = mki(ival(FP->arg[0]) & ival(FP->arg[1]));
1718 		break;
1719 	case Onand:
1720 		r = mki(~(ival(FP->arg[0]) & ival(FP->arg[1])));
1721 		break;
1722 	case Oor:
1723 		r = mki(ival(FP->arg[0]) | ival(FP->arg[1]));
1724 		break;
1725 	case Onor:
1726 		r = mki(~(ival(FP->arg[0]) | ival(FP->arg[1])));
1727 		break;
1728 	case Oxor:
1729 		r = mki(ival(FP->arg[0]) ^ ival(FP->arg[1]));
1730 		break;
1731 	case Onot:
1732 		r = mki(~ival(FP->arg[0]));
1733 		store(r, FP->arg[1]);
1734 		return r;
1735 	case Olbit:
1736 		v = ival(FP->arg[0]);
1737 		if(v == 0)
1738 			break;
1739 		for(i=0; (v & 1) == 0; i++)
1740 			v >>= 1;
1741 		r = mki(i+1);
1742 		break;
1743 	case Orbit:
1744 		v = ival(FP->arg[0]);
1745 		if(v == 0)
1746 			break;
1747 		for(i=0; v != 0; i++)
1748 			v >>= 1;
1749 		r = mki(i);
1750 		break;
1751 	case Oland:
1752 		return mki(ival(FP->arg[0]) && ival(FP->arg[1]));
1753 	case Olor:
1754 		return mki(ival(FP->arg[0]) || ival(FP->arg[1]));
1755 	case Olnot:
1756 		return mki(ival(FP->arg[0]) == 0);
1757 
1758 	case Oinc:
1759 		r = mki(ival(deref(FP->arg[0]))+1);
1760 		store(r, FP->arg[0]);
1761 		return r;
1762 	case Odec:
1763 		r = mki(ival(deref(FP->arg[0]))-1);
1764 		store(r, FP->arg[0]);
1765 		return r;
1766 	}
1767 
1768 	store(r, FP->arg[2]);
1769 	return r;
1770 }
1771 
1772 static void*
evalload(void)1773 evalload(void)
1774 {
1775 	enum { LenOffset = 4, HdrLen = 36 };
1776 	uvlong *tid;
1777 	Region *r;
1778 	int l;
1779 
1780 	tid = nil;
1781 	if(FP->aux){
1782 		if(PC >= FP->end){
1783 			amlenum(amlroot, nil, fixnames, nil);
1784 			FP->aux = nil;
1785 			FP->end = PC;
1786 			tid = mki(1);	/* fake */
1787 		}
1788 	} else {
1789 		store(nil, FP->arg[1]);
1790 		if(FP->arg[0] == nil)
1791 			return nil;
1792 
1793 		l = rwreg(FP->arg[0], LenOffset, 4, 0, 0);
1794 		if(l <= HdrLen)
1795 			return nil;
1796 
1797 		FP->aux = PC;	/* save */
1798 		FP->ref = FP->arg[0];
1799 		switch(TAG(FP->ref)){
1800 		case 'b':
1801 			if(SIZE(FP->ref) < l)
1802 				return nil;
1803 			PC = (uchar*)FP->ref + HdrLen;
1804 			break;
1805 		case 'r':
1806 			r = FP->ref;
1807 			if(r->len < l || r->va == nil || r->mapped <= 0)
1808 				return nil;
1809 			PC = (uchar*)r->va + HdrLen;
1810 			break;
1811 		default:
1812 			return nil;
1813 		}
1814 		FP->end = PC + (l - HdrLen);
1815 		FP->dot = amlroot;
1816 		FP->env = nil;
1817 
1818 		tid = mki(1); /* fake */
1819 		store(tid, FP->arg[1]);
1820 	}
1821 	return tid;
1822 }
1823 
1824 static void*
evalstall(void)1825 evalstall(void)
1826 {
1827 	amldelay(ival(FP->arg[0]));
1828 	return nil;
1829 }
1830 
1831 static void*
evalsleep(void)1832 evalsleep(void)
1833 {
1834 	amldelay(ival(FP->arg[0])*1000);
1835 	return nil;
1836 }
1837 
1838 static Op optab[] = {
1839 	[Obad]		"",			"",		evalbad,
1840 	[Onop]		"Noop",			"",		evalnop,
1841 	[Odebug]	"Debug",		"",		evalnop,
1842 
1843 	[Ostr]		".str",			"s",		evaliarg0,
1844 	[Obyte]		".byte",		"1",		evaliarg0,
1845 	[Oword]		".word",		"2",		evaliarg0,
1846 	[Odword]	".dword",		"4",		evaliarg0,
1847 	[Oqword]	".qword",		"8",		evaliarg0,
1848 	[Oconst]	".const",		"",		evalconst,
1849 	[Onamec]	".name",		"",		evalnamec,
1850 	[Oenv]		".env",			"",		evalenv,
1851 
1852 	[Oname]		"Name",			"N*",		evalname,
1853 	[Oscope]	"Scope",		"{n}",		evalscope,
1854 	[Oalias]	"Alias",		"nN",		evalalias,
1855 
1856 	[Odev]		"Device",		"{N}",		evalscope,
1857 	[Ocpu]		"Processor",		"{N141}",	evalscope,
1858 	[Othz]		"ThermalZone",		"{N}",		evalscope,
1859 	[Oprc]		"PowerResource",	"{N12}",	evalscope,
1860 
1861 	[Oreg]		"OperationRegion",	"N1ii",		evalreg,
1862 	[Ofld]		"Field",		"{n1",		evalfield,
1863 	[Oxfld]		"IndexField",		"{nn1",		evalfield,
1864 
1865 	[Ocfld]		"CreateField",		"*iiN",		evalcfield,
1866 	[Ocfld0]	"CreateBitField",	"*iN",		evalcfield,
1867 	[Ocfld1]	"CreateByteField",	"*iN",		evalcfield,
1868 	[Ocfld2]	"CreateWordField",	"*iN",		evalcfield,
1869 	[Ocfld4]	"CreateDWordField",	"*iN",		evalcfield,
1870 	[Ocfld8]	"CreateQWordField",	"*iN",		evalcfield,
1871 
1872 	[Opkg]		"Package",		"{1}",		evalpkg,
1873 	[Ovpkg]		"VarPackage",		"{i}",		evalpkg,
1874 	[Obuf]		"Buffer",		"{i",		evalbuf,
1875 	[Omet]		"Method",		"{N1",		evalmet,
1876 
1877 	[Oadd]		"Add",			"ii@",		evalarith,
1878 	[Osub]		"Subtract",		"ii@",		evalarith,
1879 	[Omod]		"Mod",			"ii@",		evalarith,
1880 	[Omul]		"Multiply",		"ii@",		evalarith,
1881 	[Odiv]		"Divide",		"ii@@",		evalarith,
1882 	[Oshl]		"ShiftLef",		"ii@",		evalarith,
1883 	[Oshr]		"ShiftRight",		"ii@",		evalarith,
1884 	[Oand]		"And",			"ii@",		evalarith,
1885 	[Onand]		"Nand",			"ii@",		evalarith,
1886 	[Oor]		"Or",			"ii@",		evalarith,
1887 	[Onor]		"Nor",			"ii@",		evalarith,
1888 	[Oxor]		"Xor",			"ii@",		evalarith,
1889 	[Onot]		"Not",			"i@",		evalarith,
1890 
1891 	[Olbit]		"FindSetLeftBit",	"i@",		evalarith,
1892 	[Orbit]		"FindSetRightBit",	"i@",		evalarith,
1893 
1894 	[Oinc]		"Increment",		"@",		evalarith,
1895 	[Odec]		"Decrement",		"@",		evalarith,
1896 
1897 	[Oland]		"LAnd",			"ii",		evalarith,
1898 	[Olor]		"LOr",			"ii",		evalarith,
1899 	[Olnot]		"LNot",			"i",		evalarith,
1900 
1901 	[Oleq]		"LEqual",		"**",		evalcmp,
1902 	[Olgt]		"LGreater",		"**",		evalcmp,
1903 	[Ollt]		"LLess",		"**",		evalcmp,
1904 
1905 	[Omutex]	"Mutex",		"N1",		evalnop,
1906 	[Oevent]	"Event",		"N",		evalnop,
1907 
1908 	[Oif]		"If",			"{i}",		evalcond,
1909 	[Oelse]		"Else",			"{}",		evalcond,
1910 	[Owhile]	"While",		"{,i}",		evalcond,
1911 	[Obreak]	"Break",		"",		evalret,
1912 	[Oret]		"Return",		"*",		evalret,
1913 	[Ocall]		"Call",			"",		evalcall,
1914 
1915 	[Ostore]	"Store",		"*@",		evalstore,
1916 	[Oindex]	"Index",		"@i@",		evalindex,
1917 	[Osize]		"SizeOf",		"*",		evalsize,
1918 	[Oref]		"RefOf",		"@",		evaliarg0,
1919 	[Ocref]		"CondRefOf",		"@@",		evalcondref,
1920 	[Oderef]	"DerefOf",		"@",		evalderef,
1921 	[Ocat]		"Concatenate",		"**@",		evalcat,
1922 
1923 	[Oacq]		"Acquire",		"@2",		evalnop,
1924 	[Orel]		"Release",		"@",		evalnop,
1925 	[Ostall]	"Stall",		"i",		evalstall,
1926 	[Osleep]	"Sleep",		"i",		evalsleep,
1927 	[Oload] 	"Load", 		"*@}", 		evalload,
1928 	[Ounload]	"Unload",		"@",		evalnop,
1929 };
1930 
1931 static uchar octab1[] = {
1932 /* 00 */	Oconst,	Oconst,	Obad,	Obad,	Obad,	Obad,	Oalias,	Obad,
1933 /* 08 */	Oname,	Obad,	Obyte,	Oword,	Odword,	Ostr,	Oqword,	Obad,
1934 /* 10 */	Oscope,	Obuf,	Opkg,	Ovpkg,	Omet,	Obad,	Obad,	Obad,
1935 /* 18 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1936 /* 20 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1937 /* 28 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Onamec,	Onamec,
1938 /* 30 */	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,
1939 /* 38 */	Onamec,	Onamec,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1940 /* 40 */	Obad,	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,
1941 /* 48 */	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,
1942 /* 50 */	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,	Onamec,
1943 /* 58 */	Onamec,	Onamec,	Onamec,	Obad,	Onamec,	Obad,	Onamec,	Onamec,
1944 /* 60 */	Oenv,	Oenv,	Oenv,	Oenv,	Oenv,	Oenv,	Oenv,	Oenv,
1945 /* 68 */	Oenv,	Oenv,	Oenv,	Oenv,	Oenv,	Oenv,	Oenv,	Obad,
1946 /* 70 */	Ostore,	Oref,	Oadd,	Ocat,	Osub,	Oinc,	Odec,	Omul,
1947 /* 78 */	Odiv,	Oshl,	Oshr,	Oand,	Onand,	Oor,	Onor,	Oxor,
1948 /* 80 */	Onot,	Olbit,	Orbit,	Oderef,	Obad,	Omod,	Obad,	Osize,
1949 /* 88 */	Oindex,	Obad,	Ocfld4,	Ocfld2,	Ocfld1,	Ocfld0,	Obad,	Ocfld8,
1950 /* 90 */	Oland,	Olor,	Olnot,	Oleq,	Olgt,	Ollt,	Obad,	Obad,
1951 /* 98 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1952 /* A0 */	Oif,	Oelse,	Owhile,	Onop,	Oret,	Obreak,	Obad,	Obad,
1953 /* A8 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1954 /* B0 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1955 /* B8 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1956 /* C0 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1957 /* C8 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1958 /* D0 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1959 /* D8 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1960 /* E0 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1961 /* E8 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1962 /* F0 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1963 /* F8 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Oconst,
1964 };
1965 
1966 static uchar octab2[] = {
1967 /* 00 */	Obad,	Omutex,	Oevent,	Obad,	Obad,	Obad,	Obad,	Obad,
1968 /* 08 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1969 /* 10 */	Obad,	Obad,	Ocref,	Ocfld,	Obad,	Obad,	Obad,	Obad,
1970 /* 18 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1971 /* 20 */	Oload,	Ostall,	Osleep,	Oacq,	Obad,	Obad,	Obad,	Orel,
1972 /* 28 */	Obad,	Obad,	Ounload,Obad,	Obad,	Obad,	Obad,	Obad,
1973 /* 30 */	Obad,	Odebug,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1974 /* 38 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1975 /* 40 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1976 /* 48 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1977 /* 50 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1978 /* 58 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1979 /* 60 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1980 /* 68 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1981 /* 70 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1982 /* 78 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1983 /* 80 */	Oreg,	Ofld,	Odev,	Ocpu,	Oprc,	Othz,	Oxfld,	Obad,
1984 /* 88 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1985 /* 90 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1986 /* 98 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1987 /* A0 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1988 /* A8 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1989 /* B0 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1990 /* B8 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1991 /* C0 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1992 /* C8 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1993 /* D0 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1994 /* D8 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1995 /* E0 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1996 /* E8 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1997 /* F0 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1998 /* F8 */	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,	Obad,
1999 };
2000 
2001 int
amltag(void * p)2002 amltag(void *p)
2003 {
2004 	return p ? TAG(p) : 0;
2005 }
2006 
2007 void*
amlval(void * p)2008 amlval(void *p)
2009 {
2010 	return deref(p);
2011 }
2012 
2013 uvlong
amlint(void * p)2014 amlint(void *p)
2015 {
2016 	return ival(p);
2017 }
2018 
2019 int
amllen(void * p)2020 amllen(void *p)
2021 {
2022 	while(p){
2023 		switch(TAG(p)){
2024 		case 'R':
2025 			p = *((Ref*)p)->ptr;
2026 			continue;
2027 		case 'n':
2028 		case 's':
2029 			return strlen((char*)p);
2030 		case 'p':
2031 			return SIZE(p)/sizeof(void*);
2032 		default:
2033 			return SIZE(p);
2034 		}
2035 	}
2036 	return 0;
2037 }
2038 
2039 void*
amlnew(char tag,int len)2040 amlnew(char tag, int len)
2041 {
2042 	switch(tag){
2043 	case 'i':
2044 		return mki(0);
2045 	case 'n':
2046 	case 's':
2047 		return mk(tag, len + 1);
2048 	case 'p':
2049 		return mk(tag, len * sizeof(void*));
2050 	default:
2051 		return mk(tag, len);
2052 	}
2053 }
2054 
2055 static void*
evalosi(void)2056 evalosi(void)
2057 {
2058 	static char *w[] = {
2059 		"Windows 2001",
2060 		"Windows 2001 SP1",
2061 		"Windows 2001 SP2",
2062 		"Windows 2006",
2063 	};
2064 	char *s;
2065 	int i;
2066 
2067 	s = FP->env->arg[0];
2068 	if(s == nil || TAG(s) != 's')
2069 		return nil;
2070 	for(i = 0; i < nelem(w); i++)
2071 		if(strcmp(s, w[i]) == 0)
2072 			return mki(0xFFFFFFFF);
2073 	return nil;
2074 }
2075 
2076 void
amlinit(void)2077 amlinit(void)
2078 {
2079 	Name *n;
2080 
2081 	fmtinstall('V', Vfmt);
2082 	fmtinstall('N', Nfmt);
2083 
2084 	n = mk('N', sizeof(Name));
2085 	n->up = n;
2086 
2087 	amlroot = n;
2088 
2089 	getname(amlroot, "_GPE", 1);
2090 	getname(amlroot, "_PR", 1);
2091 	getname(amlroot, "_SB", 1);
2092 	getname(amlroot, "_TZ", 1);
2093 	getname(amlroot, "_SI", 1);
2094 	getname(amlroot, "_GL", 1);
2095 
2096 	if(n = getname(amlroot, "_REV", 1))
2097 		n->v = mki(2);
2098 	if(n = getname(amlroot, "_OS", 1))
2099 		n->v = mks("Microsoft Windows");
2100 	if(n = getname(amlroot, "_OSI", 1)){
2101 		Method *m;
2102 
2103 		m = mk('m', sizeof(Method));
2104 		m->narg = 1;
2105 		m->eval = evalosi;
2106 		m->name = n;
2107 		n->v = m;
2108 	}
2109 }
2110 
2111 void
amlexit(void)2112 amlexit(void)
2113 {
2114 	amlroot = nil;
2115 	FP = FB-1;
2116 	gc();
2117 }
2118 
2119 int
amlload(uchar * data,int len)2120 amlload(uchar *data, int len)
2121 {
2122 	int ret;
2123 
2124 	ret = xec(data, data+len, amlroot, nil, nil);
2125 	amlenum(amlroot, nil, fixnames, nil);
2126 	return ret;
2127 }
2128 
2129 void*
amlwalk(void * dot,char * name)2130 amlwalk(void *dot, char *name)
2131 {
2132 	return getname(dot, name, 0);
2133 }
2134 
2135 void
amlenum(void * dot,char * seg,int (* proc)(void *,void *),void * arg)2136 amlenum(void *dot, char *seg, int (*proc)(void *, void *), void *arg)
2137 {
2138 	Name *n, *d;
2139 	int rec;
2140 
2141 	d = dot;
2142 	if(d == nil || TAG(d) != 'N')
2143 		return;
2144 	do {
2145 		rec = 1;
2146 		if(seg == nil || memcmp(seg, d->seg, sizeof(d->seg)) == 0)
2147 			rec = (*proc)(d, arg) == 0;
2148 		for(n = d->down; n && rec; n = n->next)
2149 			amlenum(n, seg, proc, arg);
2150 		d = d->fork;
2151 	} while(d);
2152 }
2153 
2154 int
amleval(void * dot,char * fmt,...)2155 amleval(void *dot, char *fmt, ...)
2156 {
2157 	va_list a;
2158 	Method *m;
2159 	void **r;
2160 	Env *e;
2161 	int i;
2162 
2163 	va_start(a, fmt);
2164 	e = mk('E', sizeof(Env));
2165 	for(i=0;*fmt;fmt++){
2166 		switch(*fmt){
2167 		default:
2168 			return -1;
2169 		case 's':
2170 			e->arg[i++] = mks(va_arg(a, char*));
2171 			break;
2172 		case 'i':
2173 			e->arg[i++] = mki(va_arg(a, int));
2174 			break;
2175 		case 'I':
2176 			e->arg[i++] = mki(va_arg(a, uvlong));
2177 			break;
2178 		case 'b':
2179 		case 'p':
2180 		case '*':
2181 			e->arg[i++] = va_arg(a, void*);
2182 			break;
2183 		}
2184 	}
2185 	r = va_arg(a, void**);
2186 	va_end(a);
2187 	if(dot = deref(dot))
2188 	if(TAG(dot) == 'm'){
2189 		m = dot;
2190 		if(i != m->narg)
2191 			return -1;
2192 		if(m->eval == nil)
2193 			return xec(m->start, m->end, forkname(m->name), e, r);
2194 		FP = FB;
2195 		FP->op = nil;
2196 		FP->env = e;
2197 		FP->narg = 0;
2198 		FP->dot = m->name;
2199 		FP->ref = FP->aux = nil;
2200 		dot = (*m->eval)();
2201 	}
2202 	if(r != nil)
2203 		*r = dot;
2204 	return 0;
2205 }
2206 
2207 void
amltake(void * p)2208 amltake(void *p)
2209 {
2210 	if(p != nil)
2211 		D2H(p)->mark |= 2;
2212 }
2213 
2214 void
amldrop(void * p)2215 amldrop(void *p)
2216 {
2217 	if(p != nil)
2218 		D2H(p)->mark &= ~2;
2219 }
2220