func emitcode(c *Code) { var arg uint32 addr := c.addr e := c.pcs for i := uint32(0); i < uint32(c.np); i++ { for ; e!=nil && uint32(e.pc)<=addr+i && e.st!=nil; e = e.next { oprint("# %#v\n", (*genStmt)(e.st)) } oprint("%05x\t%v", addr+i, paminstr.Instr(c.p[i])) ir := c.p[i] ic := paminstr.IC(ir) if paminstr.Hasarg(c.p[i]) { i++ arg = c.p[i] if paminstr.IT(ir)==paminstr.ITreal && ic!=paminstr.ICcast { oprint("\t%e", math.Float32frombits(arg)) } else { oprint("\t%#010x", arg) } } else { oprint("\t") } first := 0 for ; e!=nil && uint32(e.pc)<=addr+i && e.nd!=nil; e = e.next { if e.nd != nil { if first == 0 { oprint("\t#") } first++ oprint(" %#v;", e.nd) } } oprint("\n") if ic == paminstr.ICdata { for ; arg > 0; arg -= 4 { i++ oprint("%05x\t%#x\n", addr+i, c.p[i]) } } } }
func pami() { //debug['X'] = 10 //debug['M'] = 10 pop2u := func() (uint32, uint32) { return pop32(), pop32() } pop2i := func() (int32, int32) { return int32(pop32()), int32(pop32()) } pop2r := func() (float64, float64) { return popr(), popr() } pop2slice := func(n int) ([]byte, []byte) { return popslice(n), popslice(n) } if int(mabs.entry) >= len(mabs.pents) { panic("bad entry number") } mst.pc = uint32(mabs.pents[mabs.entry].addr) if debug['X'] != 0 { fmt.Fprintf(os.Stderr, "entry pc %#x\n", mst.pc) } for int(mst.pc) < len(mst.text) { mabs.ninstr++ if debug['S'] != 0 { dumpxstck(10*debug['S']) } if debug['D'] > 1 { dumpglobals() } ir := fetch() ic := paminstr.IC(uint32(ir)) it := paminstr.IT(uint32(ir)) if debug['X'] != 0 { if paminstr.Hasarg(uint32(ir)) { if it == paminstr.ITreal { fmt.Fprintf(os.Stderr, "%#05x:\t%v\t%#x (%g)\n", mst.pc-1, paminstr.Instr(ir), mst.text[mst.pc], float64(mst.text[mst.pc])) } else { fmt.Fprintf(os.Stderr, "%#05x:\t%v\t%#x\n", mst.pc-1, paminstr.Instr(ir), mst.text[mst.pc]) } } else { fmt.Fprintf(os.Stderr, "%#05x:\t%v\n", mst.pc-1, paminstr.Instr(ir)) } } switch ic { case paminstr.ICnop: // nop case paminstr.ICptr: pushdaddr(xptr(popptr())) case paminstr.ICindir: // indir n -sp +sp n := int(fetch()) d1 := popslice(n) if int(mst.sp)+n > mst.stackend { panic("stack overflow") } //fmt.Printf("INDIRING %d %#x %v\n", n, *bptr, d1); copy(mst.stack[mst.sp:mst.sp+n], d1) mst.sp += n case paminstr.ICpush: // push n +sp // both real and int push32(uint32(fetch())) case paminstr.ICjmp: // jmp addr mst.pc = uint32(fetch()) case paminstr.ICjmpt: // jmpt addr taddr := fetch() if pop32() != 0 { mst.pc = uint32(taddr) } case paminstr.ICjmpf: // jmpf addr taddr := uint32(fetch()) if pop32() == 0 { mst.pc = taddr } case paminstr.ICidx: // idx tid -sp -sp +sp //substitutes addr[i] ->elem addr idx(int(fetch())) case paminstr.ICfld: // fld n -sp +sp //TODO BUG, how to do size? //substitutes addr.a ->elem addr n := uintptr(fetch()) d1 := popduaddr() pushduaddr(d1 + n) case paminstr.ICdata: // data n +sp //push n inmediate for n := fetch(); n > 0; n -= 4 { push32(uint32(fetch())) } case paminstr.ICdaddr: // daddr n +sp //push address for data n := int(fetch()) pushdaddr(&mst.stack[n]) case paminstr.ICadd: // add -sp -sp +sp if it == paminstr.ITreal { pushr(popr() + popr()) } else { push32(pop32() + pop32()) } case paminstr.ICsub: // sub -sp -sp +sp if it == paminstr.ITreal { r1, r2 := pop2r() pushr(r1 - r2) } else { a1, a2 := pop2u() push32(a1 - a2) } case paminstr.ICminus: // minus -sp +sp if it == paminstr.ITreal { pushr(-popr()) } else { push32(-pop32()) } case paminstr.ICnot: // not -sp +sp b := pop32() pushbool(b == 0) case paminstr.ICor: // or -sp -sp +sp a1, a2 := pop2u() pushbool(a1!=0 || a2!=0) case paminstr.ICand: // and -sp -sp +sp a1, a2 := pop2u() pushbool(a1!=0 && a2!=0) case paminstr.ICeq: // eq -sp -sp +sp switch it { case paminstr.ITreal: r1, r2 := pop2r() pushbool(r1 == r2) case paminstr.ITaddr: d1 := popduaddr() d2 := popduaddr() pushbool(d1 == d2) default: a1, a2 := pop2u() pushbool(a1 == a2) } case paminstr.ICeqm: // eqm n -sp +sp n := int(fetch()) d1, d2 := pop2slice(n) pushbool(bytes.Compare(d1[:n], d2[:n]) == 0) case paminstr.ICne: // ne -sp -sp +sp switch it { case paminstr.ITreal: r1, r2 := pop2r() pushbool(r1 != r2) case paminstr.ITaddr: d1 := popduaddr() d2 := popduaddr() pushbool(d1 != d2) default: a1, a2 := pop2u() pushbool(a1 != a2) } case paminstr.ICnem: // eqm n -sp +sp n := int(fetch()) d1, d2 := pop2slice(n) pushbool(bytes.Compare(d1[:n], d2[:n]) != 0) case paminstr.ICcast: // cast tid -sp +sp t := tfetch(int(fetch())) if it == paminstr.ITreal { castr(t, popr()) } else { cast(t, int(int32(pop32()))) } case paminstr.ICle: // le -sp -sp +sp if it == paminstr.ITreal { r1, r2 := pop2r() pushbool(r1 <= r2) } else { a1, a2 := pop2i() pushbool(a1 <= a2) } case paminstr.ICge: // ge -sp -sp +sp if it == paminstr.ITreal { r1, r2 := pop2r() pushbool(r1 >= r2) } else { a1, a2 := pop2i() pushbool(a1 >= a2) } case paminstr.ICpow: // pow -sp -sp +sp if it == paminstr.ITreal { r1, r2 := pop2r() pushr(math.Pow(r1, r2)) } else { a1, a2 := pop2u() push32(uint32(math.Pow(float64(a1), float64(a2)))) } case paminstr.IClt: // lt -sp -sp +sp if it == paminstr.ITreal { r1, r2 := pop2r() pushbool(r1 < r2) } else { a1, a2 := pop2i() pushbool(a1 < a2) } case paminstr.ICgt: // gt -sp -sp +sp if it == paminstr.ITreal { r1, r2 := pop2r() pushbool(r1 > r2) } else { a1, a2 := pop2i() pushbool(a1 > a2) } case paminstr.ICmul: // mul -sp -sp +sp if it == paminstr.ITreal { r1, r2 := pop2r() pushr(r1*r2) } else { a1, a2 := pop2i() push32(uint32(a1*a2)) } case paminstr.ICdiv: // div -sp -sp +sp if it == paminstr.ITreal { r1, r2 := pop2r() if r2 == 0.0 { panic("divide by 0.0") } pushr(r1/r2) } else { a1, a2 := pop2i() if a2 == 0 { panic("divide by 0") } push32(uint32(a1/a2)) } case paminstr.ICmod: // mod -sp -sp +sp a1, a2 := pop2i() if a2 == 0 { panic("divide by zero") } push32(uint32(a1%a2)) case paminstr.ICcall: // call pid n := uint32(fetch()) if (n&paminstr.PAMbuiltin) != 0 { n &= ^uint32(paminstr.PAMbuiltin) if n >= paminstr.Nbuiltins { s := fmt.Sprintf("bad builtin call #%d", n) panic(s) } //fmt.Printf("BUILTIN %#x\n", n) builtin[n]() } else { call(int(n)) } case paminstr.ICret: // ret pid ret(int(fetch())) case paminstr.ICarg: // arg n +sp pushdaddr(&mst.stack[mst.ap+int(fetch())]) case paminstr.IClvar: // lvar n +sp pushdaddr(&mst.stack[mst.vp+int(fetch())]) case paminstr.ICstom: // stom n -sp -sp t := tfetch(int(fetch())) n := int(t.sz) d1, d2 := pop2slice(n) if bytes.Compare(d1[:n], d2[:n]) != 0 { tchk(t, d2) copy(d1[:n], d2) } case paminstr.ICsto: // sto n -sp -sp t := tfetch(int(fetch())) n := int(t.sz) d1 := popslice(n) if mst.sp-n < 0 { panic("stack underflow") } mst.sp -= n tchk(t, mst.stack[mst.sp:mst.sp+n]) copy(d1, mst.stack[mst.sp:mst.sp+n]) default: panic("unknown instruction") } } panic("bad program counter") }
func (f *FileSt) rtext() { var r float64 if f.rtoks() != 2 { badbin("bad text header") } if f.toks[0] != "text" { badbin("unexpected tab") } n, err := strconv.ParseInt(f.toks[1], 0, 64) if err != nil { badbin("bad rtext") } ntext := int(n) mst.text = make([]uint32, ntext) if debug['F'] != 0 { fmt.Fprintf(os.Stderr, "tab text[%d]\n", ntext) } ndata := 0 for i := 0; i < ntext; i++ { ntoks := f.rtoks() // feature: ignore extra toks in line if ntoks < 2 { badbin("bad text entry") } if ndata > 0 { n, err = strconv.ParseInt(f.toks[1], 0, 64) if err != nil { badbin("bad rtext") } mst.text[i] = uint32(n) if debug['F'] != 0 { fmt.Fprintf(os.Stderr, "%05x\t%#x\n", i, mst.text[i]) } ndata -= 4 continue } if f.toks[1][0]<'a' || f.toks[1][0]>'z' { n, err = strconv.ParseInt(f.toks[1], 0, 64) if err != nil { badbin("bad rtext") } mst.text[i] = uint32(n) } else { mst.text[i] = uint32(paminstr.Icode(f.toks[1])) } if !paminstr.Hasarg(mst.text[i]) { if debug['F'] != 0 { fmt.Fprintf(os.Stderr, "%05x\t%v\n", i, paminstr.Instr(mst.text[i])) } continue } if ntoks < 3 { errs := fmt.Sprintf("missing argument for %#x %v", mst.text[i], paminstr.Instr(mst.text[i])) panic(errs) } if i == ntext-1 { panic("truncated instruction") } ir := mst.text[i] if paminstr.IT(ir)==paminstr.ITreal && paminstr.IC(ir)!=paminstr.ICcast { r, err = strconv.ParseFloat(f.toks[2], 64) if err != nil { badbin("bad rtext") } i++ mst.text[i] = math.Float32bits(float32(r)) if debug['F'] != 0 { fmt.Fprintf(os.Stderr, "%05x\t%v\t%e\n", i-1, paminstr.Instr(ir), r) } } else { n, err = strconv.ParseInt(f.toks[2], 0, 64) if err != nil { badbin("bad rtext") } i++ mst.text[i] = uint32(n) if paminstr.IC(ir) == paminstr.ICdata { ndata = int(mst.text[i]) if (ndata%4) != 0 { badbin("bad data argument in text") } } if debug['F'] != 0 { fmt.Fprintf(os.Stderr, "%05x\t%v\t%#x\n", i-1, paminstr.Instr(ir), mst.text[i]) } } } if ndata > 0 { panic("truncated instruction") } }