예제 #1
0
파일: AccCIL.cs 프로젝트: PlumpMath/ac3il
        public static Type GetObjType(KnownObjectTypes objt)
        {
            switch (objt)
            {
            case KnownObjectTypes.Boolean:
                return(typeof(bool));

            case KnownObjectTypes.Byte:
                return(typeof(byte));

            case KnownObjectTypes.SByte:
                return(typeof(sbyte));

            case KnownObjectTypes.Short:
                return(typeof(short));

            case KnownObjectTypes.UShort:
                return(typeof(ushort));

            case KnownObjectTypes.Int:
                return(typeof(int));

            case KnownObjectTypes.UInt:
                return(typeof(uint));

            case KnownObjectTypes.Long:
                return(typeof(long));

            case KnownObjectTypes.ULong:
                return(typeof(ulong));

            case KnownObjectTypes.Float:
                return(typeof(float));

            case KnownObjectTypes.Double:
                return(typeof(double));

            case KnownObjectTypes.String:
                return(typeof(string));

            default:
                throw new Exception("Unexpected type: " + objt.ToString());
            }
        }
예제 #2
0
파일: AccCIL.cs 프로젝트: kenkendk/ac3il
 public static Type GetObjType(KnownObjectTypes objt)
 {
     switch (objt)
     {
         case KnownObjectTypes.Boolean:
             return typeof(bool);
         case KnownObjectTypes.Byte:
             return typeof(byte);
         case KnownObjectTypes.SByte:
             return typeof(sbyte);
         case KnownObjectTypes.Short:
             return typeof(short);
         case KnownObjectTypes.UShort:
             return typeof(ushort);
         case KnownObjectTypes.Int:
             return typeof(int);
         case KnownObjectTypes.UInt:
             return typeof(uint);
         case KnownObjectTypes.Long:
             return typeof(long);
         case KnownObjectTypes.ULong:
             return typeof(ulong);
         case KnownObjectTypes.Float:
             return typeof(float);
         case KnownObjectTypes.Double:
             return typeof(double);
         case KnownObjectTypes.String:
             return typeof(string);
         default:
             throw new Exception("Unexpected type: " + objt.ToString());
     }
 }
예제 #3
0
        public void Ldelem_common(InstructionElement el)
        {
            VirtualRegister elementIndex = PopStack(_RTMP0);
            VirtualRegister arrayPointer = PopStack(_RTMP1);
            VirtualRegister o = el.Register.RegisterNumber < 0 ? new TemporaryRegister(_RTMP0) : el.Register;

            if (el.Childnodes[1].StorageClass != typeof(int))
                throw new Exception("Unexpected index type: " + el.Childnodes[1].StorageClass.ToString());

            KnownObjectTypes[] arraytypes;

            switch (el.Instruction.OpCode.Code)
            {
                case Mono.Cecil.Cil.Code.Ldelem_I1:
                //case Mono.Cecil.Cil.Code.Ldelem_Bool: //Does not exist
                    arraytypes = new KnownObjectTypes[] { KnownObjectTypes.SByte, KnownObjectTypes.Boolean };
                    break;
                case Mono.Cecil.Cil.Code.Ldelem_I2:
                    arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Short };
                    break;
                case Mono.Cecil.Cil.Code.Ldelem_I4:
                    arraytypes = new KnownObjectTypes[] {  KnownObjectTypes.Int };
                    break;
                case Mono.Cecil.Cil.Code.Ldelem_I8:
                //case Mono.Cecil.Cil.Code.Ldelem_U8: //Does not exist
                    arraytypes = new KnownObjectTypes[] {  KnownObjectTypes.Long, KnownObjectTypes.ULong };
                    break;
                case Mono.Cecil.Cil.Code.Ldelem_R4:
                    arraytypes = new KnownObjectTypes[] {  KnownObjectTypes.Float };
                    break;
                case Mono.Cecil.Cil.Code.Ldelem_R8:
                    arraytypes = new KnownObjectTypes[] {  KnownObjectTypes.Double };
                    break;
                case Mono.Cecil.Cil.Code.Ldelem_U1:
                    arraytypes = new KnownObjectTypes[] {  KnownObjectTypes.Byte };
                    break;
                case Mono.Cecil.Cil.Code.Ldelem_U2:
                    arraytypes = new KnownObjectTypes[] {  KnownObjectTypes.UShort };
                    break;
                case Mono.Cecil.Cil.Code.Ldelem_U4:
                    arraytypes = new KnownObjectTypes[] {  KnownObjectTypes.UInt };
                    break;
                default:
                    throw new Exception("Unsupport array type: " + el.Instruction.OpCode.Code);
            }

            LoadElementAddress(el, arraytypes, (uint)elementIndex.RegisterNumber, (uint)arrayPointer.RegisterNumber, _RTMP0);
            LoadElement(arraytypes[0], _RTMP0, (uint)o.RegisterNumber);

            PushStack(o);
        }
