예제 #1
0
 public Instruction(Mnemonic mnemonic, Operand? operand, byte opcode, int length)
 {
     this.Mnemonic = mnemonic;
     this.Operand = operand;
     this.Opcode = opcode;
     this.Length = length;
 }
예제 #2
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <param name="third">The third operand.</param>
        /// <returns></returns>
        protected override OpCode ComputeOpCode(Operand destination, Operand source, Operand third)
        {
            if ((destination is MemoryOperand) && (source is RegisterOperand))
            {
                if (IsByte(destination) || IsByte(source))
                    return M_R_8;
                if (IsChar(destination) || IsChar(source))
                    return M_R_16;
                return M_R;
            }

            if ((destination is RegisterOperand) && (source is MemoryOperand))
            {
                if (IsByte(source) || IsByte(destination))
                    return R_M_8;
                if (IsChar(source) || IsShort(source))
                    return R_M_16;
                return R_M;
            }

            if ((destination is RegisterOperand) && (source is RegisterOperand)) return R_R;
            if ((destination is MemoryOperand) && (source is ConstantOperand)) return M_C;
            if ((destination is RegisterOperand) && (source is ConstantOperand))
            {
                if (IsByte(source) || IsByte(destination))
                    return R_C_8;
                if (IsChar(source) || IsShort(source))
                    return R_C_16;
                return R_C;
            }

            throw new ArgumentException(String.Format(@"x86.CmpInstruction: No opcode for operand types {0} and {1}.", destination, source));
        }
예제 #3
0
파일: Operator.cs 프로젝트: katieyang/ToQ
 //FUNCTIONS
 void Awake()
 {
     base.initialize(); //this calls initialization stuff inside the Symbol class
     operand = transform.parent.GetComponent<Operand>(); //refernce to parent Operand
     Debug.Log("Operand: " + operand);
     _padding = 0;
 }
예제 #4
0
 public SafeCast(Operand op, Type t)
 {
     _op = op;
     _t = t;
     if (t.IsValueType)
         _conditional = _op.Is(_t).Conditional(_op.Cast(_t), new DefaultValue(_t));
 }
예제 #5
0
 public AssemblerInstruction(int line, Opcode opcode, Operand left, Operand right)
 {
     Line = line;
     Opcode = opcode;
     Left = left;
     Right = right;
 }
예제 #6
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <param name="third">The third operand.</param>
        /// <returns></returns>
        protected override OpCode ComputeOpCode(Operand destination, Operand source, Operand third)
        {
            if (destination is RegisterOperand)
                if ((destination as RegisterOperand).Register is ControlRegister) return CR_R;
                else if ((destination as RegisterOperand).Register is SegmentRegister)
                    throw new ArgumentException(@"TODO: No opcode for move to segment register");

            if (source is RegisterOperand)
                if ((source as RegisterOperand).Register is ControlRegister) return R_CR;
                else if ((source as RegisterOperand).Register is SegmentRegister)
                    throw new ArgumentException(@"TODO: No opcode for move from segment register");

            if ((destination is RegisterOperand) && (source is ConstantOperand)) return R_C;
            if ((destination is MemoryOperand) && (source is ConstantOperand)) return M_C;
            if ((destination is RegisterOperand) && (source is LabelOperand)) return R_C;
            if ((destination is MemoryOperand) && (source is LabelOperand)) return M_C;

            if ((destination is RegisterOperand) && (source is RegisterOperand)) {
                if (IsByte(source) || IsByte(destination)) return R_R_U8;
                if (IsChar(source) || IsChar(destination) || IsShort(source) || IsShort(destination)) return R_R_16;
                return R_R;
            }
            if ((destination is RegisterOperand) && (source is MemoryOperand)) {
                if (IsByte(destination)) return R_M_U8;
                if (IsChar(destination) || IsShort(destination)) return R_M_16;
                return R_M;
            }
            if ((destination is MemoryOperand) && (source is RegisterOperand)) {
                if (IsByte(destination)) return M_R_U8;
                if (IsChar(destination) || IsShort(destination)) return M_R_16;
                return M_R;
            }

            throw new ArgumentException(@"No opcode for operand type. [" + destination.GetType() + ", " + source.GetType() + ")");
        }
예제 #7
0
 /// <summary>
 /// Computes the opcode.
 /// </summary>
 /// <param name="destination">The destination operand.</param>
 /// <param name="source">The source operand.</param>
 /// <param name="third">The third operand.</param>
 /// <returns></returns>
 protected override OpCode ComputeOpCode(Operand destination, Operand source, Operand third)
 {
     if ((destination is RegisterOperand) && (source is LabelOperand)) return opcode;
     if ((destination is RegisterOperand) && (source is RegisterOperand)) return opcode;
     if ((destination is RegisterOperand) && (source is MemoryOperand)) return opcode;
     throw new ArgumentException(@"No opcode for operand type.");
 }
        static List<IExpression> _FillErUp(IEnumerable<IExpression> nodes, SymbolReader symbolReader)
        {
            var childrenForNextLevel = new List<IExpression>();

            foreach(var node in nodes)
            {
                if(symbolReader.IsEndOfSymbols())
                    break;

                var symbol = symbolReader.ReadNextSymbol();
                var theOperator = _GetOperator(symbol);
                node.SetLiteral(symbol);
                node.SetOperator(theOperator);

                var childrenToCreateCount = _GetNumberOfChildrenFor(theOperator);

                for(var i=0; i<childrenToCreateCount; i++)
                {
                    var operand = new Operand();
                    node.Add(operand);
                    childrenForNextLevel.Add(operand);
                }
            }

            return childrenForNextLevel;
        }
예제 #9
0
        /// <summary>
        /// Allows quick internal call replacements
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        /// <param name="internalMethod">The internal method to replace with.</param>
        /// <param name="internalClass">The internal class that has the internal method.</param>
        protected void Internal(Context context, BaseMethodCompiler methodCompiler, string internalMethod, string internalClass = "Internal")
        {
            if (context == null || methodCompiler == null || internalMethod == null || internalClass == null)
                throw new ArgumentNullException();

            var type = methodCompiler.TypeSystem.GetTypeByName("Mosa.Runtime", internalClass);
            Debug.Assert(type != null, "Cannot find Mosa.Runtime." + internalClass);

            var method = type.FindMethodByName(internalMethod);
            Debug.Assert(method != null, "Cannot find " + internalMethod + " in " + type.Name);

            Operand callTargetOperand = Operand.CreateSymbolFromMethod(methodCompiler.TypeSystem, method);

            var operands = new Operand[context.OperandCount];

            for (int i = 0; i < context.OperandCount; i++)
                operands[i] = context.GetOperand(i);

            Operand result = context.Result;

            context.SetInstruction(IRInstruction.Call, result, callTargetOperand);

            for (int i = 0; i < operands.Length; i++)
            {
                context.SetOperand(1 + i, operands[i]);
            }

            context.OperandCount = (byte)(1 + operands.Length);
            context.InvokeMethod = method;
        }
예제 #10
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <param name="third">The third operand.</param>
        /// <returns></returns>
        protected override OpCode ComputeOpCode(Operand destination, Operand source, Operand third)
        {
            if (!(destination is RegisterOperand))
                throw new ArgumentException(@"Destination must be RegisterOperand.", @"destination");
            if (source is ConstantOperand)
                throw new ArgumentException(@"Source must not be ConstantOperand.", @"source");

            switch (source.Type.Type) {
                case CilElementType.U1: goto case CilElementType.I1;
                case CilElementType.I1: {
                        if ((destination is RegisterOperand) && (source is RegisterOperand)) return R_X8;
                        if ((destination is RegisterOperand) && (source is MemoryOperand)) return R_X8;
                    }
                    break;
                case CilElementType.Char: goto case CilElementType.U2;
                case CilElementType.U2: goto case CilElementType.I2;
                case CilElementType.I2:
                    if ((destination is RegisterOperand) && (source is RegisterOperand)) return R_X16;
                    if ((destination is RegisterOperand) && (source is MemoryOperand)) return R_X16;
                    break;
                case CilElementType.Boolean: goto case CilElementType.I1;
                default:

                    break;
            }

            throw new ArgumentException(@"No opcode for operand type. [" + destination.GetType() + ", " + source.GetType() + ")");
        }
