func GetInstr(tinst InstructionType, datatype OpDataType) Instruction {
	if datatype.op == OP_XMM || datatype.op == OP_PACKED {
		return GetXmmInstruction(tinst).Select(datatype.xmmvariant)
	} else {
		return GetInstruction(tinst).GetSized(datatype.size)
	}
}
GetInstr, the size is in bytes
package codegen
import (
	"fmt"
	"go/token"
	"math"
	"strings"
)
type InstrOpType int
const (
	OP_INVALID InstrOpType = iota
	OP_DATA                 
	OP_XMM                  
	OP_PACKED               
)
type OpDataType struct {
	op InstrOpType
	InstrData
	xmmvariant XmmData
}
func (optype OpDataType) String() string {
	return fmt.Sprintf("OpDataType{Op:%v, InstrData: %v, Xmm: %v}", optype.op, optype.InstrData, optype.xmmvariant)
}
type InstrData struct {
	size   uint
	signed bool
}
type XmmData int
const (
	XMM_INVALID XmmData = iota
	XMM_F32
	XMM_F64
	XMM_4X_F32
	XMM_2X_F64
	XMM_F128  = XMM_2X_F64
	XMM_M128  = XMM_F128  
	XMM_M128i = XMM_F128  
	XMM_M128d = XMM_F128  
	XMM_I8X16 = XMM_F32
	XMM_U8X16 = XMM_I8X16
	XMM_I16X8 = XMM_F64
	XMM_U16X8 = XMM_I16X8
	XMM_I32X4 = XMM_4X_F32
	XMM_U32X4 = XMM_I32X4
	XMM_I64X2 = XMM_2X_F64
	XMM_U64X2 = XMM_I64X2
)
type Instruction int
type DataInstruction struct {
	TInstr InstructionType
	ByteSized Instruction
	WordSized Instruction
	LongSized Instruction
	QuadSized Instruction
	OctSized  Instruction
}
type XmmInstruction struct {
	XmmInstr InstructionType
	F32      Instruction  
	F64      Instruction  
	F32x4    Instruction  
	F64x2    Instruction  
}
func (inst DataInstruction) GetSized(size uint) Instruction {
	var instr Instruction
	switch size {
	case 1:
		instr = inst.ByteSized
	case 2:
		instr = inst.WordSized
	case 4:
		instr = inst.LongSized
	case 8:
		instr = inst.QuadSized
	case 16:
		instr = inst.OctSized
	}
	if instr == NONE {
		msgstr := "invalid size(%v), for instr (%v)"
		ice(fmt.Sprintf(msgstr, size, inst.TInstr))
	}
	return instr
}
type InstructionType int
const (
	I_INVALID InstructionType = iota
	I_ADD
	I_AND
	I_CMP
	I_CVT_FLOAT2INT
	I_CVT_INT2FLOAT
	I_CVT_FLOAT2FLOAT
	I_DIV
	I_IMUL
	I_IDIV
	I_LEA
	I_MOV
	I_MOVBSX
	I_MOVWSX
	I_MOVLSX
	I_MOVBZX
	I_MOVWZX
	I_MOVLZX
	I_MUL
	I_OR
	I_PADD
	I_PAND
	I_PANDN
	I_PCMPEQ
	I_PCMPGT
	I_PIMUL
	I_PMUL
	I_POR
	I_PSLL  
	I_PSRA  
	I_PSRL  
	I_PSUB
	I_PXOR
	I_PMOV
	I_SAL
	I_SAR
	I_SHL
	I_SHR
	I_SUB
	I_XOR
)
var Insts = []DataInstruction{
	{I_ADD, ADDB, ADDW, ADDL, ADDQ, NONE},
	{I_SUB, SUBB, SUBW, SUBL, SUBQ, NONE},
	{I_MOV, MOVB, MOVW, MOVL, MOVQ, MOVOU},
	{I_MOVBSX, NONE, MOVBWSX, MOVBLSX, MOVBQSX, NONE},
	{I_MOVWSX, NONE, NONE, MOVWLSX, MOVWQSX, NONE},
	{I_MOVLSX, NONE, NONE, NONE, MOVLQSX, NONE},
	{I_MOVBZX, NONE, MOVBWZX, MOVBLZX, MOVBQZX, NONE},
	{I_MOVWZX, NONE, NONE, MOVWLZX, MOVWQZX, NONE},
	{I_MOVLZX, NONE, NONE, NONE, MOVLQZX, NONE},
	{I_XOR, XORB, XORW, XORL, XORQ, NONE},
	{I_LEA, NONE, LEAW, LEAL, LEAQ, NONE},
	{I_MUL, MULB, MULW, MULL, MULQ, NONE},
	{I_IMUL, IMULB, IMULW, IMULL, IMULQ, NONE},
	{I_DIV, DIVB, DIVW, DIVL, DIVQ, NONE},
	{I_IDIV, IDIVB, IDIVW, IDIVL, IDIVQ, NONE},
	{I_AND, ANDB, ANDW, ANDL, ANDQ, NONE},
	{I_OR, ORB, ORW, ORL, ORQ, NONE},
	{I_SHL, SHLB, SHLW, SHLL, SHLQ, NONE},
	{I_SHR, SHRB, SHRW, SHRL, SHRQ, NONE},
	{I_SAL, SALB, SHLW, SHLL, SHLQ, NONE},
	{I_SAR, SARB, SARW, SARL, SARQ, NONE},
	{I_CMP, CMPB, CMPW, CMPL, CMPQ, NONE},
}
var XmmInsts = []XmmInstruction{
	{I_ADD, ADDSS, ADDSD, ADDPS, ADDPD},
	{I_CMP, UCOMISS, UCOMISD, NONE, NONE},
	{I_DIV, DIVSS, DIVSD, DIVPS, DIVPD},
	{I_MOV, MOVSS, MOVSD, MOVUPS, MOVUPD},
	{I_MUL, MULSS, MULSD, MULPS, MULPD},
	{I_SUB, SUBSS, SUBSD, SUBPS, SUBPD},
	{I_XOR, NONE, NONE, XORPS, XORPD},
	{I_PADD, PADDB, PADDW, PADDL, PADDQ},
	{I_PAND, PANDB, PANDW, PANDL, PAND},
	{I_PANDN, NONE, NONE, NONE, PANDN},
	{I_PCMPEQ, PCMPEQB, PCMPEQW, PCMPEQL, NONE},
	{I_PCMPGT, PCMPGTB, PCMPGTW, PCMPGTL, NONE},
	{I_PIMUL, NONE, PMULLW, NONE, NONE},
	{I_PMOV, MOVOU, MOVOU, MOVOU, MOVOU},
	{I_POR, POR, POR, POR, POR},
	{I_PSLL, NONE, PSLLW, PSLLL, PSLLQ},
	{I_PSRA, NONE, PSRAW, PSRAL, NONE},
	{I_PSRL, NONE, PSRLW, PSRLL, PSRLQ},
	{I_PMUL, NONE, NONE, PMULULQ, NONE},
	{I_PSUB, PSUBB, PSUBW, PSUBL, PSUBQ},
	{I_PXOR, NONE, NONE, NONE, PXOR},
}
func GetInstruction(tinst InstructionType) DataInstruction {
	for _, inst := range Insts {
		if inst.TInstr == tinst {
			return inst
		}
	}
	ice("couldn't get instruction")
	return DataInstruction{}
}
func GetXmmInstruction(tinst InstructionType) XmmInstruction {
	for _, inst := range XmmInsts {
		if inst.XmmInstr == tinst {
			return inst
		}
	}
	ice(fmt.Sprintf("Couldn't get xmm instruction (%v)", tinst))
	return XmmInstruction{}
}
func (xinstr XmmInstruction) Select(variant XmmData) Instruction {
	var instr Instruction
	switch variant {
	case XMM_F32:
		instr = xinstr.F32
	case XMM_F64:
		instr = xinstr.F64
	case XMM_4X_F32:
		instr = xinstr.F32x4
	case XMM_2X_F64:
		instr = xinstr.F64x2
	}
	if instr == NONE {
		s := fmt.Sprintf("unrecognized variant \"%v\" for \"%v\"", variant, xinstr.XmmInstr)
		panic(ice(s))
	}
	return instr
}
func GetConvertInstruction(tinst InstructionType, fromsize, tosize uint) Instruction {
	if tinst == I_CVT_FLOAT2INT {
		if fromsize == 4 && tosize <= 4 {
			return CVTTSS2SL
		} else if fromsize == 4 && tosize == 8 {
			return CVTTSS2SQ
		} else if fromsize == 8 && tosize <= 4 {
			return CVTTSD2SL
		} else if fromsize == 8 && tosize == 8 {
			return CVTTSD2SQ
		}
	} else if tinst == I_CVT_INT2FLOAT {
		if fromsize == 4 && tosize == 4 {
			return CVTSL2SS
		} else if fromsize == 4 && tosize == 8 {
			return CVTSL2SD
		} else if fromsize == 8 && tosize == 4 {
			return CVTSQ2SS
		} else if fromsize == 8 && tosize == 8 {
			return CVTSQ2SD
		}
	} else if tinst == I_CVT_FLOAT2FLOAT {
		if fromsize == 4 && tosize == 8 {
			return CVTSS2SD
		} else if fromsize == 8 && tosize == 4 {
			return CVTSD2SS
		}
	}
	ice(fmt.Sprintf("numeric type conversion instruction (%v)", tinst))
	return NONE
}