예제 #4
0
        /// <summary>
        /// Stores the given value as an array element at the position indicated by the pointer.
        /// Note that this function is expected to be the last in the sequence and
        /// destroys all temporary registers.
        /// Note that no type/index checks are performed.
        /// </summary>
        /// <param name="arraytype">The type of the array elements</param>
        /// <param name="pointer">The register that contains the element address must not be _RTMP0, _RTMP2, _RTMP3</param>
        /// <param name="value">The register that contains the value to store, must not be _RTMP1, _RTMP2, _RTMP3</param>
        private void StoreElement(KnownObjectTypes arraytype, uint pointer, uint value)
        {
            System.Diagnostics.Debug.Assert(pointer != _RTMP0 && pointer != _RTMP2 && pointer != _RTMP3);
            System.Diagnostics.Debug.Assert(value != _RTMP1 && value != _RTMP2 && value != _RTMP3);

            uint eldivsize = BuiltInSPEMethods.get_array_elem_len_mult((uint)arraytype);

            //Calculate the number of bytes to shift left, i.e. 16 - bytes_shift_right
            m_state.Instructions.Add(new SPEEmulator.OpCodes.sfi(_RTMP2, pointer, 0x10)); //16 - value

            //The instruction ignores anything but the low four bits anyway
            //m_state.Instructions.Add(new SPEEmulator.OpCodes.andi(_RTMP2, (uint)pointer.RegisterNumber, 0xfu)); //Remove anything but the low 4 bits

            uint mask;
            if (eldivsize == 0)
                mask = 0x8000;
            else if (eldivsize == 1)
                mask = 0xC000;
            else if (eldivsize == 2)
                mask = 0xf000;
            else if (eldivsize == 3)
                mask = 0xff00;
            else
                throw new InvalidProgramException();

            //Get a mask for selecting the element from the source, and rotate it into place
            m_state.Instructions.Add(new SPEEmulator.OpCodes.fsmbi(_RTMP3, mask)); //Get mask
            m_state.Instructions.Add(new SPEEmulator.OpCodes.rotqby(_RTMP3, _RTMP3, _RTMP2)); //Rotate into place

            //Place the new value in the slot
            if (eldivsize == 0)
            {
                m_state.Instructions.Add(new SPEEmulator.OpCodes.sfi(_RTMP2, pointer, 0x03)); //3 - Pointer
                m_state.Instructions.Add(new SPEEmulator.OpCodes.andi(_RTMP2, _RTMP2, 0x03)); //Only low 2 bits
                m_state.Instructions.Add(new SPEEmulator.OpCodes.rotqby(_RTMP0, value, _RTMP2)); //Rotate into place
                m_state.Instructions.Add(new SPEEmulator.OpCodes.and(_RTMP0, _RTMP0, _RTMP3)); //Select the portion of the value
            }
            else if (eldivsize == 1)
            {
                m_state.Instructions.Add(new SPEEmulator.OpCodes.sfi(_RTMP2, pointer, 0x02)); //2 - Pointer
                m_state.Instructions.Add(new SPEEmulator.OpCodes.andi(_RTMP2, _RTMP2, 0x02)); //Only bit at pos 1
                m_state.Instructions.Add(new SPEEmulator.OpCodes.rotqby(_RTMP0, value, _RTMP2)); //Rotate into place
                m_state.Instructions.Add(new SPEEmulator.OpCodes.and(_RTMP0, _RTMP0, _RTMP3)); //Select the portion of the value
            }
            else
            {
                m_state.Instructions.Add(new SPEEmulator.OpCodes.and(_RTMP0, value, _RTMP3)); //Select the portion of the value
            }

            //Remove the current value in the slot
            m_state.Instructions.Add(new SPEEmulator.OpCodes.xori(_RTMP3, _RTMP3, 0x3ff)); //Invert mask
            m_state.Instructions.Add(new SPEEmulator.OpCodes.lqd(_RTMP2, pointer, 0x0)); //Load current
            m_state.Instructions.Add(new SPEEmulator.OpCodes.and(_RTMP2, _RTMP2, _RTMP3)); //Mask out slot
            m_state.Instructions.Add(new SPEEmulator.OpCodes.or(_RTMP0, _RTMP0, _RTMP2)); //Merge the two values

            //Save the value in LS
            m_state.Instructions.Add(new SPEEmulator.OpCodes.stqd(_RTMP0, pointer, 0));
        }
예제 #5
0
        /// <summary>
        /// Function that loads an array element from an address and places it on the stack.
        /// Note that this function is expected to be the last in a sequence and as
        /// such destroys all temporary registers.
        /// Note that this function does no type/index checking.
        /// </summary>
        /// <param name="arraytype">The array element type</param>
        /// <param name="pointer">The register that holds the address, cannot be _RTMP3</param>
        /// <param name="output">The register to receive the loaded value</param>
        private void LoadElement(KnownObjectTypes arraytype, uint pointer, uint output)
        {
            //We overwrite this register early on
            System.Diagnostics.Debug.Assert(pointer != _RTMP3);

            //Load the value
            m_state.Instructions.Add(new SPEEmulator.OpCodes.lqd(_RTMP3, pointer, 0));

            //Figure out how much non-aligned we are
            m_state.Instructions.Add(new SPEEmulator.OpCodes.andi(_RTMP1, pointer, 0xfu)); //Use only the lower bits
            m_state.Instructions.Add(new SPEEmulator.OpCodes.rotqby(_RTMP3, _RTMP3, _RTMP1)); //Rotate into prefered slot

            ExpandValue(arraytype, _RTMP3, output);
        }