예제 #11
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <param name="third">The third operand.</param>
        /// <returns></returns>
        protected override OpCode ComputeOpCode(Operand destination, Operand source, Operand third)
        {
            if (source.Type.Type == Mosa.Runtime.Metadata.CilElementType.R4)
                return F;

            return I;
        }
예제 #12
0
		public NewDelegate(Type delegateType, Operand target, string methodName, ITypeMapper typeMapper)
		{
			_delegateType = delegateType;
			_target = target;
		    _typeMapper = typeMapper;
		    Initialize(target.GetReturnType(typeMapper), methodName);
		}
예제 #13
0
        /// <summary>
        /// Determines if this is a valid result operand of the instruction.
        /// </summary>
        /// <param name="resIdx">The result operand index to check.</param>
        /// <param name="op">The operand in use.</param>
        /// <returns>True if the used operand is valid or false, if it is not valid.</returns>
        public bool IsValidResult(int resIdx, Operand op)
        {
            if (!(op.StackType == StackTypeCode.F))
                return false;

            return (op is MemoryOperand || op is RegisterOperand);
        }
예제 #14
0
        /// <summary>
        /// Builds up an expression to divide the left operand by the right operand.
        /// </summary>
        /// <param name="left">The left operand.</param>
        /// <param name="right">The right operand.</param>
        /// <returns>The operand that consists of the expression to divide the left operand by the right operand.</returns>
        public override Operand Calculate(Operand left, Operand right)
        {
            Logger.Info("Dividing operands (left = '{0}', right = '{1}').", left.OperandType.FullName, right.OperandType.FullName);

            Operand result = null;

            var operands = new OperandPair(left, right);
            if (operands.Are(typeof(decimal)))
            {
                result = new Operand(Expression.Divide(left.Expression, right.Expression), typeof(decimal));
            }
            else
            {
                Warn("'{0}' doesn't support to divide '{1}' and '{2}'.", GetType().FullName, left.OperandType.FullName, right.OperandType.FullName);

                var l = Expression.Call(null, typeof(Convert).GetMethod("ToString", new Type[] { typeof(object) }), Expression.Convert(left.Expression, typeof(object)));
                var r = Expression.Call(null, typeof(Convert).GetMethod("ToString", new Type[] { typeof(object) }), Expression.Convert(right.Expression, typeof(object)));
                var method = typeof(string).GetMethod("Concat", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(string), typeof(string), typeof(string) }, null);
                result = new Operand(Expression.Call(null, method, l, Expression.Constant(Symbol), r), typeof(string));
            }

            Logger.Info("Divided operands (result = '{0}').", result.OperandType.FullName);

            return result;
        }
예제 #15
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <param name="third">The third operand.</param>
        /// <returns></returns>
        protected override OpCode ComputeOpCode(Operand destination, Operand source, Operand third)
        {
            if (destination == null || destination is RegisterOperand || destination is MemoryOperand)
                return DIV;

            throw new ArgumentException ("No opcode for operand type.");
        }
예제 #16
0
 public Instruction(Mnemonic mnemonic, Operand[] operands, byte[] opcode, int length)
 {
     this.Mnemonic = mnemonic;
     this.Operands = operands;
     this.Opcode = opcode;
     this.Length = length;
 }
예제 #17
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <param name="third">The third operand.</param>
        /// <returns></returns>
        protected override OpCode ComputeOpCode(Operand destination, Operand source, Operand third)
        {
            if ((destination is MemoryOperand) && (source is RegisterOperand))
            {
                if (IsByte (destination) || IsByte (source))
                    return M_R_8;
                if (IsChar (destination) || IsChar (source))
                    return M_R_16;
                return M_R;
            }

            if ((destination is RegisterOperand) && (source is MemoryOperand))
            {
                if (IsByte (source) || IsByte (destination))
                    return R_M_8;
                if (IsChar (source) || IsShort (source))
                    return R_M_16;
                return R_M;
            }

            if ((destination is RegisterOperand) && (source is RegisterOperand))
                return R_R;
            if ((destination is MemoryOperand) && (source is ConstantOperand))
                return M_C;
            if ((destination is RegisterOperand) && (source is ConstantOperand))
            {
                if (IsByte (source) || IsByte (destination))
                    return R_C_8;
                if (IsChar (source) || IsShort (source))
                    return R_C_16;
                return R_C;
            }
            throw new ArgumentException ("No opcode for operand type.");
        }
예제 #18
0
 public AssemblerInstruction()
 {
     Line = -1;
     Opcode = Opcode.None;
     Left = null;
     Right = null;
 }
 /// <summary>
 /// Determines whether the specified operand is 32 bits.
 /// </summary>
 /// <param name="operand">The operand.</param>
 /// <returns></returns>
 protected static bool Is32Bit(Operand operand)
 {
     return (operand.Type.Type == CilElementType.U4)
         || (operand.Type.Type == CilElementType.I4)
         || IsPointer(operand)
         || IsObject(operand);
 }
        void IIntrinsicSupport.EmitInstruction(InstructionCode code, Operand operand0, Operand operand1)
        {
            Contract.Requires(operand0 != null);
            Contract.Requires(operand1 != null);

            throw new NotImplementedException();
        }
예제 #21
0
        private void HandleMemoryToMemoryOperation(Context ctx, Operand register, bool useStack)
        {
            Operand destination = ctx.Result;
            Operand source = ctx.Operand1;

            Debug.Assert (destination is MemoryOperand && source is MemoryOperand);

            if (register == null)
                register = new RegisterOperand (destination.Type, GeneralPurposeRegister.EDX);

            ctx.Operand1 = register;

            Context before = ctx.InsertBefore ();

            if (useStack)
            {
                before.SetInstruction (CPUx86.Instruction.PushInstruction, null, register);
                before.AppendInstruction (CPUx86.Instruction.MovInstruction, register, source);
            }

            else
                before.SetInstruction (CPUx86.Instruction.MovInstruction, register, source);

            if (useStack)
                ctx.AppendInstruction (CPUx86.Instruction.PopInstruction, register);
        }
예제 #22
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <param name="third">The third operand.</param>
        /// <returns></returns>
        protected override OpCode ComputeOpCode(Operand destination, Operand source, Operand third)
        {
            //if (source.Type.Type == CilElementType.R4) return DIVSS;
            return opcode;

            //return DIVSD;
        }
예제 #23
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="destination"></param>
        /// <param name="source"></param>
        /// <param name="third"></param>
        /// <returns></returns>
        protected override OpCode ComputeOpCode(Operand destination, Operand source, Operand third)
        {
            if (source.Type.Type == CilElementType.R4)
                return R4;

            return R8;
        }
