func (a RetConstant) Assemble() (RawInstruction, error) {
	return RawInstruction{
		Op: opClsReturn | opRetSrcConstant,
		K:  a.Val,
	}, nil
}
Assemble implements the Instruction Assemble method.
package bpf
import "fmt"
type Instruction interface {
	Assemble() (RawInstruction, error)
}
type RawInstruction struct {
	Op uint16
	Jt uint8
	Jf uint8
	K uint32
}
func (ri RawInstruction) Assemble() (RawInstruction, error) { return ri, nil }
func (ri RawInstruction) Disassemble() Instruction {
	switch ri.Op & opMaskCls {
	case opClsLoadA, opClsLoadX:
		reg := Register(ri.Op & opMaskLoadDest)
		sz := 0
		switch ri.Op & opMaskLoadWidth {
		case opLoadWidth4:
			sz = 4
		case opLoadWidth2:
			sz = 2
		case opLoadWidth1:
			sz = 1
		default:
			return ri
		}
		switch ri.Op & opMaskLoadMode {
		case opAddrModeImmediate:
			if sz != 4 {
				return ri
			}
			return LoadConstant{Dst: reg, Val: ri.K}
		case opAddrModeScratch:
			if sz != 4 || ri.K > 15 {
				return ri
			}
			return LoadScratch{Dst: reg, N: int(ri.K)}
		case opAddrModeAbsolute:
			if ri.K > extOffset+0xffffffff {
				return LoadExtension{Num: Extension(-extOffset + ri.K)}
			}
			return LoadAbsolute{Size: sz, Off: ri.K}
		case opAddrModeIndirect:
			return LoadIndirect{Size: sz, Off: ri.K}
		case opAddrModePacketLen:
			if sz != 4 {
				return ri
			}
			return LoadExtension{Num: ExtLen}
		case opAddrModeMemShift:
			return LoadMemShift{Off: ri.K}
		default:
			return ri
		}
	case opClsStoreA:
		if ri.Op != opClsStoreA || ri.K > 15 {
			return ri
		}
		return StoreScratch{Src: RegA, N: int(ri.K)}
	case opClsStoreX:
		if ri.Op != opClsStoreX || ri.K > 15 {
			return ri
		}
		return StoreScratch{Src: RegX, N: int(ri.K)}
	case opClsALU:
		switch op := ALUOp(ri.Op & opMaskOperator); op {
		case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor:
			switch operand := opOperand(ri.Op & opMaskOperand); operand {
			case opOperandX:
				return ALUOpX{Op: op}
			case opOperandConstant:
				return ALUOpConstant{Op: op, Val: ri.K}
			default:
				return ri
			}
		case aluOpNeg:
			return NegateA{}
		default:
			return ri
		}
	case opClsJump:
		switch op := jumpOp(ri.Op & opMaskOperator); op {
		case opJumpAlways:
			return Jump{Skip: ri.K}
		case opJumpEqual, opJumpGT, opJumpGE, opJumpSet:
			cond, skipTrue, skipFalse := jumpOpToTest(op, ri.Jt, ri.Jf)
			switch operand := opOperand(ri.Op & opMaskOperand); operand {
			case opOperandX:
				return JumpIfX{Cond: cond, SkipTrue: skipTrue, SkipFalse: skipFalse}
			case opOperandConstant:
				return JumpIf{Cond: cond, Val: ri.K, SkipTrue: skipTrue, SkipFalse: skipFalse}
			default:
				return ri
			}
		default:
			return ri
		}
	case opClsReturn:
		switch ri.Op {
		case opClsReturn | opRetSrcA:
			return RetA{}
		case opClsReturn | opRetSrcConstant:
			return RetConstant{Val: ri.K}
		default:
			return ri
		}
	case opClsMisc:
		switch ri.Op {
		case opClsMisc | opMiscTAX:
			return TAX{}
		case opClsMisc | opMiscTXA:
			return TXA{}
		default:
			return ri
		}
	default:
		panic("unreachable")  
	}
}
func jumpOpToTest(op jumpOp, skipTrue uint8, skipFalse uint8) (JumpTest, uint8, uint8) {
	var test JumpTest
	if skipTrue == 0 {
		switch op {
		case opJumpEqual:
			test = JumpNotEqual
		case opJumpGT:
			test = JumpLessOrEqual
		case opJumpGE:
			test = JumpLessThan
		case opJumpSet:
			test = JumpBitsNotSet
		}
		return test, skipFalse, 0
	}
	switch op {
	case opJumpEqual:
		test = JumpEqual
	case opJumpGT:
		test = JumpGreaterThan
	case opJumpGE:
		test = JumpGreaterOrEqual
	case opJumpSet:
		test = JumpBitsSet
	}
	return test, skipTrue, skipFalse
}
type LoadConstant struct {
	Dst Register
	Val uint32
}
func (a LoadConstant) Assemble() (RawInstruction, error) {
	return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
}
func (a LoadConstant) String() string {
	switch a.Dst {
	case RegA:
		return fmt.Sprintf("ld #%d", a.Val)
	case RegX:
		return fmt.Sprintf("ldx #%d", a.Val)
	default:
		return fmt.Sprintf("unknown instruction: %#v", a)
	}
}
type LoadScratch struct {
	Dst Register
	N   int  
}
func (a LoadScratch) Assemble() (RawInstruction, error) {
	if a.N < 0 || a.N > 15 {
		return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
	}
	return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
}
func (a LoadScratch) String() string {
	switch a.Dst {
	case RegA:
		return fmt.Sprintf("ld M[%d]", a.N)
	case RegX:
		return fmt.Sprintf("ldx M[%d]", a.N)
	default:
		return fmt.Sprintf("unknown instruction: %#v", a)
	}
}
type LoadAbsolute struct {
	Off  uint32
	Size int  
}
func (a LoadAbsolute) Assemble() (RawInstruction, error) {
	return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
}
func (a LoadAbsolute) String() string {
	switch a.Size {
	case 1:  
		return fmt.Sprintf("ldb [%d]", a.Off)
	case 2:  
		return fmt.Sprintf("ldh [%d]", a.Off)
	case 4:  
		if a.Off > extOffset+0xffffffff {
			return LoadExtension{Num: Extension(a.Off + 0x1000)}.String()
		}
		return fmt.Sprintf("ld [%d]", a.Off)
	default:
		return fmt.Sprintf("unknown instruction: %#v", a)
	}
}
type LoadIndirect struct {
	Off  uint32
	Size int  
}
func (a LoadIndirect) Assemble() (RawInstruction, error) {
	return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
}
func (a LoadIndirect) String() string {
	switch a.Size {
	case 1:  
		return fmt.Sprintf("ldb [x + %d]", a.Off)
	case 2:  
		return fmt.Sprintf("ldh [x + %d]", a.Off)
	case 4:  
		return fmt.Sprintf("ld [x + %d]", a.Off)
	default:
		return fmt.Sprintf("unknown instruction: %#v", a)
	}
}
type LoadMemShift struct {
	Off uint32
}
func (a LoadMemShift) Assemble() (RawInstruction, error) {
	return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
}
func (a LoadMemShift) String() string {
	return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off)
}
type LoadExtension struct {
	Num Extension
}
func (a LoadExtension) Assemble() (RawInstruction, error) {
	if a.Num == ExtLen {
		return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
	}
	return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num))
}
func (a LoadExtension) String() string {
	switch a.Num {
	case ExtLen:
		return "ld #len"
	case ExtProto:
		return "ld #proto"
	case ExtType:
		return "ld #type"
	case ExtPayloadOffset:
		return "ld #poff"
	case ExtInterfaceIndex:
		return "ld #ifidx"
	case ExtNetlinkAttr:
		return "ld #nla"
	case ExtNetlinkAttrNested:
		return "ld #nlan"
	case ExtMark:
		return "ld #mark"
	case ExtQueue:
		return "ld #queue"
	case ExtLinkLayerType:
		return "ld #hatype"
	case ExtRXHash:
		return "ld #rxhash"
	case ExtCPUID:
		return "ld #cpu"
	case ExtVLANTag:
		return "ld #vlan_tci"
	case ExtVLANTagPresent:
		return "ld #vlan_avail"
	case ExtVLANProto:
		return "ld #vlan_tpid"
	case ExtRand:
		return "ld #rand"
	default:
		return fmt.Sprintf("unknown instruction: %#v", a)
	}
}
type StoreScratch struct {
	Src Register
	N   int  
}
func (a StoreScratch) Assemble() (RawInstruction, error) {
	if a.N < 0 || a.N > 15 {
		return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
	}
	var op uint16
	switch a.Src {
	case RegA:
		op = opClsStoreA
	case RegX:
		op = opClsStoreX
	default:
		return RawInstruction{}, fmt.Errorf("invalid source register %v", a.Src)
	}
	return RawInstruction{
		Op: op,
		K:  uint32(a.N),
	}, nil
}
func (a StoreScratch) String() string {
	switch a.Src {
	case RegA:
		return fmt.Sprintf("st M[%d]", a.N)
	case RegX:
		return fmt.Sprintf("stx M[%d]", a.N)
	default:
		return fmt.Sprintf("unknown instruction: %#v", a)
	}
}
type ALUOpConstant struct {
	Op  ALUOp
	Val uint32
}
func (a ALUOpConstant) Assemble() (RawInstruction, error) {
	return RawInstruction{
		Op: opClsALU | uint16(opOperandConstant) | uint16(a.Op),
		K:  a.Val,
	}, nil
}
func (a ALUOpConstant) String() string {
	switch a.Op {
	case ALUOpAdd:
		return fmt.Sprintf("add #%d", a.Val)
	case ALUOpSub:
		return fmt.Sprintf("sub #%d", a.Val)
	case ALUOpMul:
		return fmt.Sprintf("mul #%d", a.Val)
	case ALUOpDiv:
		return fmt.Sprintf("div #%d", a.Val)
	case ALUOpMod:
		return fmt.Sprintf("mod #%d", a.Val)
	case ALUOpAnd:
		return fmt.Sprintf("and #%d", a.Val)
	case ALUOpOr:
		return fmt.Sprintf("or #%d", a.Val)
	case ALUOpXor:
		return fmt.Sprintf("xor #%d", a.Val)
	case ALUOpShiftLeft:
		return fmt.Sprintf("lsh #%d", a.Val)
	case ALUOpShiftRight:
		return fmt.Sprintf("rsh #%d", a.Val)
	default:
		return fmt.Sprintf("unknown instruction: %#v", a)
	}
}
type ALUOpX struct {
	Op ALUOp
}
func (a ALUOpX) Assemble() (RawInstruction, error) {
	return RawInstruction{
		Op: opClsALU | uint16(opOperandX) | uint16(a.Op),
	}, nil
}
func (a ALUOpX) String() string {
	switch a.Op {
	case ALUOpAdd:
		return "add x"
	case ALUOpSub:
		return "sub x"
	case ALUOpMul:
		return "mul x"
	case ALUOpDiv:
		return "div x"
	case ALUOpMod:
		return "mod x"
	case ALUOpAnd:
		return "and x"
	case ALUOpOr:
		return "or x"
	case ALUOpXor:
		return "xor x"
	case ALUOpShiftLeft:
		return "lsh x"
	case ALUOpShiftRight:
		return "rsh x"
	default:
		return fmt.Sprintf("unknown instruction: %#v", a)
	}
}
type NegateA struct{}
func (a NegateA) Assemble() (RawInstruction, error) {
	return RawInstruction{
		Op: opClsALU | uint16(aluOpNeg),
	}, nil
}
func (a NegateA) String() string {
	return fmt.Sprintf("neg")
}
type Jump struct {
	Skip uint32
}
func (a Jump) Assemble() (RawInstruction, error) {
	return RawInstruction{
		Op: opClsJump | uint16(opJumpAlways),
		K:  a.Skip,
	}, nil
}
func (a Jump) String() string {
	return fmt.Sprintf("ja %d", a.Skip)
}
type JumpIf struct {
	Cond      JumpTest
	Val       uint32
	SkipTrue  uint8
	SkipFalse uint8
}
func (a JumpIf) Assemble() (RawInstruction, error) {
	return jumpToRaw(a.Cond, opOperandConstant, a.Val, a.SkipTrue, a.SkipFalse)
}
func (a JumpIf) String() string {
	return jumpToString(a.Cond, fmt.Sprintf("#%d", a.Val), a.SkipTrue, a.SkipFalse)
}
type JumpIfX struct {
	Cond      JumpTest
	SkipTrue  uint8
	SkipFalse uint8
}
func (a JumpIfX) Assemble() (RawInstruction, error) {
	return jumpToRaw(a.Cond, opOperandX, 0, a.SkipTrue, a.SkipFalse)
}
func (a JumpIfX) String() string {
	return jumpToString(a.Cond, "x", a.SkipTrue, a.SkipFalse)
}
func jumpToRaw(test JumpTest, operand opOperand, k uint32, skipTrue, skipFalse uint8) (RawInstruction, error) {
	var (
		cond jumpOp
		flip bool
	)
	switch test {
	case JumpEqual:
		cond = opJumpEqual
	case JumpNotEqual:
		cond, flip = opJumpEqual, true
	case JumpGreaterThan:
		cond = opJumpGT
	case JumpLessThan:
		cond, flip = opJumpGE, true
	case JumpGreaterOrEqual:
		cond = opJumpGE
	case JumpLessOrEqual:
		cond, flip = opJumpGT, true
	case JumpBitsSet:
		cond = opJumpSet
	case JumpBitsNotSet:
		cond, flip = opJumpSet, true
	default:
		return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", test)
	}
	jt, jf := skipTrue, skipFalse
	if flip {
		jt, jf = jf, jt
	}
	return RawInstruction{
		Op: opClsJump | uint16(cond) | uint16(operand),
		Jt: jt,
		Jf: jf,
		K:  k,
	}, nil
}
func jumpToString(cond JumpTest, operand string, skipTrue, skipFalse uint8) string {
	switch cond {
	case JumpEqual:
		return conditionalJump(operand, skipTrue, skipFalse, "jeq", "jneq")
	case JumpNotEqual:
		return fmt.Sprintf("jneq %s,%d", operand, skipTrue)
	case JumpGreaterThan:
		return conditionalJump(operand, skipTrue, skipFalse, "jgt", "jle")
	case JumpLessThan:
		return fmt.Sprintf("jlt %s,%d", operand, skipTrue)
	case JumpGreaterOrEqual:
		return conditionalJump(operand, skipTrue, skipFalse, "jge", "jlt")
	case JumpLessOrEqual:
		return fmt.Sprintf("jle %s,%d", operand, skipTrue)
	case JumpBitsSet:
		if skipFalse > 0 {
			return fmt.Sprintf("jset %s,%d,%d", operand, skipTrue, skipFalse)
		}
		return fmt.Sprintf("jset %s,%d", operand, skipTrue)
	case JumpBitsNotSet:
		return jumpToString(JumpBitsSet, operand, skipFalse, skipTrue)
	default:
		return fmt.Sprintf("unknown JumpTest %#v", cond)
	}
}
func conditionalJump(operand string, skipTrue, skipFalse uint8, positiveJump, negativeJump string) string {
	if skipTrue > 0 {
		if skipFalse > 0 {
			return fmt.Sprintf("%s %s,%d,%d", positiveJump, operand, skipTrue, skipFalse)
		}
		return fmt.Sprintf("%s %s,%d", positiveJump, operand, skipTrue)
	}
	return fmt.Sprintf("%s %s,%d", negativeJump, operand, skipFalse)
}
type RetA struct{}
func (a RetA) Assemble() (RawInstruction, error) {
	return RawInstruction{
		Op: opClsReturn | opRetSrcA,
	}, nil
}
func (a RetA) String() string {
	return fmt.Sprintf("ret a")
}
type RetConstant struct {
	Val uint32
}