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