예제 #24
0
 public ConversationWrapper(Conversion conv, Operand op, Type @from, Type to)
 {
     _conv = conv;
     _op = op;
     _to = to;
     _from = @from;
 }
        /// <summary>
        /// This function emits a constant variable into the read-only data section.
        /// </summary>
        /// <param name="operand">The operand.</param>
        /// <returns>
        /// An operand, which represents the reference to the read-only constant.
        /// </returns>
        protected Operand EmitFloatingPointConstant(Operand operand)
        {
            if (!operand.IsConstant || !operand.IsR)
                return operand;

            int size, alignment;
            Architecture.GetTypeRequirements(TypeLayout, operand.Type, out size, out alignment);

            string name = String.Format("C_{0}", Guid.NewGuid());

            using (Stream stream = MethodCompiler.Linker.Allocate(name, SectionKind.ROData, size, alignment))
            {
                using (BinaryWriter writer = new BinaryWriter(stream))
                {
                    if (operand.IsR4)
                    {
                        writer.Write(operand.ConstantSingleFloatingPoint);
                    }
                    else if (operand.IsR8)
                    {
                        writer.Write(operand.ConstantDoubleFloatingPoint);
                    }
                }
            }

            return Operand.CreateLabel(operand.Type, name);
        }
예제 #26
0
        bool IRegisterConstraint.IsValidOperand(int opIdx, Operand op)
        {
            Debug.Assert(0 == opIdx, @"Only one operand supported.");
            if (opIdx > 0)
                throw new ArgumentOutOfRangeException(@"opIdx", opIdx, @"Only one operand supported.");

            return (op is ConstantOperand);
        }
예제 #27
0
	public override int Apply (Operand operand1, Operand operand2)
	{
		int solution = operand1.GetValue();
		for (int i = 1; i < operand2.GetValue(); i++) {
			solution *= operand1.GetValue();
		}
		return solution;
	}
		public ArrayLength(Operand array, bool asLong)
		{
			if (!array.Type.IsArray)
				throw new InvalidOperationException(Properties.Messages.ErrArrayOnly);

			this.array = array;
			this.asLong = asLong;
		}
예제 #29
0
        /// <summary>
        /// Computes the opcode.
        /// </summary>
        /// <param name="destination">The destination operand.</param>
        /// <param name="source">The source operand.</param>
        /// <param name="third">The third operand.</param>
        /// <returns></returns>
        protected override OpCode ComputeOpCode(Operand destination, Operand source, Operand third)
        {
            if (IsByte(destination)) return DEC8;
            if (IsShort(destination) || IsChar(destination)) return DEC16;
            if (IsInt(destination)) return DEC32;

            throw new ArgumentException(@"No opcode for operand type.");
        }
예제 #30
0
        /// <summary>
        /// Determines if this is a valid operand of the instruction.
        /// </summary>
        /// <param name="opIdx">The operand index to check.</param>
        /// <param name="op">The operand in use.</param>
        /// <returns>
        /// True if the used operand is valid or false, if it is not valid.
        /// </returns>
        public bool IsValidOperand(int opIdx, Operand op)
        {
            Debug.Assert(0 == opIdx, @"Invalid operand index.");
            if (opIdx == 0)
                throw new ArgumentOutOfRangeException(@"opIdx", opIdx, @"Only one operand supported. (Index 0)");

            return (op.StackType == StackTypeCode.F && (op is RegisterOperand || op is MemoryOperand));
        }
예제 #31
0
        public static void Suld(EmitterContext context)
        {
            context.Config.SetUsedFeature(FeatureFlags.IntegerSampling);

            OpCodeImage op = (OpCodeImage)context.CurrOp;

            SamplerType type = ConvertSamplerType(op.Dimensions);

            if (type == SamplerType.None)
            {
                context.Config.GpuAccessor.Log("Invalid image store sampler type.");

                return;
            }

            // Rb is Rd on the SULD instruction.
            int rdIndex = op.Rb.Index;
            int raIndex = op.Ra.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            List <Operand> sourcesList = new List <Operand>();

            if (op.IsBindless)
            {
                sourcesList.Add(context.Copy(Register(op.Rc)));
            }

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D)
            {
                sourcesList.Add(Const(0));

                type &= ~SamplerType.Mask;
                type |= SamplerType.Texture2D;
            }

            if (type.HasFlag(SamplerType.Array))
            {
                sourcesList.Add(Ra());

                type |= SamplerType.Array;
            }

            Operand[] sources = sourcesList.ToArray();

            int handle = !op.IsBindless ? op.HandleOffset : 0;

            TextureFlags flags = op.IsBindless ? TextureFlags.Bindless : TextureFlags.None;

            if (op.UseComponents)
            {
                int componentMask = (int)op.Components;

                for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
                {
                    if ((compMask & 1) == 0)
                    {
                        continue;
                    }

                    if (rdIndex == RegisterConsts.RegisterZeroIndex)
                    {
                        break;
                    }

                    Operand rd = Register(rdIndex++, RegisterType.Gpr);

                    TextureOperation operation = context.CreateTextureOperation(
                        Instruction.ImageLoad,
                        type,
                        flags,
                        handle,
                        compIndex,
                        rd,
                        sources);

                    if (!op.IsBindless)
                    {
                        operation.Format = context.Config.GetTextureFormat(handle);
                    }

                    context.Add(operation);
                }
            }
            else
            {
                if (op.ByteAddress)
                {
                    int xIndex = op.IsBindless ? 1 : 0;

                    sources[xIndex] = context.ShiftRightS32(sources[xIndex], Const(GetComponentSizeInBytesLog2(op.Size)));
                }

                int components = GetComponents(op.Size);

                for (int compIndex = 0; compIndex < components; compIndex++)
                {
                    if (rdIndex == RegisterConsts.RegisterZeroIndex)
                    {
                        break;
                    }

                    Operand rd = Register(rdIndex++, RegisterType.Gpr);

                    TextureOperation operation = context.CreateTextureOperation(
                        Instruction.ImageLoad,
                        type,
                        GetTextureFormat(op.Size),
                        flags,
                        handle,
                        compIndex,
                        rd,
                        sources);

                    context.Add(operation);

                    switch (op.Size)
                    {
                    case IntegerSize.U8:  context.Copy(rd, ZeroExtendTo32(context, rd, 8));  break;

                    case IntegerSize.U16: context.Copy(rd, ZeroExtendTo32(context, rd, 16)); break;

                    case IntegerSize.S8:  context.Copy(rd, SignExtendTo32(context, rd, 8));  break;

                    case IntegerSize.S16: context.Copy(rd, SignExtendTo32(context, rd, 16)); break;
                    }
                }
            }
        }
예제 #32
0
        public static void Iadd3(EmitterContext context)
        {
            OpCodeAlu op = (OpCodeAlu)context.CurrOp;

            IntegerHalfPart partC = (IntegerHalfPart)op.RawOpCode.Extract(31, 2);
            IntegerHalfPart partB = (IntegerHalfPart)op.RawOpCode.Extract(33, 2);
            IntegerHalfPart partA = (IntegerHalfPart)op.RawOpCode.Extract(35, 2);

            IntegerShift mode = (IntegerShift)op.RawOpCode.Extract(37, 2);

            bool negateC = op.RawOpCode.Extract(49);
            bool negateB = op.RawOpCode.Extract(50);
            bool negateA = op.RawOpCode.Extract(51);

            Operand Extend(Operand src, IntegerHalfPart part)
            {
                if (!(op is OpCodeAluReg) || part == IntegerHalfPart.B32)
                {
                    return(src);
                }

                if (part == IntegerHalfPart.H0)
                {
                    return(context.BitwiseAnd(src, Const(0xffff)));
                }
                else if (part == IntegerHalfPart.H1)
                {
                    return(context.ShiftRightU32(src, Const(16)));
                }
                else
                {
                    // TODO: Warning.
                }

                return(src);
            }

            Operand srcA = context.INegate(Extend(GetSrcA(context), partA), negateA);
            Operand srcB = context.INegate(Extend(GetSrcB(context), partB), negateB);
            Operand srcC = context.INegate(Extend(GetSrcC(context), partC), negateC);

            Operand res = context.IAdd(srcA, srcB);

            if (op is OpCodeAluReg && mode != IntegerShift.NoShift)
            {
                if (mode == IntegerShift.ShiftLeft)
                {
                    res = context.ShiftLeft(res, Const(16));
                }
                else if (mode == IntegerShift.ShiftRight)
                {
                    res = context.ShiftRightU32(res, Const(16));
                }
                else
                {
                    // TODO: Warning.
                }
            }

            res = context.IAdd(res, srcC);

            context.Copy(GetDest(context), res);

            // TODO: CC, X, corner cases
        }
