#include <u.h>#include <libc.h>#include <aml.h> typedef struct Interp Interp;typedef struct Frame Frame;typedef struct Heap Heap; typedef struct Package Package;typedef struct Method Method;typedef struct Region Region;typedef struct Field Field; typedef struct Name Name;typedef struct Ref Ref;typedef struct Env Env;typedef struct Op Op; struct Heap { Heap *link; short size; uchar mark; char tag;}; #define H2D(h) (((Heap*)(h))+1)#define D2H(d) (((Heap*)(d))-1)#define TAG(d) D2H(d)->tag#define SIZE(d) D2H(d)->size enum { MemSpace = 0x00, IoSpace = 0x01, PcicfgSpace = 0x02, EbctlSpace = 0x03, SmbusSpace = 0x04, CmosSpace = 0x05, PcibarSpace = 0x06, IpmiSpace = 0x07,}; static char *spacename[] = { "Mem", "Io", "Pcicfg", "Ebctl", "Smbus", "Cmos", "Pcibar", "Ipmi"}; /* field flags */enum { AnyAcc = 0x00, ByteAcc = 0x01, WordAcc = 0x02, DWordAcc = 0x03, QWordAcc = 0x04, BufferAcc = 0x05, AccMask = 0x07, NoLock = 0x10, Preserve = 0x00, WriteAsOnes = 0x20, WriteAsZeros = 0x40, UpdateMask = 0x60,}; struct Package { int n; void *a[];}; struct Method { Name *name; int narg; void* (*eval)(void); uchar *start; uchar *end;}; struct Region { Name *name; int space; uvlong off; uvlong len; uchar *va;}; struct Field { void *reg; /* Buffer or Region */ Field *index; void *indexv; int flags; int bitoff; int bitlen;}; struct Name { void *v; Name *up; Name *next; Name *fork; Name *down; char seg[4];}; struct Ref { void *ref; void **ptr;}; struct Env { void *loc[8]; void *arg[8];}; struct Op { char *name; char *sequence; void* (*eval)(void);}; struct Frame { int tag; char *phase; uchar *start; uchar *end; Op *op; Env *env; Name *dot; void *ref; void *aux; int narg; void *arg[8];}; struct Interp { uchar *pc; Frame *fp; int cond;}; static Interp interp;static Frame stack[32]; void* amlroot; int amldebug; #define PC interp.pc#define FP interp.fp#define FB stack#define FT &stack[nelem(stack)] static Heap *hp; enum { Obad, Onop, Odebug, Ostr, Obyte, Oword, Odword, Oqword, Oconst, Onamec, Oname, Oscope, Oalias, Oreg, Ofld, Oxfld, Opkg, Ovpkg, Oenv, Obuf, Omet, Odev, Ocpu, Othz, Oprc, Oadd, Osub, Omod, Omul, Odiv, Oshl, Oshr, Oand, Onand, Oor, Onor, Oxor, Onot, Oinc, Odec, Oland, Olor, Olnot, Oleq, Olgt, Ollt, Oindex, Omutex, Oevent, Ocfld, Ocfld0, Ocfld1, Ocfld2, Ocfld4, Ocfld8, Oif, Oelse, Owhile, Obreak, Oret, Ocall, Ostore, Oderef, Osize, Oref, Ocref, Oacq, Orel,}; static Op optab[];static uchar octab1[];static uchar octab2[]; static Name*rootname(Name *dot){ while(dot != dot->up) dot = dot->up; return dot;} static voidgcmark(void *p){ int i; Env *e; Field *f; Heap *h; Name *n, *d; Package *a; if(p == nil) return; h = D2H(p); if(h->mark) return; h->mark = 1; switch(h->tag){ case 'E': e = p; for(i=0; i<nelem(e->loc); i++) gcmark(e->loc[i]); for(i=0; i<nelem(e->arg); i++) gcmark(e->arg[i]); break; case 'R': case 'A': case 'L': gcmark(((Ref*)p)->ref); break; case 'N': n = p; gcmark(n->v); for(d = n->down; d; d = d->next) gcmark(d); gcmark(n->fork); gcmark(n->up); break; case 'p': a = p; for(i=0; i<a->n; i++) gcmark(a->a[i]); break; case 'r': gcmark(((Region*)p)->name); break; case 'm': gcmark(((Method*)p)->name); break; case 'f': case 'u': f = p; gcmark(f->reg); gcmark(f->index); gcmark(f->indexv); break; }} static intgc(void){ int i; Heap *h, **hh; Frame *f; for(h = hp; h; h = h->link) h->mark = 0; for(f = FP; f >= FB; f--){ for(i=0; i<f->narg; i++) gcmark(f->arg[i]); gcmark(f->env); gcmark(f->dot); gcmark(f->ref); } gcmark(amlroot); i = 0; hh = &hp; while(h = *hh){ if(h->mark){ hh = &h->link; continue; } *hh = h->link; memset(h, ~0, sizeof(Heap)+h->size); amlfree(h); i++; } return i;} static void*mk(int tag, int size){ Heap *h; int a; a = sizeof(Heap) + size; h = amlalloc(a); h->size = size; h->tag = tag; h->link = hp; hp = h; return h+1;} static uvlong*mki(uvlong i){ uvlong *v; v = mk('i', sizeof(uvlong)); *v = i; return v;} static char*mks(char *s){ char *r = mk('s', strlen(s)+1); strcpy(r, s); return r;} static intpkglen(uchar *p, uchar *e, uchar **np){ ulong n; uchar b; if(p >= e) return -1; b = *p++; if(b <= 0x3F) n = b; else { n = b & 0xF; if(p >= e) return -1; n += *p++ << 4; if(b >= 0x80){ if(p >= e) return -1; n += *p++ << 12; } if(b >= 0xC0){ if(p >= e) return -1; n += *p++ << 20; } } if(np) *np = p; return n;} static Name*forkname(Name *dot){ Name *n; n = mk('N', sizeof(Name)); *n = *dot; n->fork = dot; n->next = n->down = nil; if(dot->v == dot) n->v = n; if(dot->up == dot) n->up = n; else { if(n->up = forkname(dot->up)) n->up->down = n; } return n;} static Name*getseg(Name *dot, void *seg, int new){ Name *n, *l; for(n = l = nil; dot; dot = dot->fork){ for(n = dot->down; n; n = n->next){ if(memcmp(seg, n->seg, 4) == 0) return n; l = n; } if(new){ n = mk('N', sizeof(Name)); memmove(n->seg, seg, sizeof(n->seg)); n->up = dot; if(l == nil) dot->down = n; else l->next = n; n->v = n; break; } } return n;} Name*getname(Name *dot, char *path, int new){ char seg[4]; int i, s; Name *x; s = !new; if(*path == '\\'){ path++; dot = rootname(dot); s = 0; } while(*path == '^'){ path++; dot = dot->up; s = 0; } do { for(i=0; i<4; i++){ if(*path == 0 || *path == '.') break; seg[i] = *path++; } if(i == 0) break; while(i < 4) seg[i++] = '_'; if(s && *path == 0){ for(;;){ if(x = getseg(dot, seg, 0)) break; if(dot == dot->up) break; dot = dot->up; } return x; } s = 0; dot = getseg(dot, seg, new); } while(*path++ == '.'); return dot;} static uvlongival(void *p){ if(p) switch(TAG(p)){ case 'i': return *((uvlong*)p); case 's': return strtoull((char*)p, 0, 0); } return 0;} static uvlongrwreg(void *reg, int off, int len, uvlong v, int write){ Region *r; uchar *p; int i; switch(TAG(reg)){ case 'b': p = reg; if((off+len) > SIZE(p)) break; if(write){ /* putle(p, v, 8); */ for(i=0; i<len; i++){ p[off+i] = v & 0xFF; v >>= 8; } } else { /* v |= getle(p, 8); */ for(i=0; i<len; i++) v |= ((u64int)p[off+i]) << i*8; } return v; case 'r': r = reg; if((off+len) > r->len) break; if(amldebug){ print("rwreg: %s %-8s [%llux+%x]/%d %llux\n", write ? "W" : "R", spacename[r->space], r->off, off, len, v); } break; } return ~0;} static void *deref(void *p);static void *store(void *s, void *d); static intfieldalign(int flags){ switch(flags & AccMask){ default: case AnyAcc: case ByteAcc: case BufferAcc:Lines 1–500 of 1885. Load more
#include <u.h> #include <libc.h> #include <aml.h> typedef struct Interp Interp; typedef struct Frame Frame; typedef struct Heap Heap; typedef struct Package Package; typedef struct Method Method; typedef struct Region Region; typedef struct Field Field; typedef struct Name Name; typedef struct Ref Ref; typedef struct Env Env; typedef struct Op Op; struct Heap { Heap *link; short size; uchar mark; char tag; }; #define H2D(h) (((Heap*)(h))+1) #define D2H(d) (((Heap*)(d))-1) #define TAG(d) D2H(d)->tag #define SIZE(d) D2H(d)->size enum { MemSpace = 0x00, IoSpace = 0x01, PcicfgSpace = 0x02, EbctlSpace = 0x03, SmbusSpace = 0x04, CmosSpace = 0x05, PcibarSpace = 0x06, IpmiSpace = 0x07, }; static char *spacename[] = { "Mem", "Io", "Pcicfg", "Ebctl", "Smbus", "Cmos", "Pcibar", "Ipmi" }; /* field flags */ enum { AnyAcc = 0x00, ByteAcc = 0x01, WordAcc = 0x02, DWordAcc = 0x03, QWordAcc = 0x04, BufferAcc = 0x05, AccMask = 0x07, NoLock = 0x10, Preserve = 0x00, WriteAsOnes = 0x20, WriteAsZeros = 0x40, UpdateMask = 0x60, }; struct Package { int n; void *a[]; }; struct Method { Name *name; int narg; void* (*eval)(void); uchar *start; uchar *end; }; struct Region { Name *name; int space; uvlong off; uvlong len; uchar *va; }; struct Field { void *reg; /* Buffer or Region */ Field *index; void *indexv; int flags; int bitoff; int bitlen; }; struct Name { void *v; Name *up; Name *next; Name *fork; Name *down; char seg[4]; }; struct Ref { void *ref; void **ptr; }; struct Env { void *loc[8]; void *arg[8]; }; struct Op { char *name; char *sequence; void* (*eval)(void); }; struct Frame { int tag; char *phase; uchar *start; uchar *end; Op *op; Env *env; Name *dot; void *ref; void *aux; int narg; void *arg[8]; }; struct Interp { uchar *pc; Frame *fp; int cond; }; static Interp interp; static Frame stack[32]; void* amlroot; int amldebug; #define PC interp.pc #define FP interp.fp #define FB stack #define FT &stack[nelem(stack)] static Heap *hp; enum { Obad, Onop, Odebug, Ostr, Obyte, Oword, Odword, Oqword, Oconst, Onamec, Oname, Oscope, Oalias, Oreg, Ofld, Oxfld, Opkg, Ovpkg, Oenv, Obuf, Omet, Odev, Ocpu, Othz, Oprc, Oadd, Osub, Omod, Omul, Odiv, Oshl, Oshr, Oand, Onand, Oor, Onor, Oxor, Onot, Oinc, Odec, Oland, Olor, Olnot, Oleq, Olgt, Ollt, Oindex, Omutex, Oevent, Ocfld, Ocfld0, Ocfld1, Ocfld2, Ocfld4, Ocfld8, Oif, Oelse, Owhile, Obreak, Oret, Ocall, Ostore, Oderef, Osize, Oref, Ocref, Oacq, Orel, }; static Op optab[]; static uchar octab1[]; static uchar octab2[]; static Name* rootname(Name *dot){ while(dot != dot->up) dot = dot->up; return dot; } static void gcmark(void *p) { int i; Env *e; Field *f; Heap *h; Name *n, *d; Package *a; if(p == nil) return; h = D2H(p); if(h->mark) return; h->mark = 1; switch(h->tag){ case 'E': e = p; for(i=0; i<nelem(e->loc); i++) gcmark(e->loc[i]); for(i=0; i<nelem(e->arg); i++) gcmark(e->arg[i]); break; case 'R': case 'A': case 'L': gcmark(((Ref*)p)->ref); break; case 'N': n = p; gcmark(n->v); for(d = n->down; d; d = d->next) gcmark(d); gcmark(n->fork); gcmark(n->up); break; case 'p': a = p; for(i=0; i<a->n; i++) gcmark(a->a[i]); break; case 'r': gcmark(((Region*)p)->name); break; case 'm': gcmark(((Method*)p)->name); break; case 'f': case 'u': f = p; gcmark(f->reg); gcmark(f->index); gcmark(f->indexv); break; } } static int gc(void) { int i; Heap *h, **hh; Frame *f; for(h = hp; h; h = h->link) h->mark = 0; for(f = FP; f >= FB; f--){ for(i=0; i<f->narg; i++) gcmark(f->arg[i]); gcmark(f->env); gcmark(f->dot); gcmark(f->ref); } gcmark(amlroot); i = 0; hh = &hp; while(h = *hh){ if(h->mark){ hh = &h->link; continue; } *hh = h->link; memset(h, ~0, sizeof(Heap)+h->size); amlfree(h); i++; } return i; } static void* mk(int tag, int size) { Heap *h; int a; a = sizeof(Heap) + size; h = amlalloc(a); h->size = size; h->tag = tag; h->link = hp; hp = h; return h+1; } static uvlong* mki(uvlong i) { uvlong *v; v = mk('i', sizeof(uvlong)); *v = i; return v; } static char* mks(char *s) { char *r = mk('s', strlen(s)+1); strcpy(r, s); return r; } static int pkglen(uchar *p, uchar *e, uchar **np) { ulong n; uchar b; if(p >= e) return -1; b = *p++; if(b <= 0x3F) n = b; else { n = b & 0xF; if(p >= e) return -1; n += *p++ << 4; if(b >= 0x80){ if(p >= e) return -1; n += *p++ << 12; } if(b >= 0xC0){ if(p >= e) return -1; n += *p++ << 20; } } if(np) *np = p; return n; } static Name* forkname(Name *dot) { Name *n; n = mk('N', sizeof(Name)); *n = *dot; n->fork = dot; n->next = n->down = nil; if(dot->v == dot) n->v = n; if(dot->up == dot) n->up = n; else { if(n->up = forkname(dot->up)) n->up->down = n; } return n; } static Name* getseg(Name *dot, void *seg, int new) { Name *n, *l; for(n = l = nil; dot; dot = dot->fork){ for(n = dot->down; n; n = n->next){ if(memcmp(seg, n->seg, 4) == 0) return n; l = n; } if(new){ n = mk('N', sizeof(Name)); memmove(n->seg, seg, sizeof(n->seg)); n->up = dot; if(l == nil) dot->down = n; else l->next = n; n->v = n; break; } } return n; } Name* getname(Name *dot, char *path, int new) { char seg[4]; int i, s; Name *x; s = !new; if(*path == '\\'){ path++; dot = rootname(dot); s = 0; } while(*path == '^'){ path++; dot = dot->up; s = 0; } do { for(i=0; i<4; i++){ if(*path == 0 || *path == '.') break; seg[i] = *path++; } if(i == 0) break; while(i < 4) seg[i++] = '_'; if(s && *path == 0){ for(;;){ if(x = getseg(dot, seg, 0)) break; if(dot == dot->up) break; dot = dot->up; } return x; } s = 0; dot = getseg(dot, seg, new); } while(*path++ == '.'); return dot; } static uvlong ival(void *p) { if(p) switch(TAG(p)){ case 'i': return *((uvlong*)p); case 's': return strtoull((char*)p, 0, 0); } return 0; } static uvlong rwreg(void *reg, int off, int len, uvlong v, int write) { Region *r; uchar *p; int i; switch(TAG(reg)){ case 'b': p = reg; if((off+len) > SIZE(p)) break; if(write){ /* putle(p, v, 8); */ for(i=0; i<len; i++){ p[off+i] = v & 0xFF; v >>= 8; } } else { /* v |= getle(p, 8); */ for(i=0; i<len; i++) v |= ((u64int)p[off+i]) << i*8; } return v; case 'r': r = reg; if((off+len) > r->len) break; if(amldebug){ print("rwreg: %s %-8s [%llux+%x]/%d %llux\n", write ? "W" : "R", spacename[r->space], r->off, off, len, v); } break; } return ~0; } static void *deref(void *p); static void *store(void *s, void *d); static int fieldalign(int flags) { switch(flags & AccMask){ default: case AnyAcc: case ByteAcc: case BufferAcc: