Пример #1
0
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])
			}
		}
	}
}
Пример #2
0
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")
}
Пример #3
0
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")
	}
}
Пример #4
0
func genop(op int, arg uint32) {
	emit32(uint32(op))
	if paminstr.Hasarg(uint32(op)) {
		emit32(arg)
	}
}