예제 #33
0
        private static Operand GetIntComparisonExtended(
            EmitterContext context,
            IntegerCondition cond,
            Operand srcA,
            Operand srcB,
            bool isSigned)
        {
            Operand res;

            if (cond == IntegerCondition.Always)
            {
                res = Const(IrConsts.True);
            }
            else if (cond == IntegerCondition.Never)
            {
                res = Const(IrConsts.False);
            }
            else
            {
                res = context.ISubtract(srcA, srcB);
                res = context.IAdd(res, context.BitwiseNot(GetCF()));

                switch (cond)
                {
                case Decoders.IntegerCondition.Equal:     // r = xh == yh && xl == yl
                    res = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), GetZF());
                    break;

                case Decoders.IntegerCondition.Less:     // r = xh < yh || (xh == yh && xl < yl)
                    Operand notC   = context.BitwiseNot(GetCF());
                    Operand prevLt = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), notC);
                    res = isSigned
                            ? context.BitwiseOr(context.ICompareLess(srcA, srcB), prevLt)
                            : context.BitwiseOr(context.ICompareLessUnsigned(srcA, srcB), prevLt);
                    break;

                case Decoders.IntegerCondition.LessOrEqual:     // r = xh < yh || (xh == yh && xl <= yl)
                    Operand zOrNotC = context.BitwiseOr(GetZF(), context.BitwiseNot(GetCF()));
                    Operand prevLe  = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), zOrNotC);
                    res = isSigned
                            ? context.BitwiseOr(context.ICompareLess(srcA, srcB), prevLe)
                            : context.BitwiseOr(context.ICompareLessUnsigned(srcA, srcB), prevLe);
                    break;

                case Decoders.IntegerCondition.Greater:     // r = xh > yh || (xh == yh && xl > yl)
                    Operand notZAndC = context.BitwiseAnd(context.BitwiseNot(GetZF()), GetCF());
                    Operand prevGt   = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), notZAndC);
                    res = isSigned
                            ? context.BitwiseOr(context.ICompareGreater(srcA, srcB), prevGt)
                            : context.BitwiseOr(context.ICompareGreaterUnsigned(srcA, srcB), prevGt);
                    break;

                case Decoders.IntegerCondition.GreaterOrEqual:     // r = xh > yh || (xh == yh && xl >= yl)
                    Operand prevGe = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), GetCF());
                    res = isSigned
                            ? context.BitwiseOr(context.ICompareGreater(srcA, srcB), prevGe)
                            : context.BitwiseOr(context.ICompareGreaterUnsigned(srcA, srcB), prevGe);
                    break;

                case Decoders.IntegerCondition.NotEqual:     // r = xh != yh || xl != yl
                    context.BitwiseOr(context.ICompareNotEqual(srcA, srcB), context.BitwiseNot(GetZF()));
                    break;

                default:
                    throw new InvalidOperationException($"Unexpected condition \"{cond}\".");
                }
            }

            return(res);
        }
예제 #34
0
 public Conditional(Operand cond, Operand ifTrue, Operand ifFalse)
 {
     _cond    = cond;
     _ifTrue  = ifTrue;
     _ifFalse = ifFalse;
 }
 public JumpOnCarryCommand(Z80AssemblyParsing.Command sourceCommand, Operand operand) : base(sourceCommand, operand)
 {
 }
예제 #36
0
        public void LSL(Operand operand, ref DataStorage memory, ref DataStorage registers, ref int currentInstruction, int maxInstruction, ref Operand comparer)
        {
            //Ensure correct types for operand data
            ErrorManager.OperandCountMustBe(operand, 3, currentInstruction);
            ErrorManager.OperandMustBe(operand, 0, OperandType.Register, currentInstruction);
            ErrorManager.OperandMustBe(operand, 1, OperandType.Register, currentInstruction);

            //Fetch data and use bitwise or on casted data
            float firstArg  = GetData(operand.Values[1], memory, registers);
            float secondArg = GetData(operand.Values[2], memory, registers);
            float data      = (int)firstArg << (int)secondArg;

            //Set a register to that value
            registers.SetData((int)operand.Values[0].Value, data);
        }
예제 #37
0
 protected override object Evaluate(object context, EvaluationContext evalContext)
 {
     return(!Convert.ToBoolean(Operand.EvaluateInternal(context, evalContext)));
 }
예제 #38
0
 bool IRegisterConstraint.IsValidResult(int resIdx, Operand op)
 {
     throw new NotSupportedException();
 }
예제 #39
0
 /// <summary>
 /// Replaces the intrinsic call site
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="typeSystem">The type system.</param>
 void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
 {
     context.SetInstruction(IRInstruction.Move, context.Result, Operand.CreateUnmanagedSymbolPointer(methodCompiler.TypeSystem, Metadata.MethodLookupTable));
 }
예제 #40
0
 protected override void Setup()
 {
     Constant4 = CreateConstant(4);
 }
        protected BasicBlocks CopyInstructions()
        {
            var newBasicBlocks = new BasicBlocks();
            var mapBlocks      = new Dictionary <BasicBlock, BasicBlock>(BasicBlocks.Count);
            var map            = new Dictionary <Operand, Operand>();

            foreach (var block in BasicBlocks)
            {
                var newBlock = newBasicBlocks.CreateBlock(block.Label);
                mapBlocks.Add(block, newBlock);
            }

            var newPrologueBlock = newBasicBlocks.GetByLabel(BasicBlock.PrologueLabel);

            foreach (var operand in MethodCompiler.Parameters)
            {
                if (operand.Definitions.Count > 0)
                {
                    var newOp = Map(operand, map);

                    var newOperand = Operand.CreateVirtualRegister(operand.Type, -operand.Index);

                    newPrologueBlock.BeforeLast.Insert(new InstructionNode(IRInstruction.Move, newOperand, newOp));

                    // redirect map from parameter to virtual register going forward
                    map.Remove(operand);
                    map.Add(operand, newOperand);
                }
            }

            foreach (var block in BasicBlocks)
            {
                var newBlock = newBasicBlocks.GetByLabel(block.Label);

                for (var node = block.First.Next; !node.IsBlockEndInstruction; node = node.Next)
                {
                    if (node.IsEmpty)
                    {
                        continue;
                    }

                    var newNode = new InstructionNode(node.Instruction, node.OperandCount, node.ResultCount);
                    newNode.Size          = node.Size;
                    newNode.ConditionCode = node.ConditionCode;

                    if (node.BranchTargets != null)
                    {
                        // copy targets
                        foreach (var target in node.BranchTargets)
                        {
                            newNode.AddBranchTarget(mapBlocks[target]);
                        }
                    }

                    // copy results
                    for (int i = 0; i < node.ResultCount; i++)
                    {
                        var op = node.GetResult(i);

                        var newOp = Map(op, map);

                        newNode.SetResult(i, newOp);
                    }

                    // copy operands
                    for (int i = 0; i < node.OperandCount; i++)
                    {
                        var op = node.GetOperand(i);

                        var newOp = Map(op, map);

                        newNode.SetOperand(i, newOp);
                    }

                    // copy other
                    if (node.MosaType != null)
                    {
                        newNode.MosaType = node.MosaType;
                    }
                    if (node.MosaField != null)
                    {
                        newNode.MosaField = node.MosaField;
                    }
                    if (node.InvokeMethod != null)
                    {
                        newNode.InvokeMethod = node.InvokeMethod;
                    }

                    newBlock.BeforeLast.Insert(newNode);
                }
            }

            var trace = CreateTraceLog("InlineMap");

            if (trace.Active)
            {
                foreach (var entry in map)
                {
                    trace.Log(entry.Value.ToString() + " from: " + entry.Key.ToString());
                }
            }

            return(newBasicBlocks);
        }