예제 #6
0
        /// <summary>
        /// Function that expands the value in a register to fit onto the stack.
        /// Note that this function is expected to be the last in a sequence and as
        /// such destroys all temporary registers.
        /// </summary>
        /// <param name="type">The element type</param>
        /// <param name="valueRegister">The register that holds the value</param>
        /// <param name="outputregister">The register into which the expanded value is stored</param>
        private void ExpandValue(KnownObjectTypes type, uint valueRegister, uint outputregister)
        {
            uint eldivsize = BuiltInSPEMethods.get_array_elem_len_mult((uint)type);
            bool signed = type == KnownObjectTypes.SByte || type == KnownObjectTypes.Short || type == KnownObjectTypes.Int || type == KnownObjectTypes.Long;

            uint tmpReg = valueRegister == _RTMP0 ? _RTMP1 : _RTMP0;

            if (signed)
            {
                ulong mask;
                if (eldivsize == 0)
                    mask = 0x1010101010101010;
                else if (eldivsize == 1)
                    mask = 0x1011101110111011;
                else if (eldivsize == 2)
                    mask = 0x1011121310111213;
                else if (eldivsize == 3)
                    mask = 0x1011121314151617;
                else
                    throw new InvalidProgramException();

                //Load the new value into the register
                m_state.RegisterConstantLoad(mask, mask); //Load element into register
                m_state.Instructions.Add(new SPEEmulator.OpCodes.lqr(tmpReg, 0));
                m_state.Instructions.Add(new SPEEmulator.OpCodes.shufb(outputregister, valueRegister, valueRegister, tmpReg)); //Move word into position (should be 4 bytes)

                //Since the element must be stored as int32 on stack, we must convert it and sign extend it
                if (eldivsize <= 0)
                    m_state.Instructions.Add(new SPEEmulator.OpCodes.xsbh(outputregister, outputregister)); //Convert to halfword
                if (eldivsize <= 1)
                    m_state.Instructions.Add(new SPEEmulator.OpCodes.xshw(outputregister, outputregister)); //Convert to word
            }
            else
            {
                ulong mask;
                if (eldivsize == 0)
                    mask = 0x8080801080808010;
                else if (eldivsize == 1)
                    mask = 0x8080101180801011;
                else if (eldivsize == 2)
                    mask = 0x1011121310111213;
                else if (eldivsize == 3)
                    mask = 0x1011121314151617;
                else
                    throw new InvalidProgramException();

                //Load the new value into the register
                m_state.RegisterConstantLoad(mask, mask); //Load element into register
                m_state.Instructions.Add(new SPEEmulator.OpCodes.lqr(tmpReg, 0));
                m_state.Instructions.Add(new SPEEmulator.OpCodes.shufb(outputregister, valueRegister, valueRegister, tmpReg)); //Move word into position (should be 4 bytes)
            }
        }
예제 #7
0
        public void Stelem_common(InstructionElement el)
        {
            VirtualRegister value = PopStack(_RTMP4);

            VirtualRegister elementIndex = PopStack(_RTMP0);
            VirtualRegister arrayPointer = PopStack(_RTMP1);

            KnownObjectTypes[] arraytypes;

            switch (el.Instruction.OpCode.Code)
            {
                case Mono.Cecil.Cil.Code.Stelem_I:
                    arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Int };
                    break;
                case Mono.Cecil.Cil.Code.Stelem_I1:
                    arraytypes = new KnownObjectTypes[] { KnownObjectTypes.SByte, KnownObjectTypes.Boolean, KnownObjectTypes.Byte };
                    break;
                case Mono.Cecil.Cil.Code.Stelem_I2:
                    arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Short, KnownObjectTypes.UShort };
                    break;
                case Mono.Cecil.Cil.Code.Stelem_I4:
                    arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Int, KnownObjectTypes.UInt };
                    break;
                case Mono.Cecil.Cil.Code.Stelem_I8:
                    arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Long, KnownObjectTypes.ULong };
                    break;
                case Mono.Cecil.Cil.Code.Stelem_R4:
                    arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Float };
                    break;
                case Mono.Cecil.Cil.Code.Stelem_R8:
                    arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Double };
                    break;
                case Mono.Cecil.Cil.Code.Stelem_Ref:
                    arraytypes = new KnownObjectTypes[] { KnownObjectTypes.Object };
                    break;
                default:
                    throw new Exception("Unsupported stelem instruction: " + el.Instruction.OpCode.Code);
            }

            LoadElementAddress(el, arraytypes, (uint)elementIndex.RegisterNumber, (uint)arrayPointer.RegisterNumber, _RTMP1);
            StoreElement(arraytypes[0], _RTMP1, (uint)value.RegisterNumber);
        }