func (vm *v53) shr(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		ra = vm.thread().arith(OpRsh, rb, rc)
	)
	vm.thread().frame().set(instr.A(), ra)
}
SHR: Shift bits right.

@args A B C

R(A) := RK(B) >> RK(C)
package lua
import "github.com/Azure/golua/lua/vm"
func (vm *v53) move(instr vm.Instr) {
	rb := vm.thread().frame().get(instr.B())
	vm.thread().frame().set(instr.A(), rb)
}
func (vm *v53) loadk(instr vm.Instr) {
	kst := vm.constant(instr.BX())
	vm.thread().frame().set(instr.A(), kst)
}
func (vm *v53) loadkx(instr vm.Instr) {
	extra := vm.thread().frame().step(1).AX()
	ra := vm.constant(extra)
	vm.thread().frame().set(instr.A(), ra)
}
func (vm *v53) loadbool(instr vm.Instr) {
	vm.thread().frame().set(instr.A(), Bool(instr.B() == 1))
	if instr.C() != 0 {
		vm.thread().frame().step(1)
	}
}
func (vm *v53) loadnil(instr vm.Instr) {
	var (
		a = instr.A()
		b = instr.B()
	)
	for i := a; i <= a+b; i++ {
		vm.thread().frame().set(i, Nil(1))
	}
}
func (vm *v53) getupval(instr vm.Instr) {
	var (
		a = instr.A()
		b = instr.B()
	)
	up := vm.thread().frame().getUp(b)
	vm.thread().frame().set(a, up.get())
}
func (vm *v53) setupval(instr vm.Instr) {
	var (
		a = instr.A()
		b = instr.B()
	)
	ra := vm.thread().frame().get(a)
	vm.thread().frame().setUp(b, ra)
}
func (vm *v53) gettable(instr vm.Instr) {
	var (
		a = instr.A()
		b = instr.B()
		c = instr.C()
	)
	t := vm.thread().frame().get(b)
	k := vm.rk(c)
	v := vm.thread().gettable(t, k, false)
	vm.thread().frame().set(a, v)
}
func (vm *v53) settable(instr vm.Instr) {
	obj := vm.thread().frame().get(instr.A())
	key := vm.rk(instr.B())
	val := vm.rk(instr.C())
	vm.thread().settable(obj, key, val, false)
}
func (vm *v53) gettabup(instr vm.Instr) {
	up := vm.thread().frame().getUp(instr.B()).get()
	rc := vm.rk(instr.C())
	ra := vm.thread().gettable(up, rc, false)
	vm.thread().frame().set(instr.A(), ra)
}
func (vm *v53) settabup(instr vm.Instr) {
	up := vm.thread().frame().getUp(instr.A()).get()
	rb := vm.rk(instr.B())
	rc := vm.rk(instr.C())
	vm.thread().settable(up, rb, rc, false)
}
func (vm *v53) newtable(instr vm.Instr) {
	var (
		a = instr.A()
		b = instr.B()
		c = instr.C()
	)
	t := newTable(vm.thread(), fb2i(b), fb2i(c))
	vm.thread().frame().set(a, t)
}
func (vm *v53) self(instr vm.Instr) {
	var (
		obj = vm.thread().frame().get(instr.B())
		key = vm.rk(instr.C())
		fn  = vm.thread().gettable(obj, key, false)
	)
	vm.thread().frame().set(instr.A(), fn)
	vm.thread().frame().set(instr.A()+1, obj)
}
func (vm *v53) add(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		ra = vm.thread().arith(OpAdd, rb, rc)
	)
	vm.thread().frame().set(instr.A(), ra)
}
func (vm *v53) sub(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		ra = vm.thread().arith(OpSub, rb, rc)
	)
	vm.thread().frame().set(instr.A(), ra)
}
func (vm *v53) mul(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		ra = vm.thread().arith(OpMul, rb, rc)
	)
	vm.thread().frame().set(instr.A(), ra)
}
func (vm *v53) mod(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		ra = vm.thread().arith(OpMod, rb, rc)
	)
	vm.thread().frame().set(instr.A(), ra)
}
func (vm *v53) pow(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		ra = vm.thread().arith(OpPow, rb, rc)
	)
	vm.thread().frame().set(instr.A(), ra)
}
func (vm *v53) div(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		ra = vm.thread().arith(OpDiv, rb, rc)
	)
	vm.thread().frame().set(instr.A(), ra)
}
func (vm *v53) unm(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		ra = vm.thread().arith(OpMinus, rb, None)
	)
	vm.thread().frame().set(instr.A(), ra)
}
func (vm *v53) not(instr vm.Instr) {
	rb := vm.thread().frame().get(instr.B())
	vm.thread().frame().set(instr.A(), !truth(rb))
}
func (vm *v53) length(instr vm.Instr) {
	rb := vm.thread().frame().get(instr.B())
	vm.thread().frame().set(instr.A(), vm.thread().length(rb))
}
func (vm *v53) concat(instr vm.Instr) {
	var (
		a = instr.A()
		b = instr.B()
		c = instr.C()
	)
	vm.thread().Concat(c - b + 1)
	vm.thread().frame().replace(a)
}
func (vm *v53) jmp(instr vm.Instr) {
	vm.thread().frame().step(instr.SBX())
	if a := instr.A(); a != 0 {
		vm.thread().frame().closeUp(a - 1)
	}
}
func (vm *v53) eq(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		aa = (instr.A() != 0)
	)
	if vm.thread().compare(OpEq, rb, rc, false) != aa {
		vm.thread().frame().step(1)
	}
}
func (vm *v53) lt(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		aa = (instr.A() == 1)
	)
	if vm.thread().compare(OpLt, rb, rc, false) != aa {
		vm.thread().frame().step(1)
	}
}
func (vm *v53) le(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		aa = (instr.A() == 1)
	)
	if vm.thread().compare(OpLe, rb, rc, false) != aa {
		vm.thread().frame().step(1)
	}
}
func (vm *v53) test(instr vm.Instr) {
	var (
		ra = vm.thread().frame().get(instr.A())
		cc = (instr.C() == 1)
	)
	if Truth(ra) != cc {
		vm.thread().frame().step(1)
	}
}
func (vm *v53) testset(instr vm.Instr) {
	var (
		rb = vm.thread().frame().get(instr.B())
		cc = (instr.C() == 1)
	)
	if Truth(rb) == cc {
		vm.thread().frame().set(instr.A(), rb)
	} else {
		vm.thread().frame().step(1)
	}
}
func (vm *v53) call(instr vm.Instr) {
	var (
		a = instr.A()
		b = instr.B()
		c = instr.C()
	)
	if b != 0 {
		vm.thread().frame().settop(a + b)
		vm.thread().Call(b-1, c-1)
	} else {
		vm.thread().Call(vm.thread().frame().gettop()-a-1, c-1)
	}
	if c--; c > 0 {
		for i, v := range vm.thread().frame().popN(c) {
			vm.thread().frame().set(a+i, v)
		}
	}
}
func (vm *v53) tailcall(instr vm.Instr) {
	var (
		a = instr.A()
		b = instr.B()
		c = instr.C()
	)
	if b != 0 {
		vm.thread().frame().settop(a + b)
		vm.thread().Call(b-1, c-1)
	} else {
		vm.thread().Call(vm.thread().frame().gettop()-a-1, c-1)
	}
	if c--; c > 0 {
		for i, v := range vm.thread().frame().popN(c) {
			vm.thread().frame().set(a+i, v)
		}
	}
}
func (vm *v53) returns(instr vm.Instr) {
	var (
		a = instr.A()
		b = instr.B()
	)
	if want := vm.thread().frame().rets; want != 0 {
		b--
		var (
			retc int = b
			rets []Value
		)
		if b == -1 {
			retc = vm.thread().frame().gettop() - a
		}
		switch {
		case want > retc:  
			for i := a; i < a+retc; i++ {
				rets = append(rets, vm.thread().frame().get(i))
			}
			for retc < want {
				rets = append(rets, None)
				retc++
			}
		case want <= retc:  
			if want == MultRets {
				want = retc
			}
			for i := a; i < a+want; i++ {
				rets = append(rets, vm.thread().frame().get(i))
			}
		}
		vm.thread().frame().caller().pushN(rets)
	}
}
func (vm *v53) forloop(instr vm.Instr) {
	var (
		item = vm.thread().frame().get(instr.A())
		upto = vm.thread().frame().get(instr.A() + 1)
		step = vm.thread().frame().get(instr.A() + 2)
	)
	if isInteger(item) {  
		i1 := item.(Int)
		i2 := upto.(Int)
		i3 := step.(Int)
		i1 += i3  
		if (i3 > 0 && (i1 <= i2)) || (i3 < 0 && (i1 > i2)) {
			vm.thread().frame().set(instr.A(), i1)    
			vm.thread().frame().set(instr.A()+3, i1)  
			vm.thread().frame().step(instr.SBX())     
		}
	} else {  
		f1 := item.(Float)
		f2 := upto.(Float)
		f3 := step.(Float)
		f1 += f3
		if (f3 > 0 && (f1 <= f2)) || (f3 < 0 && (f1 > f2)) {
			vm.thread().frame().set(instr.A(), f1)    
			vm.thread().frame().set(instr.A()+3, f1)  
			vm.thread().frame().step(instr.SBX())     
		}
	}
}
func (vm *v53) forprep(instr vm.Instr) {
	var (
		init = vm.thread().frame().get(instr.A())
		upto = vm.thread().frame().get(instr.A() + 1)
		step = vm.thread().frame().get(instr.A() + 2)
	)
	var (
		i1, ok1 = toInteger(init)
		i2, ok2 = toInteger(upto)
		i3, ok3 = toInteger(step)
	)
	if ok1 && ok2 && ok3 {
		vm.thread().frame().set(instr.A(), i1-i3)
		vm.thread().frame().set(instr.A()+1, i2)
		vm.thread().frame().set(instr.A()+2, i3)
		vm.thread().frame().step(instr.SBX())
		return
	}
	var f1, f2, f3 Float
	if f1, ok1 = toFloat(init); !ok1 {
		vm.thread().errorf("'for' init must be a number")
	}
	if f2, ok2 = toFloat(upto); !ok2 {
		vm.thread().errorf("'for' limit must be a number")
	}
	if f3, ok3 = toFloat(step); !ok3 {
		vm.thread().errorf("'for' step must be a number")
	}
	vm.thread().frame().set(instr.A(), f1-f3)
	vm.thread().frame().set(instr.A()+1, f2)
	vm.thread().frame().set(instr.A()+2, f3)
	vm.thread().frame().step(instr.SBX())
}
func (vm *v53) tforcall(instr vm.Instr) {
	var (
		a = instr.A()
		c = instr.C()
	)
	var (
		iter = vm.thread().frame().get(a)      
		data = vm.thread().frame().get(a + 1)  
		ctrl = vm.thread().frame().get(a + 2)  
		base = instr.A() + 3
	)
	vm.thread().frame().push(iter)
	vm.thread().frame().push(data)
	vm.thread().frame().push(ctrl)
	vm.thread().Call(2, c)
	rets := vm.thread().frame().popN(c)
	for i, v := range rets {
		vm.thread().frame().set(base+i, v)
	}
}
func (vm *v53) tforloop(instr vm.Instr) {
	if ctrl := vm.thread().frame().get(instr.A() + 1); !IsNone(ctrl) {
		vm.thread().frame().set(instr.A(), ctrl)
		vm.thread().frame().step(instr.SBX())
		return
	}
	vm.thread().frame().settop(instr.A())
}
func (vm *v53) setlist(instr vm.Instr) {
	var (
		a = instr.A()
		b = instr.B()
		c = instr.C()
	)
	if b == 0 {
		b = vm.thread().frame().gettop() - a - 1
	}
	o := (c - 1) * FieldsPerFlush
	t := vm.thread().frame().get(a).(*table)
	for i := 1; i <= b; i++ {
		t.setInt(int64(o+i), vm.thread().frame().get(a+i))
	}
	vm.thread().frame().popN(b)
}
func (vm *v53) closure(instr vm.Instr) {
	cls := newLuaClosure(vm.prototype(instr.BX()))
	vm.thread().frame().openUp(cls)
	vm.thread().frame().push(cls)
	vm.thread().frame().replace(instr.A())
}
func (vm *v53) vararg(instr vm.Instr) {
	var (
		a = instr.A()
		b = instr.B()
	)
	for i, v := range vm.thread().frame().varargs(b - 1) {
		if v == nil {
			v = None
		}
		vm.thread().frame().set(a+i, v)
	}
}
func (vm *v53) idiv(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		ra = vm.thread().arith(OpQuo, rb, rc)
	)
	vm.thread().frame().set(instr.A(), ra)
}
func (vm *v53) band(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		ra = vm.thread().arith(OpAnd, rb, rc)
	)
	vm.thread().frame().set(instr.A(), ra)
}
func (vm *v53) bor(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		ra = vm.thread().arith(OpOr, rb, rc)
	)
	vm.thread().frame().set(instr.A(), ra)
}
func (vm *v53) bxor(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		ra = vm.thread().arith(OpXor, rb, rc)
	)
	vm.thread().frame().set(instr.A(), ra)
}
func (vm *v53) shl(instr vm.Instr) {
	var (
		rb = vm.rk(instr.B())
		rc = vm.rk(instr.C())
		ra = vm.thread().arith(OpLsh, rb, rc)
	)
	vm.thread().frame().set(instr.A(), ra)
}