예제 #42
0
        private static void EmitTextureSample(EmitterContext context, TextureFlags flags)
        {
            OpCodeTexture op = (OpCodeTexture)context.CurrOp;

            bool isBindless = (flags & TextureFlags.Bindless) != 0;

            if (op.Rd.IsRZ)
            {
                return;
            }

            int raIndex = op.Ra.Index;
            int rbIndex = op.Rb.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (rbIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(rbIndex++, RegisterType.Gpr)));
            }

            Operand arrayIndex = op.IsArray ? Ra() : null;

            List <Operand> sourcesList = new List <Operand>();

            if (isBindless)
            {
                sourcesList.Add(Rb());
            }

            SamplerType type = ConvertSamplerType(op.Dimensions);

            bool hasLod = op.LodMode > TextureLodMode.LodZero;

            if (type == SamplerType.Texture1D && (flags & ~TextureFlags.Bindless) == TextureFlags.IntCoords && !(hasLod ||
                                                                                                                 op.HasDepthCompare ||
                                                                                                                 op.HasOffset ||
                                                                                                                 op.IsArray ||
                                                                                                                 op.IsMultisample))
            {
                // For bindless, we don't have any way to know the texture type,
                // so we assume it's texture buffer when the sampler type is 1D, since that's more common.
                bool isTypeBuffer = isBindless || context.Config.GpuAccessor.QueryIsTextureBuffer(op.HandleOffset);

                if (isTypeBuffer)
                {
                    type = SamplerType.TextureBuffer;
                }
            }

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            if (Sample1DAs2D && type == SamplerType.Texture1D)
            {
                sourcesList.Add(ConstF(0));

                type = SamplerType.Texture2D;
            }

            if (op.IsArray)
            {
                sourcesList.Add(arrayIndex);

                type |= SamplerType.Array;
            }

            Operand lodValue = hasLod ? Rb() : ConstF(0);

            Operand packedOffs = op.HasOffset ? Rb() : null;

            if (op.HasDepthCompare)
            {
                sourcesList.Add(Rb());

                type |= SamplerType.Shadow;
            }

            if ((op.LodMode == TextureLodMode.LodZero ||
                 op.LodMode == TextureLodMode.LodLevel ||
                 op.LodMode == TextureLodMode.LodLevelA) && !op.IsMultisample && type != SamplerType.TextureBuffer)
            {
                sourcesList.Add(lodValue);

                flags |= TextureFlags.LodLevel;
            }

            if (op.HasOffset)
            {
                for (int index = 0; index < coordsCount; index++)
                {
                    sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * 4), Const(4)));
                }

                flags |= TextureFlags.Offset;
            }

            if (op.LodMode == TextureLodMode.LodBias ||
                op.LodMode == TextureLodMode.LodBiasA)
            {
                sourcesList.Add(lodValue);

                flags |= TextureFlags.LodBias;
            }

            if (op.IsMultisample)
            {
                sourcesList.Add(Rb());

                type |= SamplerType.Multisample;
            }

            Operand[] sources = sourcesList.ToArray();

            int rdIndex = op.Rd.Index;

            Operand GetDest()
            {
                if (rdIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(Register(rdIndex++, RegisterType.Gpr));
            }

            int handle = !isBindless ? op.HandleOffset : 0;

            for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
            {
                if ((compMask & 1) != 0)
                {
                    Operand dest = GetDest();

                    TextureOperation operation = context.CreateTextureOperation(
                        Instruction.TextureSample,
                        type,
                        flags,
                        handle,
                        compIndex,
                        dest,
                        sources);

                    context.Add(operation);
                }
            }
        }
예제 #43
0
        private static void EmitTextureQuery(EmitterContext context, bool bindless)
        {
            OpCodeTex op = (OpCodeTex)context.CurrOp;

            if (op.Rd.IsRZ)
            {
                return;
            }

            TextureProperty property = (TextureProperty)op.RawOpCode.Extract(22, 6);

            // TODO: Validate and use property.
            Instruction inst = Instruction.TextureSize;

            SamplerType type = SamplerType.Texture2D;

            TextureFlags flags = bindless ? TextureFlags.Bindless : TextureFlags.None;

            int raIndex = op.Ra.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            List <Operand> sourcesList = new List <Operand>();

            if (bindless)
            {
                sourcesList.Add(Ra());
            }

            sourcesList.Add(Ra());

            Operand[] sources = sourcesList.ToArray();

            int rdIndex = op.Rd.Index;

            Operand GetDest()
            {
                if (rdIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(Register(rdIndex++, RegisterType.Gpr));
            }

            int handle = !bindless ? op.HandleOffset : 0;

            for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
            {
                if ((compMask & 1) != 0)
                {
                    Operand dest = GetDest();

                    TextureOperation operation = context.CreateTextureOperation(
                        inst,
                        type,
                        flags,
                        handle,
                        compIndex,
                        dest,
                        sources);

                    context.Add(operation);
                }
            }
        }
예제 #44
0
        protected override void ExecuteInternal(ICpu cpu, IMemory _, Operand op0, Operand op1, Operand op2)
        {
            var condition = (Condition)op0.Value.ToUInt();

            if (IsConditionTrue(condition, op1.Value, Word.Zero))
            {
                cpu.InstructionPointer = op2.Value;
            }
        }
예제 #45
0
 public override string ToStr()
 {
     return("avg(" + Operand.ToStr() + ")");
 }
예제 #46
0
 /// <summary>
 /// Requests the calling convention to create an appropriate move instruction to populate the return
 /// value of a method.
 /// </summary>
 /// <param name="compiler">The compiler.</param>
 /// <param name="context">The context.</param>
 /// <param name="operand">The operand, that's holding the return value.</param>
 public abstract void SetReturnValue(BaseMethodCompiler compiler, Context context, Operand operand);
예제 #47
0
 public override string ToSql(ExpressionSqlBuilder builder)
 {
     return(" avg(" + Operand.ToSql(builder) + ")");
 }
예제 #48
0
        public static void Txd(EmitterContext context)
        {
            OpCodeTxd op = (OpCodeTxd)context.CurrOp;

            if (op.Rd.IsRZ)
            {
                return;
            }

            int raIndex = op.Ra.Index;
            int rbIndex = op.Rb.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (rbIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(rbIndex++, RegisterType.Gpr)));
            }

            TextureFlags flags = TextureFlags.Derivatives;

            List <Operand> sourcesList = new List <Operand>();

            if (op.IsBindless)
            {
                sourcesList.Add(Ra());

                flags |= TextureFlags.Bindless;
            }

            SamplerType type = ConvertSamplerType(op.Dimensions);

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            bool is1DTo2D = Sample1DAs2D && type == SamplerType.Texture1D;

            if (is1DTo2D)
            {
                sourcesList.Add(ConstF(0));

                type = SamplerType.Texture2D;
            }

            Operand packedParams = Ra();

            if (op.IsArray)
            {
                sourcesList.Add(context.BitwiseAnd(packedParams, Const(0xffff)));

                type |= SamplerType.Array;
            }

            // Derivatives (X and Y).
            for (int dIndex = 0; dIndex < 2 * coordsCount; dIndex++)
            {
                sourcesList.Add(Rb());

                if (is1DTo2D)
                {
                    sourcesList.Add(ConstF(0));
                }
            }

            if (op.HasOffset)
            {
                for (int index = 0; index < coordsCount; index++)
                {
                    sourcesList.Add(context.BitfieldExtractS32(packedParams, Const(16 + index * 4), Const(4)));
                }

                if (is1DTo2D)
                {
                    sourcesList.Add(Const(0));
                }

                flags |= TextureFlags.Offset;
            }

            Operand[] sources = sourcesList.ToArray();

            int rdIndex = op.Rd.Index;

            Operand GetDest()
            {
                if (rdIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(Register(rdIndex++, RegisterType.Gpr));
            }

            int handle = !op.IsBindless ? op.HandleOffset : 0;

            for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
            {
                if ((compMask & 1) != 0)
                {
                    Operand dest = GetDest();

                    TextureOperation operation = context.CreateTextureOperation(
                        Instruction.TextureSample,
                        type,
                        flags,
                        handle,
                        compIndex,
                        dest,
                        sources);

                    context.Add(operation);
                }
            }
        }
