// icode-s.txt
//   public release som-v2  30 December 2004

to outa code arg =
	CS[CP] = (arg << 8) | (code & 255)
	CP = CP + 1

to outs code =
	CS[CP] = code
	CP = CP + 1

// change arg, perserve code
to patch ads v =
	CS[ads] = (v << 8) | (CS[ads] & 255)

to putcode ip code data =
	CS[ip] = (data << 8) | (code & 255)

to isJmp op =
	(op == icJmp) | (op == icJt) | (op == icJf)

to reName fn | i c d lvar ref =
	lvar = getLv fn
	ref = getRef fn
	for i ref+1 CP-1
		c = CS[i] & 255
		d = CS[i] >> 8
		if (c==icGet) | (c==icPut) | (c==icInc) | (c==icDec)
			patch i lvar-d+1

to improve2 ref | i c1 d1 c2 d2 =
	// replace jmp to ret, jmp to jmp
	for i ref+1 CP-1
		c1 = CS[i] & 255
		d1 = CS[i] >> 8
		if isJmp c1
			c2 = CS[i+d1] & 255
			d2 = CS[i+d1] >> 8
			if (c1==icJmp) & (c2==icRet)
				putcode i icRet d2
			else
				if c2 == icJmp
					patch i d1+d2

// ref at "ret"
to tailCall2 ref | i ref2 c d c1 d1 arg =
	ref2 = getRef currentf
	d = CS[ref] >> 8		// ret d
	c1 = CS[ref-1] & 255	// call
	d1 = CS[ref-1] >> 8
	if (c1 == icCall) & (d1 == ref2)
//		prints "tail call" nl
		arg = getArity currentf
		CP = ref - 1
		for i 1 arg
			outa icPut (arg-i+1)
		outa icJmp (ref2-CP+1)
		outa icRet d		// necessary !
		// correct jump to ref
		for i ref2 ref-1
			c = CS[i] & 255
			d = CS[i] >> 8
			if (isJmp c) & ((d+i) == ref)
				patch i (CP-1-i)

to pr2 s1 a =
	prints s1 space print a

// search symbol table for name with ref
to prNm s1 ref | idx =
	prints s1 space
	idx = searchref ref
	if idx < 0
		prints "undef"
	else
		prints getName idx

to prCode a | op arg =
	op = CS[a] & 255
	arg = CS[a] >> 8
	case op
		icAdd: prints "Add"
		icSub: prints "Sub"
		icMul: prints "Mul"
		icDiv: prints "Div"
		icBand: prints "Band"
		icBor: prints "Bor"
		icBxor: prints "Bxor"
		icNot: prints "Not"
		icEq: prints "Eq"
		icNe: prints "Ne"
		icLt: prints "Lt"
		icLe: prints "Le"
		icGe: prints "Ge"
		icGt: prints "Gt"
		icShl: prints "Shl"
		icShr: prints "Shr"
		icMod: prints "Mod"
		icLdx: prints "Ldx"
		icStx: prints "Stx"
		icRet: pr2 "Ret" arg
		icArray: prints "Array"
		icEnd: prints "End"
		icGet: pr2 "Get" arg
		icPut: pr2 "Put" arg
		icLd: prNm "Ld" arg
		icSt: prNm "St" arg
		icJmp: pr2 "Jmp" a+arg
		icJt: pr2 "Jt" a+arg
		icJf: pr2 "Jf" a+arg
		icLit: pr2 "Lit" arg
		icCall: prNm "Call" arg
		icInc: pr2 "Inc" arg
		icDec: pr2 "Dec" arg
		icSys: pr2 "Sys" arg
		icCase: prints "Case"
		icFun: prNm "Fun" a
//		icCalli: pr2 "Calli" arg
		else: prints "Undef"

to showCode a b | i =
	for i a b
		print i space
		prCode i nl

to outM mem start end | i =
	print start space print end nl
	for i start end
		print mem[i] space
		if (i % 8) == 0 nl
	nl

// End
