Esempio n. 1
0
        private static void EmitLoadEx(ArmEmitterContext context, AccessType accType, bool pair)
        {
            OpCodeMemEx op = (OpCodeMemEx)context.CurrOp;

            bool ordered   = (accType & AccessType.Ordered) != 0;
            bool exclusive = (accType & AccessType.Exclusive) != 0;

            Operand address = context.Copy(GetIntOrSP(context, op.Rn));

            if (pair)
            {
                // Exclusive loads should be atomic. For pairwise loads, we need to
                // read all the data at once. For a 32-bits pairwise load, we do a
                // simple 64-bits load, for a 128-bits load, we need to call a special
                // method to read 128-bits atomically.
                if (op.Size == 2)
                {
                    Operand value = EmitLoadExclusive(context, address, exclusive, 3);

                    Operand valueLow = context.ConvertI64ToI32(value);

                    valueLow = context.ZeroExtend32(OperandType.I64, valueLow);

                    Operand valueHigh = context.ShiftRightUI(value, Const(32));

                    SetIntOrZR(context, op.Rt, valueLow);
                    SetIntOrZR(context, op.Rt2, valueHigh);
                }
                else if (op.Size == 3)
                {
                    Operand value = EmitLoadExclusive(context, address, exclusive, 4);

                    Operand valueLow  = context.VectorExtract(OperandType.I64, value, 0);
                    Operand valueHigh = context.VectorExtract(OperandType.I64, value, 1);

                    SetIntOrZR(context, op.Rt, valueLow);
                    SetIntOrZR(context, op.Rt2, valueHigh);
                }
                else
                {
                    throw new InvalidOperationException($"Invalid load size of {1 << op.Size} bytes.");
                }
            }
            else
            {
                // 8, 16, 32 or 64-bits (non-pairwise) load.
                Operand value = EmitLoadExclusive(context, address, exclusive, op.Size);

                SetIntOrZR(context, op.Rt, value);
            }

            if (ordered)
            {
                // Memory operations after this load may be only executed after the load completes.
                EmitBarrier(context);
            }
        }
Esempio n. 2
0
        private static void EmitStoreEx(ArmEmitterContext context, AccessType accType, bool pair)
        {
            OpCodeMemEx op = (OpCodeMemEx)context.CurrOp;

            bool ordered   = (accType & AccessType.Ordered) != 0;
            bool exclusive = (accType & AccessType.Exclusive) != 0;

            if (ordered)
            {
                EmitBarrier(context);
            }

            Operand address = context.Copy(GetIntOrSP(context, op.Rn));

            Operand t = GetIntOrZR(context, op.Rt);

            Operand s = null;

            if (pair)
            {
                Debug.Assert(op.Size == 2 || op.Size == 3, "Invalid size for pairwise store.");

                Operand t2 = GetIntOrZR(context, op.Rt2);

                Operand value;

                if (op.Size == 2)
                {
                    value = context.BitwiseOr(t, context.ShiftLeft(t2, Const(32)));
                }
                else /* if (op.Size == 3) */
                {
                    value = context.VectorInsert(context.VectorZero(), t, 0);
                    value = context.VectorInsert(value, t2, 1);
                }

                s = EmitStoreExclusive(context, address, value, exclusive, op.Size + 1);
            }
            else
            {
                s = EmitStoreExclusive(context, address, t, exclusive, op.Size);
            }

            if (s != null)
            {
                // This is only needed for exclusive stores. The function returns 0
                // when the store is successful, and 1 otherwise.
                SetIntOrZR(context, op.Rs, s);
            }
        }
Esempio n. 3
0
        private static void EmitStoreEx(ArmEmitterContext context, AccessType accType, bool pair)
        {
            OpCodeMemEx op = (OpCodeMemEx)context.CurrOp;

            bool ordered   = (accType & AccessType.Ordered) != 0;
            bool exclusive = (accType & AccessType.Exclusive) != 0;

            if (ordered)
            {
                // Memory operations before this store must have completed before the store is executed.
                EmitBarrier(context);
            }

            Operand address = context.Copy(GetIntOrSP(context, op.Rn));

            Operand t = GetIntOrZR(context, op.Rt);

            if (pair)
            {
                Debug.Assert(op.Size == 2 || op.Size == 3, "Invalid size for pairwise store.");

                Operand t2 = GetIntOrZR(context, op.Rt2);

                Operand value;

                if (op.Size == 2)
                {
                    value = context.BitwiseOr(t, context.ShiftLeft(t2, Const(32)));
                }
                else /* if (op.Size == 3) */
                {
                    value = context.VectorInsert(context.VectorZero(), t, 0);
                    value = context.VectorInsert(value, t2, 1);
                }

                EmitStoreExclusive(context, address, value, exclusive, op.Size + 1, op.Rs, a32: false);
            }
            else
            {
                EmitStoreExclusive(context, address, t, exclusive, op.Size, op.Rs, a32: false);
            }
        }