예제 #49
0
        public static void Xmad(EmitterContext context)
        {
            OpCodeAlu op = (OpCodeAlu)context.CurrOp;

            bool signedA = context.CurrOp.RawOpCode.Extract(48);
            bool signedB = context.CurrOp.RawOpCode.Extract(49);
            bool highA   = context.CurrOp.RawOpCode.Extract(53);

            bool isReg = (op is OpCodeAluReg) && !(op is OpCodeAluRegCbuf);
            bool isImm = (op is OpCodeAluImm);

            XmadCMode mode = isReg || isImm
                ? (XmadCMode)context.CurrOp.RawOpCode.Extract(50, 3)
                : (XmadCMode)context.CurrOp.RawOpCode.Extract(50, 2);

            bool highB = false;

            if (isReg)
            {
                highB = context.CurrOp.RawOpCode.Extract(35);
            }
            else if (!isImm)
            {
                highB = context.CurrOp.RawOpCode.Extract(52);
            }

            Operand srcA = GetSrcA(context);
            Operand srcB = GetSrcB(context);
            Operand srcC = GetSrcC(context);

            // XMAD immediates are 16-bits unsigned integers.
            if (srcB.Type == OperandType.Constant)
            {
                srcB = Const(srcB.Value & 0xffff);
            }

            Operand Extend16To32(Operand src, bool high, bool signed)
            {
                if (signed && high)
                {
                    return(context.ShiftRightS32(src, Const(16)));
                }
                else if (signed)
                {
                    return(context.BitfieldExtractS32(src, Const(0), Const(16)));
                }
                else if (high)
                {
                    return(context.ShiftRightU32(src, Const(16)));
                }
                else
                {
                    return(context.BitwiseAnd(src, Const(0xffff)));
                }
            }

            srcA = Extend16To32(srcA, highA, signedA);
            srcB = Extend16To32(srcB, highB, signedB);

            bool productShiftLeft = false;
            bool merge            = false;

            if (op is OpCodeAluCbuf)
            {
                productShiftLeft = context.CurrOp.RawOpCode.Extract(55);
                merge            = context.CurrOp.RawOpCode.Extract(56);
            }
            else if (!(op is OpCodeAluRegCbuf))
            {
                productShiftLeft = context.CurrOp.RawOpCode.Extract(36);
                merge            = context.CurrOp.RawOpCode.Extract(37);
            }

            bool extended;

            if ((op is OpCodeAluReg) || (op is OpCodeAluImm))
            {
                extended = context.CurrOp.RawOpCode.Extract(38);
            }
            else
            {
                extended = context.CurrOp.RawOpCode.Extract(54);
            }

            Operand res = context.IMultiply(srcA, srcB);

            if (productShiftLeft)
            {
                res = context.ShiftLeft(res, Const(16));
            }

            switch (mode)
            {
            case XmadCMode.Cfull: break;

            case XmadCMode.Clo: srcC = Extend16To32(srcC, high: false, signed: false); break;

            case XmadCMode.Chi: srcC = Extend16To32(srcC, high: true, signed: false); break;

            case XmadCMode.Cbcc:
            {
                srcC = context.IAdd(srcC, context.ShiftLeft(GetSrcB(context), Const(16)));

                break;
            }

            case XmadCMode.Csfu:
            {
                Operand signAdjustA = context.ShiftLeft(context.ShiftRightU32(srcA, Const(31)), Const(16));
                Operand signAdjustB = context.ShiftLeft(context.ShiftRightU32(srcB, Const(31)), Const(16));

                srcC = context.ISubtract(srcC, context.IAdd(signAdjustA, signAdjustB));

                break;
            }

            default: /* TODO: Warning */ break;
            }

            Operand product = res;

            if (extended)
            {
                // Add with carry.
                res = context.IAdd(res, context.BitwiseAnd(GetCF(), Const(1)));
            }
            else
            {
                // Add (no carry in).
                res = context.IAdd(res, srcC);
            }

            SetIaddFlags(context, res, product, srcC, op.SetCondCode, extended);

            if (merge)
            {
                res = context.BitwiseAnd(res, Const(0xffff));
                res = context.BitwiseOr(res, context.ShiftLeft(GetSrcB(context), Const(16)));
            }

            context.Copy(GetDest(context), res);
        }
예제 #50
0
        private static void EmitTextureMipMapLevel(EmitterContext context, bool isBindless)
        {
            OpCodeTexture op = (OpCodeTexture)context.CurrOp;

            if (op.Rd.IsRZ)
            {
                return;
            }

            int raIndex = op.Ra.Index;
            int rbIndex = op.Rb.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (rbIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(rbIndex++, RegisterType.Gpr)));
            }

            TextureFlags flags = TextureFlags.None;

            List <Operand> sourcesList = new List <Operand>();

            if (isBindless)
            {
                sourcesList.Add(Rb());

                flags |= TextureFlags.Bindless;
            }

            SamplerType type = ConvertSamplerType(op.Dimensions);

            int coordsCount = type.GetDimensions();

            Operand arrayIndex = op.IsArray ? Ra() : null;

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            if (Sample1DAs2D && type == SamplerType.Texture1D)
            {
                sourcesList.Add(ConstF(0));

                type = SamplerType.Texture2D;
            }

            if (op.IsArray)
            {
                sourcesList.Add(arrayIndex);

                type |= SamplerType.Array;
            }

            Operand[] sources = sourcesList.ToArray();

            int rdIndex = op.Rd.Index;

            Operand GetDest()
            {
                if (rdIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(Register(rdIndex++, RegisterType.Gpr));
            }

            int handle = !isBindless ? op.HandleOffset : 0;

            for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
            {
                if ((compMask & 1) != 0)
                {
                    Operand dest = GetDest();

                    // Components z and w aren't standard, we return 0 in this case and add a comment.
                    if (compIndex >= 2)
                    {
                        context.Add(new CommentNode("Unsupported component z or w found"));
                        context.Copy(dest, Const(0));
                    }
                    else
                    {
                        Operand tempDest = Local();

                        TextureOperation operation = context.CreateTextureOperation(
                            Instruction.Lod,
                            type,
                            flags,
                            handle,
                            compIndex,
                            tempDest,
                            sources);

                        context.Add(operation);

                        tempDest = context.FPMultiply(tempDest, ConstF(256.0f));

                        Operand finalValue = context.FPConvertToS32(tempDest);

                        context.Copy(dest, finalValue);
                    }
                }
            }
        }
