]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libaml/aml.c
merge
[plan9front.git] / sys / src / libaml / aml.c
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*
159 rootname(Name *dot)
160 {
161         while(dot != dot->up)
162                 dot = dot->up;
163         return dot;
164 }
165
166 static void
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
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*
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*
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*
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
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*
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*
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*
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
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
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
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
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
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
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*
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*
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*
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*
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
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
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
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
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*
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*
1146 evaliarg0(void)
1147 {
1148         return FP->arg[0];
1149 }
1150
1151 static 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*
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*
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*
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*
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*
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*
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*
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*
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*
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*
1386 evalnop(void)
1387 {
1388         return nil;
1389 }
1390
1391 static 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*
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*
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*
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*
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*
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*
1567 evalstore(void)
1568 {
1569         return store(FP->arg[0], FP->arg[1]);
1570 }
1571
1572 static 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*
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*
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*
1659 evalsize(void)
1660 {
1661         return mki(amllen(FP->arg[0]));
1662 }
1663
1664 static 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*
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*
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*
1825 evalstall(void)
1826 {
1827         amldelay(ival(FP->arg[0]));
1828         return nil;
1829 }
1830
1831 static 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
2002 amltag(void *p)
2003 {
2004         return p ? TAG(p) : 0;
2005 }
2006
2007 void*
2008 amlval(void *p)
2009 {
2010         return deref(p);
2011 }
2012
2013 uvlong
2014 amlint(void *p)
2015 {
2016         return ival(p);
2017 }
2018
2019 int
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*
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*
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
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
2112 amlexit(void)
2113 {
2114         amlroot = nil;
2115         FP = FB-1;
2116         gc();
2117 }
2118
2119 int
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*
2130 amlwalk(void *dot, char *name)
2131 {
2132         return getname(dot, name, 0);
2133 }
2134
2135 void
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
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
2208 amltake(void *p)
2209 {
2210         if(p != nil)
2211                 D2H(p)->mark |= 2;
2212 }
2213
2214 void
2215 amldrop(void *p)
2216 {
2217         if(p != nil)
2218                 D2H(p)->mark &= ~2;
2219 }