protected IList<AddressIndependentThing> EncodeImmediate(RISA.Operand op)
        {
            var immop = op as ImmediateOperand;
            var addrop = op as AddressOperand;
            if (immop != null)
            {
                byte[] bytes = null;
                switch (op.Size)
                {
                    case OperandSize.Byte:
                        bytes = new byte[1] { (byte)immop.Value };
                        break;
                    case OperandSize.Word:
                        bytes = BitConverter.GetBytes((short)immop.Value);
                        break;
                    case OperandSize.DWord:
                        bytes = BitConverter.GetBytes((int)immop.Value);
                        break;
                    case OperandSize.QWord:
                        bytes = BitConverter.GetBytes(immop.Value);
                        break;
                }
                return bytes.Convert();
            }
            else if (addrop != null)
            {
                return new List<AddressIndependentThing>() { AIF.Instance.Address(addrop.Label) };
            }

            return null;
        }
        private bool IsExtendedRegister(RISA.Operand op)
        {
            var rop = op as RegisterOperand;
            if (rop != null)
            {
                if (rop.Type.IsCombo(RISA.OperandType.ArgumentRegister))
                {
                    return rop.Index == 2 || rop.Index == 3;
                }

                // general register case?
            }

            return false;
        }
        protected byte RegisterIndex(RISA.Operand baseOperand)
        {
            var operand = baseOperand as RegisterOperand;
            if (operand == null)
                throw new Exception("ModRM.rm not register");

            if (operand.Type.IsCombo(RISA.OperandType.ReturnRegister))
                return 0; // rax | xmm0
            else if (operand.Type.IsCombo(RISA.OperandType.StackRegister))
                return 4;
            else if (operand.Type.IsCombo(RISA.OperandType.ReturnRegister))
                return 5;
            else if (operand.Type.IsCombo(RISA.OperandType.ArgumentRegister))
            {
                switch (operand.Index)
                {
                    case 0:
                        return 1; //TODO: windows only
                    case 1:
                        return 2; //TODO: windows only
                    case 2:
                        return 0;
                    case 3:
                        return 1;
                }
            }
            else if (operand.Type.IsCombo(RISA.OperandType.GeneralRegister))
            {
                switch (operand.Index)
                {
                    case 0:
                        return 3;
                    case 1:
                        return 6;
                    case 2:
                        return 7;
                    default:
                        return (byte)(operand.Index - 2);
                }
            }

            throw new Exception("Unexpected register");
        }
 private bool IsLargeOperand(RISA.Operand op)
 {
     return op.Size == OperandSize.QWord || op.Size == OperandSize.OWord;
 }
        private void ProcessOp(ref byte modrm, ref byte sib, Operand localOperand, RISA.Operand op)
        {
            if (localOperand.Type == OperandType.Register)
                PutValue(ref modrm, ref sib, localOperand.EncodingPosition, RegisterIndex(op));
            else if (localOperand.Type == OperandType.Memory)
            {
                var mop = op as MemoryOperand;
                var registerOffset = mop.Address as RegisterOperand;
                var offsetOffset = mop.Address as OffsetOperand;
                var addrOffset = mop.Address as AddressOperand;

                if (registerOffset != null)
                {
                    PutValue(ref modrm, ref sib, EncodingPosition.Mod, 0);
                    byte regIndex = RegisterIndex(registerOffset);

                    switch (regIndex & 7)
                    {
                        case 4: //SP/R12
                            PutValue(ref modrm, ref sib, EncodingPosition.RM, regIndex);
                            PutValue(ref modrm, ref sib, EncodingPosition.Index, regIndex);
                            PutValue(ref modrm, ref sib, EncodingPosition.Base, regIndex);
                            break;
                        case 5: // BP/R13
                            throw new Exception("this is weird");
                        default:
                            // check for scale, indexer, etc
                            PutValue(ref modrm, ref sib, EncodingPosition.RM, regIndex);
                            break;
                    }
                }
                else if (offsetOffset != null)
                {
                    byte regIndex = RegisterIndex(offsetOffset.Register);
                    switch (regIndex & 7)
                    {
                        case 4: //SP/R12
                            PutValue(ref modrm, ref sib, EncodingPosition.RM, regIndex);
                            PutValue(ref modrm, ref sib, EncodingPosition.Index, (byte)(regIndex & 7));
                            PutValue(ref modrm, ref sib, EncodingPosition.Base, regIndex);
                            break;
                        case 5: // BP/R13
                            throw new Exception("this is weird");
                        default:
                            // check for scale, indexer, etc
                            PutValue(ref modrm, ref sib, EncodingPosition.RM, regIndex);
                            break;
                    }

                    if (offsetOffset.Immediate.Size == OperandSize.S8)
                    {
                        PutValue(ref modrm, ref sib, EncodingPosition.Mod, 1);
                        delayAdd = EncodeImmediate(offsetOffset.Immediate);
                    }
                    else if (offsetOffset.Immediate.Size == OperandSize.S32)
                    {
                        PutValue(ref modrm, ref sib, EncodingPosition.Mod, 2);
                        delayAdd = EncodeImmediate(offsetOffset.Immediate);
                    }
                    else
                        throw new Exception("Invalid memory offset size");
                }
                else if(addrOffset != null)
                {
                    PutValue(ref modrm, ref sib, EncodingPosition.Mod, 0);
                    PutValue(ref modrm, ref sib, EncodingPosition.RM, 5); // [disp32] maybe?
                    delayAdd = new List<AddressIndependentThing>() { AIF.Instance.Address(addrOffset.Label, addrOffset.Size == OperandSize.QWord) };
                }
            }
        }