예제 #51
0
        public static void Tld4(EmitterContext context)
        {
            IOpCodeTld4 op = (IOpCodeTld4)context.CurrOp;

            if (op.Rd.IsRZ)
            {
                return;
            }

            int raIndex = op.Ra.Index;
            int rbIndex = op.Rb.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (rbIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(rbIndex++, RegisterType.Gpr)));
            }

            Operand arrayIndex = op.IsArray ? Ra() : null;

            List <Operand> sourcesList = new List <Operand>();

            SamplerType  type  = ConvertSamplerType(op.Dimensions);
            TextureFlags flags = TextureFlags.Gather;

            if (op.Bindless)
            {
                sourcesList.Add(Rb());

                flags |= TextureFlags.Bindless;
            }

            int coordsCount = type.GetDimensions();

            for (int index = 0; index < coordsCount; index++)
            {
                sourcesList.Add(Ra());
            }

            bool is1DTo2D = Sample1DAs2D && type == SamplerType.Texture1D;

            if (is1DTo2D)
            {
                sourcesList.Add(ConstF(0));

                type = SamplerType.Texture2D;
            }

            if (op.IsArray)
            {
                sourcesList.Add(arrayIndex);

                type |= SamplerType.Array;
            }

            Operand[] packedOffs = new Operand[2];

            packedOffs[0] = op.Offset != TextureGatherOffset.None    ? Rb() : null;
            packedOffs[1] = op.Offset == TextureGatherOffset.Offsets ? Rb() : null;

            if (op.HasDepthCompare)
            {
                sourcesList.Add(Rb());

                type |= SamplerType.Shadow;
            }

            if (op.Offset != TextureGatherOffset.None)
            {
                int offsetTexelsCount = op.Offset == TextureGatherOffset.Offsets ? 4 : 1;

                for (int index = 0; index < coordsCount * offsetTexelsCount; index++)
                {
                    Operand packed = packedOffs[(index >> 2) & 1];

                    sourcesList.Add(context.BitfieldExtractS32(packed, Const((index & 3) * 8), Const(6)));
                }

                if (is1DTo2D)
                {
                    for (int index = 0; index < offsetTexelsCount; index++)
                    {
                        sourcesList.Add(Const(0));
                    }
                }

                flags |= op.Offset == TextureGatherOffset.Offsets
                    ? TextureFlags.Offsets
                    : TextureFlags.Offset;
            }

            sourcesList.Add(Const(op.GatherCompIndex));

            Operand[] sources = sourcesList.ToArray();

            int rdIndex = op.Rd.Index;

            Operand GetDest()
            {
                if (rdIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(Register(rdIndex++, RegisterType.Gpr));
            }

            int handle = op.HandleOffset;

            for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
            {
                if ((compMask & 1) != 0)
                {
                    Operand dest = GetDest();

                    TextureOperation operation = context.CreateTextureOperation(
                        Instruction.TextureSample,
                        type,
                        flags,
                        handle,
                        compIndex,
                        dest,
                        sources);

                    context.Add(operation);
                }
            }
        }
예제 #52
0
        public static void Texs(EmitterContext context)
        {
            OpCodeTextureScalar op = (OpCodeTextureScalar)context.CurrOp;

            if (op.Rd0.IsRZ && op.Rd1.IsRZ)
            {
                return;
            }

            List <Operand> sourcesList = new List <Operand>();

            int raIndex = op.Ra.Index;
            int rbIndex = op.Rb.Index;

            Operand Ra()
            {
                if (raIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(raIndex++, RegisterType.Gpr)));
            }

            Operand Rb()
            {
                if (rbIndex > RegisterConsts.RegisterZeroIndex)
                {
                    return(Const(0));
                }

                return(context.Copy(Register(rbIndex++, RegisterType.Gpr)));
            }

            void AddTextureOffset(int coordsCount, int stride, int size)
            {
                Operand packedOffs = Rb();

                for (int index = 0; index < coordsCount; index++)
                {
                    sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * stride), Const(size)));
                }
            }

            SamplerType  type;
            TextureFlags flags;

            if (op is OpCodeTexs texsOp)
            {
                type = ConvertSamplerType(texsOp.Target);

                if (type == SamplerType.None)
                {
                    context.Config.GpuAccessor.Log("Invalid texture sampler type.");

                    return;
                }

                flags = ConvertTextureFlags(texsOp.Target);

                // We don't need to handle 1D -> Buffer conversions here as
                // only texture sample with integer coordinates can ever use buffer targets.

                if ((type & SamplerType.Array) != 0)
                {
                    Operand arrayIndex = Ra();

                    sourcesList.Add(Ra());
                    sourcesList.Add(Rb());

                    sourcesList.Add(arrayIndex);

                    if ((type & SamplerType.Shadow) != 0)
                    {
                        sourcesList.Add(Rb());
                    }

                    if ((flags & TextureFlags.LodLevel) != 0)
                    {
                        sourcesList.Add(ConstF(0));
                    }
                }
                else
                {
                    switch (texsOp.Target)
                    {
                    case TextureTarget.Texture1DLodZero:
                        sourcesList.Add(Ra());

                        if (Sample1DAs2D)
                        {
                            sourcesList.Add(ConstF(0));

                            type &= ~SamplerType.Mask;
                            type |= SamplerType.Texture2D;
                        }

                        sourcesList.Add(ConstF(0));
                        break;

                    case TextureTarget.Texture2D:
                        sourcesList.Add(Ra());
                        sourcesList.Add(Rb());
                        break;

                    case TextureTarget.Texture2DLodZero:
                        sourcesList.Add(Ra());
                        sourcesList.Add(Rb());
                        sourcesList.Add(ConstF(0));
                        break;

                    case TextureTarget.Texture2DLodLevel:
                    case TextureTarget.Texture2DDepthCompare:
                    case TextureTarget.Texture3D:
                    case TextureTarget.TextureCube:
                        sourcesList.Add(Ra());
                        sourcesList.Add(Ra());
                        sourcesList.Add(Rb());
                        break;

                    case TextureTarget.Texture2DLodZeroDepthCompare:
                    case TextureTarget.Texture3DLodZero:
                        sourcesList.Add(Ra());
                        sourcesList.Add(Ra());
                        sourcesList.Add(Rb());
                        sourcesList.Add(ConstF(0));
                        break;

                    case TextureTarget.Texture2DLodLevelDepthCompare:
                    case TextureTarget.TextureCubeLodLevel:
                        sourcesList.Add(Ra());
                        sourcesList.Add(Ra());
                        sourcesList.Add(Rb());
                        sourcesList.Add(Rb());
                        break;
                    }
                }
            }
            else if (op is OpCodeTlds tldsOp)
            {
                type = ConvertSamplerType(tldsOp.Target);

                if (type == SamplerType.None)
                {
                    context.Config.GpuAccessor.Log("Invalid texel fetch sampler type.");

                    return;
                }

                context.Config.SetUsedFeature(FeatureFlags.IntegerSampling);

                flags = ConvertTextureFlags(tldsOp.Target) | TextureFlags.IntCoords;

                if (tldsOp.Target == TexelLoadTarget.Texture1DLodZero && context.Config.GpuAccessor.QueryIsTextureBuffer(tldsOp.HandleOffset))
                {
                    type   = SamplerType.TextureBuffer;
                    flags &= ~TextureFlags.LodLevel;
                }

                switch (tldsOp.Target)
                {
                case TexelLoadTarget.Texture1DLodZero:
                    sourcesList.Add(Ra());

                    if (type != SamplerType.TextureBuffer)
                    {
                        if (Sample1DAs2D)
                        {
                            sourcesList.Add(ConstF(0));

                            type &= ~SamplerType.Mask;
                            type |= SamplerType.Texture2D;
                        }

                        sourcesList.Add(ConstF(0));
                    }
                    break;

                case TexelLoadTarget.Texture1DLodLevel:
                    sourcesList.Add(Ra());

                    if (Sample1DAs2D)
                    {
                        sourcesList.Add(ConstF(0));

                        type &= ~SamplerType.Mask;
                        type |= SamplerType.Texture2D;
                    }

                    sourcesList.Add(Rb());
                    break;

                case TexelLoadTarget.Texture2DLodZero:
                    sourcesList.Add(Ra());
                    sourcesList.Add(Rb());
                    sourcesList.Add(Const(0));
                    break;

                case TexelLoadTarget.Texture2DLodZeroOffset:
                    sourcesList.Add(Ra());
                    sourcesList.Add(Ra());
                    sourcesList.Add(Const(0));
                    break;

                case TexelLoadTarget.Texture2DLodZeroMultisample:
                case TexelLoadTarget.Texture2DLodLevel:
                case TexelLoadTarget.Texture2DLodLevelOffset:
                    sourcesList.Add(Ra());
                    sourcesList.Add(Ra());
                    sourcesList.Add(Rb());
                    break;

                case TexelLoadTarget.Texture3DLodZero:
                    sourcesList.Add(Ra());
                    sourcesList.Add(Ra());
                    sourcesList.Add(Rb());
                    sourcesList.Add(Const(0));
                    break;

                case TexelLoadTarget.Texture2DArrayLodZero:
                    sourcesList.Add(Rb());
                    sourcesList.Add(Rb());
                    sourcesList.Add(Ra());
                    sourcesList.Add(Const(0));
                    break;
                }

                if ((flags & TextureFlags.Offset) != 0)
                {
                    AddTextureOffset(type.GetDimensions(), 4, 4);
                }
            }
            else if (op is OpCodeTld4s tld4sOp)
            {
                if (!(tld4sOp.HasDepthCompare || tld4sOp.HasOffset))
                {
                    sourcesList.Add(Ra());
                    sourcesList.Add(Rb());
                }
                else
                {
                    sourcesList.Add(Ra());
                    sourcesList.Add(Ra());
                }

                type  = SamplerType.Texture2D;
                flags = TextureFlags.Gather;

                if (tld4sOp.HasDepthCompare)
                {
                    sourcesList.Add(Rb());

                    type |= SamplerType.Shadow;
                }

                if (tld4sOp.HasOffset)
                {
                    AddTextureOffset(type.GetDimensions(), 8, 6);

                    flags |= TextureFlags.Offset;
                }

                sourcesList.Add(Const(tld4sOp.GatherCompIndex));
            }
            else
            {
                throw new InvalidOperationException($"Invalid opcode type \"{op.GetType().Name}\".");
            }

            Operand[] sources = sourcesList.ToArray();

            Operand[] rd0 = new Operand[2] {
                ConstF(0), ConstF(0)
            };
            Operand[] rd1 = new Operand[2] {
                ConstF(0), ConstF(0)
            };

            int destIncrement = 0;

            Operand GetDest()
            {
                int high = destIncrement >> 1;
                int low  = destIncrement & 1;

                destIncrement++;

                if (op.IsFp16)
                {
                    return(high != 0
                        ? (rd1[low] = Local())
                        : (rd0[low] = Local()));
                }
                else
                {
                    int rdIndex = high != 0 ? op.Rd1.Index : op.Rd0.Index;

                    if (rdIndex < RegisterConsts.RegisterZeroIndex)
                    {
                        rdIndex += low;
                    }

                    return(Register(rdIndex, RegisterType.Gpr));
                }
            }

            int handle = op.HandleOffset;

            for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
            {
                if ((compMask & 1) != 0)
                {
                    Operand dest = GetDest();

                    TextureOperation operation = context.CreateTextureOperation(
                        Instruction.TextureSample,
                        type,
                        flags,
                        handle,
                        compIndex,
                        dest,
                        sources);

                    context.Add(operation);
                }
            }

            if (op.IsFp16)
            {
                context.Copy(Register(op.Rd0), context.PackHalf2x16(rd0[0], rd0[1]));
                context.Copy(Register(op.Rd1), context.PackHalf2x16(rd1[0], rd1[1]));
            }
        }
예제 #53
0
파일: Task.cs 프로젝트: svejdo1/Euler
        public string Run()
        {
            var indexes = new List <byte[]>();

            MathUtility.GetPermutations(new byte[] { 0, 1, 2, 3 }, indexes);

            int    max      = 0;
            string solution = null;

            bool[] buffer   = new bool[9 * 8 * 7 * 6 + 1];
            var    operands = new Operand[] { Operand.Add, Operand.Divide, Operand.Multiply, Operand.Substract };
            var    trees    = BuildTrees();

            for (var a = 1; a < 10; a++)
            {
                for (var b = a + 1; b < 10; b++)
                {
                    for (var c = b + 1; c < 10; c++)
                    {
                        for (var d = c + 1; d < 10; d++)
                        {
                            Array.Clear(buffer, 0, buffer.Length);
                            foreach (var tree in trees)
                            {
                                foreach (var index in indexes)
                                {
                                    tree.Terms[index[0]].Value = new Rational <long, Int64Policy>(a, 1);
                                    tree.Terms[index[1]].Value = new Rational <long, Int64Policy>(b, 1);
                                    tree.Terms[index[2]].Value = new Rational <long, Int64Policy>(c, 1);
                                    tree.Terms[index[3]].Value = new Rational <long, Int64Policy>(d, 1);

                                    foreach (var o1 in operands)
                                    {
                                        foreach (var o2 in operands)
                                        {
                                            foreach (var o3 in operands)
                                            {
                                                tree.Operands[0].Operand = o1;
                                                tree.Operands[1].Operand = o2;
                                                tree.Operands[2].Operand = o3;
                                                var result = tree.Root.Evaluate();
                                                if (result.HasValue)
                                                {
                                                    var term = result.Value.Normalize();
                                                    if (term.Denominator == 1 && term.Numerator >= 0)
                                                    {
                                                        buffer[term.Numerator] = true;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            int i = 1;
                            while (buffer[i++])
                            {
                                ;
                            }
                            if (i > max)
                            {
                                solution = string.Format("{0}{1}{2}{3}", a, b, c, d);
                                max      = i;
                            }
                        }
                    }
                }
            }
            return(solution);
        }
        private static Operand Map(Operand operand, Dictionary <Operand, Operand> map)
        {
            if (operand == null)
            {
                return(null);
            }

            Operand mappedOperand;

            if (map.TryGetValue(operand, out mappedOperand))
            {
                return(mappedOperand);
            }

            if (operand.IsSymbol)
            {
                if (operand.StringData != null)
                {
                    mappedOperand = Operand.CreateStringSymbol(operand.Type.TypeSystem, operand.Name, operand.StringData);
                }
                else if (operand.Method != null)
                {
                    mappedOperand = Operand.CreateSymbolFromMethod(operand.Type.TypeSystem, operand.Method);
                }
                else if (operand.Name != null)
                {
                    mappedOperand = Operand.CreateManagedSymbol(operand.Type, operand.Name);
                }
            }
            else if (operand.IsParameter)
            {
                mappedOperand = operand;
            }
            else if (operand.IsStackLocal)
            {
                mappedOperand = Operand.CreateStackLocal(operand.Type, operand.Register, operand.Index);
            }
            else if (operand.IsVirtualRegister)
            {
                if (operand.Uses.Count != 0 || operand.Definitions.Count != 0)
                {
                    mappedOperand = Operand.CreateVirtualRegister(operand.Type, operand.Index, operand.Name);
                }
            }
            else if (operand.IsField)
            {
                mappedOperand = Operand.CreateField(operand.Field);
            }
            else if (operand.IsConstant)
            {
                mappedOperand = operand;
            }
            else if (operand.IsCPURegister)
            {
                mappedOperand = operand;
            }

            Debug.Assert(mappedOperand != null);

            map.Add(operand, mappedOperand);

            return(mappedOperand);
        }