示例#1
0
        /// <summary>
        /// Read the block of memory at the given address and size.
        /// </summary>
        /// <param name="address">address to read</param>
        /// <param name="ms">size of read</param>
        /// <returns>value read at that address</returns>
        public uint GetMemory(uint address, ARMPluginInterfaces.MemorySize ms)
        {
            System.Diagnostics.Debug.Assert(Valid && ((address & Mask) == Tag));

            uint index = (address & ~Mask) >> 2;
            uint data  = Data[index];

            //fetch the value based on the size requested
            switch (ms)
            {
            case ARMPluginInterfaces.MemorySize.Byte:
            {
                uint byteNumber = address & 0x0003;
                data = (data >> (int)(byteNumber * 8)) & 0x00ff;
            } break;

            case ARMPluginInterfaces.MemorySize.HalfWord:
            {
                if ((address & 0x0002) != 0)
                {
                    data >>= 16;
                }
                data &= 0xFFFF;
            } break;

            case ARMPluginInterfaces.MemorySize.Word:
                break;

            default:
                throw new Exception("Bad memory size specified");
            } //switch
            return(data);
        }     //GetMemory
示例#2
0
        }//allocateLine

        /// <summary>
        /// Read from the CacheSet.
        /// Check each block in the set and compare the line tag with the address. If the address tag matches the
        /// line tag, then we have a cache block hit. Otherwise we need to get the requested block into the
        /// cache and this will depend on the allocate policy.
        /// </summary>
        /// <param name="address">address to read</param>
        /// <param name="ms">size to read</param>
        /// <param name="allocatePolicy">allocation policy to use</param>
        /// <returns>value read</returns>
        public uint GetMemory(uint address, ARMPluginInterfaces.MemorySize ms, AllocatePolicyEnum allocatePolicy)
        {
            //check each line in the cache set
            foreach (CacheBlock cb in Blocks)
            {
                //only check valid lines and look for a tag match
                if (cb.Valid && ((address & cb.Mask) == cb.Tag))
                {
                    //cache read hit
                    ReadHits++;
                    return(cb.GetMemory(address, ms));
                }
            }
            //cache read miss
            ReadMisses++;

            if (allocatePolicy != AllocatePolicyEnum.Write)
            {
                //read or both policy
                return(allocateLine(address).GetMemory(address, ms));
            }
            else
            {
                //write policy, do not allocate a new cache line
                return(memBlock.GetMemory(address, ms));
            }
        }//GetMemory
        internal uint LoadMemorySignedByte(uint address, uint Rd, ARMPluginInterfaces.MemorySize memorySize)
        {
            System.Diagnostics.Debug.Assert(memorySize == ARMPluginInterfaces.MemorySize.Byte);
            uint value = GetMemory(address, memorySize);

            //Sign-extend the loaded byte to a word.
            mGPR[Rd] = (uint)(SByte)(value & 0xff);
            return((Rd == GeneralPurposeRegisters.PCRegisterIndex) ? (uint)5 : (uint)3);
        }
示例#4
0
        }//GetMemory

        /// <summary>
        /// Write memory to data cache
        /// </summary>
        /// <param name="address">address to read</param>
        /// <param name="ms">size to read</param>
        /// <param name="data">data to write</param>
        public void SetMemory(uint address, ARMPluginInterfaces.MemorySize ms, uint data)
        {
            if (!this.Enabled)
            {
                memBlock.SetMemory(address, ms, data);
                return;
            } //if
            Sets[computeSetNumber(address)].SetMemory(address, ms, data, _writeThru, _allocatePolicy);
        }     //SetMemory
示例#5
0
        }        //computeSetNumber

        /// <summary>
        /// Get memory from the cache. If the cache is not enabled, pass the request to main memory.
        /// Otherwise pass request to computed cache set.
        /// </summary>
        /// <param name="address">address to read</param>
        /// <param name="ms">size to read</param>
        /// <returns>value read</returns>
        public virtual uint GetMemory(uint address, ARMPluginInterfaces.MemorySize ms)
        {
            if (!this.Enabled)
            {
                return(memBlock.GetMemory(address, ms));
            }

            //force allocate policy to be read for an L1cache
            return(Sets[computeSetNumber(address)].GetMemory(address, ms, ARMPluginInterfaces.Preferences.AllocatePolicyEnum.Read));
        }//GetMemory
示例#6
0
        }     //GetMemory

        /// <summary>
        /// Write to the cache Line. If the write-thru policy is active, write to both
        /// the cache line and out to main memory.
        /// </summary>
        /// <param name="address">address to write to</param>
        /// <param name="ms">size of write</param>
        /// <param name="data">value to write</param>
        /// <param name="writeThru">write through to main memory</param>
        public void SetMemory(uint address, ARMPluginInterfaces.MemorySize ms, uint data, bool writeThru)
        {
            System.Diagnostics.Debug.Assert(Valid && ((address & Mask) == Tag));

            //convert address to array index
            uint index = (address & ~Mask) >> 2;

            switch (ms)
            {
            //case handles the writing of bytes
            case ARMPluginInterfaces.MemorySize.Byte:
            {
                uint byteNumber = address & 0x0003;
                uint mask       = (uint)(0x00ff << (int)(byteNumber * 8));

                uint newData  = Data[index] & ~mask;
                uint thisData = data & 0x00ff;
                uint sData    = thisData << (int)(byteNumber * 8);
                Data[index] = newData | sData;
            }
            break;

            //case handles the writing of halfwords
            case ARMPluginInterfaces.MemorySize.HalfWord:
            {
                uint d = Data[index];
                if ((address & 0x0002) == 0)
                {
                    Data[index] = (d & 0xFFFF0000) | (data & 0x0000FFFF);
                }
                else
                {
                    Data[index] = (d & 0x0000FFFF) | (data << 16);
                }
            }
            break;

            //case handles the writing of words
            case ARMPluginInterfaces.MemorySize.Word:
                Data[index] = data;
                break;

            default:
                throw new Exception("Bad memory size specified");
            }            //switch

            if (writeThru)
            {//if write thru is active then write this to main memory as well
                memBlock.SetMemory(address, ms, data);
            }
            else
            {//else set the dirty bit
                Dirty = true;
            }
        }//SetMemory
示例#7
0
        internal uint transfer(uint op_code)
        {
            if ((op_code & undef_mask) == undef_code)
            {
                return(0);
            }

            ARMPluginInterfaces.MemorySize ms =
                ((op_code & byte_mask) == 0) ? ARMPluginInterfaces.MemorySize.Word : ARMPluginInterfaces.MemorySize.Byte;
            uint Rd      = (op_code & rd_mask) >> 12;
            uint Rn      = (op_code & rn_mask) >> 16;
            uint address = get_reg(Rn);
            int  offset  = transfer_offset((op_code & op2_mask), ((op_code & up_mask) != 0), ((op_code & imm_mask) != 0), false); //bit(25) = 1 -> reg

            if ((op_code & pre_mask) != 0)
            {
                //Pre-index
                address = (uint)((int)address + offset);
            }

            if (TrapUnalignedMemoryAccess)
            {
                if ((ms == ARMPluginInterfaces.MemorySize.Word && ((address & 0x03) != 0)) ||
                    (ms == ARMPluginInterfaces.MemorySize.HalfWord && ((address & 0x01) != 0)))
                {
                    throw new UnalignedAccessException(address);
                }
            }

            uint cycles;

            if ((op_code & load_mask) == 0)
            {
                this.SetMemory(address, ms, get_reg(Rd));
                cycles = 2;
            }
            else
            {
                mGPR[Rd] = this.GetMemory(address, ms);
                cycles   = (Rd == GeneralPurposeRegisters.PCRegisterIndex) ? (uint)5 : (uint)3;
            }

            if ((op_code & pre_mask) == 0)//Post-index
            //Post index write-back
            {
                mGPR[Rn] = (uint)((int)address + offset);
            }
            else if ((op_code & write_back_mask) != 0)
            {
                //Pre index write-back
                mGPR[Rn] = address;
            }

            return(cycles);
        }
示例#8
0
        /* **************** DATA OP HANDLERS ********************** */

        internal uint swap(uint op_code)
        {
            uint address = get_reg((byte)((op_code & rn_mask) >> 16));

            ARMPluginInterfaces.MemorySize ms = ((op_code & byte_mask) != 0) ? ARMPluginInterfaces.MemorySize.Byte : ARMPluginInterfaces.MemorySize.Word;

            uint data = this.GetMemory(address, ms);

            this.SetMemory(address, ms, get_reg(op_code & rm_mask));
            mGPR[((op_code & rd_mask) >> 12)] = data;
            return(4);
        }
示例#9
0
        private int CellWidth(ARMPluginInterfaces.MemorySize ms)
        {
            switch (ms)
            {
            case ARMPluginInterfaces.MemorySize.Byte: return(mCharSize.Width * 3);

            case ARMPluginInterfaces.MemorySize.HalfWord: return(mCharSize.Width * 5);

            case ARMPluginInterfaces.MemorySize.Word: return(mCharSize.Width * 10);

            default: return(0);
            }
        }
示例#10
0
        private static string MemoryToUnknownString(ARMPluginInterfaces.MemorySize ms)
        {
            switch (ms)
            {
            case ARMPluginInterfaces.MemorySize.Byte: return("??");

            case ARMPluginInterfaces.MemorySize.HalfWord: return("????");

            case ARMPluginInterfaces.MemorySize.Word: return("????????");

            default: return("");
            }
        }
示例#11
0
        }        //Purge

        /// <summary>
        /// This method allows reading of the cache with no side effects. This is used ny the user interface
        /// so the cache contents can be displayed without changing the state of the cache.
        /// </summary>
        /// <param name="address">address to read</param>
        /// <param name="ms">size to read</param>
        /// <returns>valuee read</returns>
        public uint GetMemoryNoSideEffect(uint address, ARMPluginInterfaces.MemorySize ms)
        {
            //iterate over the cache blocks looking for the block that holds this address
            foreach (CacheBlock cl in Blocks)
            {
                //check if this block is valid and has this address
                if (cl.Valid && ((address & cl.Mask) == cl.Tag))
                {
                    //cache read hit
                    return(cl.GetMemory(address, ms));
                }        //if
            }            //foreach
            return(memBlock.GetMemory(address, ms));
        }//GetMemoryNoSideEffect
示例#12
0
        }         //memoryChangedHandler

        private static string MemoryToString(uint data, ARMPluginInterfaces.MemorySize ms)
        {
            switch (ms)
            {
            case ARMPluginInterfaces.MemorySize.Byte: return(data.ToString("X2"));

            case ARMPluginInterfaces.MemorySize.HalfWord: return(data.ToString("X4"));

            case ARMPluginInterfaces.MemorySize.Word: return(data.ToString("X8"));

            //                case ARMPluginInterfaces.MemorySize.HalfWord: return Utils.reverseBinary(data, ARMPluginInterfaces.MemorySize.HalfWord).ToString("X4");
            //                case ARMPluginInterfaces.MemorySize.Word: return Utils.reverseBinary(data, ARMPluginInterfaces.MemorySize.Word).ToString("X8");
            default: return("");
            }
        }
示例#13
0
        public void memoryChangedHandler(uint address, ARMPluginInterfaces.MemorySize ms, uint oldValue, uint newValue)
        {
            if (mChangedMemory == null || address < mChangedMemoryStart)
            {
                return;
            }

            uint memAddress = address - mChangedMemoryStart;

            for (int ii = 0; ii < (int)ms; ii++, memAddress++)
            {
                if (memAddress < mChangedMemory.Length)
                {
                    mChangedMemory[memAddress] = true;
                } //if
            }     //for ii
        }         //memoryChangedHandler
示例#14
0
        }        //setmem8

        /// <summary>
        /// Set a memory value at the specified address
        /// Checks for a valid address within the memory block limits.
        /// If the memory changed handler is set, call it with the write info.
        /// </summary>
        /// <param name="address">address to write</param>
        /// <param name="ms">size of memory to write</param>
        /// <param name="data">value to write</param>
        public void SetMemory(uint address, ARMPluginInterfaces.MemorySize ms, uint data)
        {
            if (ProtectTextArea)
            {
                if (!InDataRange(address, ms))
                {
                    throw new ARMPluginInterfaces.MemoryAccessException(address, "Out of range");
                }
            }
            else
            {
                if (!InRange(address, ms))
                {
                    throw new ARMPluginInterfaces.MemoryAccessException(address, "Out of range");
                }
            }

            //if changed handler set, call it
            if (_memoryChangedHandler != null)
            {
                _memoryChangedHandler(address, ms, GetMemory(address, ms), data);
            }

            //call the write function based on the data type
            switch (ms)
            {
            case ARMPluginInterfaces.MemorySize.Byte:
                setmem8(address, data);
                break;

            case ARMPluginInterfaces.MemorySize.HalfWord:
                setmem16(address, data);
                break;

            case ARMPluginInterfaces.MemorySize.Word:
                setmem32(address, data);
                break;

            default:
                throw new ARMPluginInterfaces.MemoryAccessException(address, "Bad memory size");
            }            //switch
        }//SetMemory
示例#15
0
        }        //getmem8

        /// <summary>
        /// Get a memory value at the specified address
        /// Checks for a valid address within the memory block limits.
        /// </summary>
        /// <param name="address">address to read</param>
        /// <param name="ms">size of memory to read</param>
        /// <returns>value read at address</returns>
        public uint GetMemory(uint address, ARMPluginInterfaces.MemorySize ms)
        {
            //if its out of range, abort
            if (!InRange(address, ms))
            {
                throw new ARMPluginInterfaces.MemoryAccessException(address, "Out of range");
            }

            //otherwise call the specific memget based on type
            switch (ms)
            {
            case ARMPluginInterfaces.MemorySize.Byte: return(getmem8(address));

            case ARMPluginInterfaces.MemorySize.HalfWord: return(getmem16(address));

            case ARMPluginInterfaces.MemorySize.Word: return(getmem32(address));

            default:
                throw new ARMPluginInterfaces.MemoryAccessException(address, "Bad memory size");
            }            //switvh
        }//GetMemory
示例#16
0
        }        //InRange

        /// <summary>
        /// Safely checks if the specified address and size are in the address range for data.
        /// </summary>
        /// <param name="address">address to check</param>
        /// <param name="ms">size of memory operation to check</param>
        /// <returns>true if in range</returns>
        public bool InDataRange(uint address, ARMPluginInterfaces.MemorySize ms)
        {
            if (address < _data_start)
            {
                return(false);
            }
            switch (ms)
            {
            case ARMPluginInterfaces.MemorySize.Byte:
                return(address < _memory_end);

            case ARMPluginInterfaces.MemorySize.HalfWord:
                return(address < (_memory_end - 1));

            case ARMPluginInterfaces.MemorySize.Word:
                return(address < (_memory_end - 3));

            default:
                throw new ARMPluginInterfaces.MemoryAccessException(address, "Bad memory size");
            }            //switch
        }
示例#17
0
        private bool get_changed(uint address, ARMPluginInterfaces.MemorySize ms)
        {
            if (mChangedMemory == null || address < mChangedMemoryStart)
            {
                return(false);
            }

            bool changed    = false;
            uint memAddress = address - mChangedMemoryStart;

            for (int ii = 0; ii < (int)ms; ii++, memAddress++)
            {
                if (memAddress < mChangedMemory.Length)
                {
                    if (mChangedMemory[memAddress])
                    {
                        changed = true;
                    }
                } //if
            }     //for ii
            return(changed);
        }
示例#18
0
        }        //WriteMisses

        /// <summary>
        /// Override the getmem here to use the true allocate policy. The L1Cache version forces
        /// this parameter to be read allocate.
        /// </summary>
        /// <param name="address">address to read</param>
        /// <param name="ms">size to read</param>
        /// <returns></returns>
        public override uint GetMemory(uint address, ARMPluginInterfaces.MemorySize ms)
        {
            uint result;

            if (!this.Enabled)
            {
                result = memBlock.GetMemory(address, ms);
            }
            else
            {
                result = Sets[computeSetNumber(address)].GetMemory(address, ms, _allocatePolicy);
            }
            if ((address & 0x03) != 0)  // check for unaligned access
            {
                if (ms == ARMPluginInterfaces.MemorySize.Word)
                {
                    // implement rotations of the memory word as specified in
                    // the architectural specification of the LDR instruction
                    switch (address & 0x03)
                    {
                    case 0x01:
                        result = ((result >> 8) & 0x00FFFFFF) | (result << 24);
                        break;

                    case 0x02:
                        result = ((result >> 16) & 0x0000FFFF) | (result << 16);
                        break;

                    case 0x03:
                        result = ((result >> 24) & 0x000000FF) | (result << 8);
                        break;
                    }
                }
                // Note: for an unaligned halfword access, the result is unpredictable
                // so we do nothing.
            }
            return(result);
        }//GetMemory
示例#19
0
        /// <summary>
        /// Write to the CacheSet.
        /// Check each block in the set and compare the block tag with the address. If the address tag matches the
        /// block tag, then we have a cache write block hit. Otherwise we need to get the requested block into the
        /// cache and this will depend on the allocate policy.
        /// </summary>
        /// <param name="address">address to write to</param>
        /// <param name="ms">size to write</param>
        /// <param name="data">data to write</param>
        /// <param name="writeThru">true then write through to main memory</param>
        /// <param name="allocatePolicy">allocate policy to use</param>
        public void SetMemory(uint address, ARMPluginInterfaces.MemorySize ms, uint data, bool writeThru, AllocatePolicyEnum allocatePolicy)
        {
            //iterate over the cache blocks looking for the block that holds this address
            foreach (CacheBlock cb in Blocks)
            {
                //check if this block is valid and has this address
                if (cb.Valid && ((address & cb.Mask) == cb.Tag))
                {
                    //cache write hit, set data into cache memory
                    WriteHits++;
                    cb.SetMemory(address, ms, data, writeThru);

                    //if the changed handler is set, call it
                    if (_cacheChangedHandler != null)
                    {
                        _cacheChangedHandler(cb.BlockNumber, address & cb.Mask);
                    }

                    //done
                    return;
                }        //if
            }            //foreach

            //cache write miss
            WriteMisses++;

            //allocate a cache line based on the allocation policy
            if (allocatePolicy != AllocatePolicyEnum.Read)
            {
                //write or both policy
                allocateLine(address).SetMemory(address, ms, data, writeThru);
            }
            else
            {
                //read policy, do not allocate a new cache line
                memBlock.SetMemory(address, ms, data);
            }
        } //SetMemory
示例#20
0
 /// <summary>
 /// Fetch memory from the main memory module and bypass the cache system.
 /// </summary>
 /// <param name="address"></param>
 /// <param name="ms"></param>
 /// <returns></returns>
 public abstract uint GetMemoryNoSideEffect(uint address, ARMPluginInterfaces.MemorySize ms);
示例#21
0
 /// <summary>
 /// Test if a given memory address and size are within the bounds of main memory.
 /// </summary>
 /// <param name="address"></param>
 /// <param name="ms"></param>
 /// <returns></returns>
 public abstract bool InRange(uint address, ARMPluginInterfaces.MemorySize ms);
示例#22
0
        /// <summary>
        /// Execute the next instruction pointed to by the PC.
        /// Can be in either ARM or Thumb mode.
        /// </summary>
        public void Execute()
        {
            uint pcBefore = mGPR.PC;  // PC before op is executed

            try {
                ARMPluginInterfaces.MemorySize opcodeSize = mCPSR.tf ? ARMPluginInterfaces.MemorySize.HalfWord : ARMPluginInterfaces.MemorySize.Word;

                //this should never happen as the PC is checked after the opcode is executed,
                //but just being careful ...
                if (!this.InRange(pcBefore, opcodeSize))
                {
                    pcOutofRange(uint.MaxValue);  // we don't know the old address??
                    return;
                }

                //track the number of instructions executed.
                ++InstructionCount;

                //get the opcode and increment the PC. Fetch through the cache system if available.
                uint opcode = this.mL1InstructionCache.GetMemory(pcBefore, opcodeSize);

                //increment the PC by the current opcode size (ARM or Thumb mode).
                mGPR.PC = pcBefore + (uint)opcodeSize;

                uint cycleCount;
                bool swiInstruction;

                try
                {
                    cycleCount = ExecuteInstruction(opcode, out swiInstruction);
                }
                catch (UnalignedAccessException e)
                {
                    ReportRuntimeError(pcBefore, "{0}", e.Message);
                    HaltSimulation();
                    mGPR.PC = pcBefore;  // undo any advance of the PC
                    return;
                }
                catch (MemoryAccessException e)
                {
                    ReportRuntimeError(pcBefore, "{0}", e.Message);
                    HaltSimulation();
                    mGPR.PC = pcBefore;  // undo any advance of the PC
                    return;
                }
                // a cycle count of zero indicates an unknown instruction (including an swi instruction)
                if (cycleCount == 0)
                {
                    //let plugins have first crack at the unknown instruction.
                    //a return of 0 indicates it cannot handle it.
                    cycleCount = UnknownOpCode(opcode);
                }//if

                //if the cycle count is still 0 and it's an swi instruction, it wasn't handled by a plugin
                //invoke an ARM swi exception
                if (cycleCount == 0 && swiInstruction)
                {
                    this.RequestException(ARMExceptions.SoftwareInterrupt);
                }//if
                //otherwise its an unknown instruction that is not an swi instruction
                //so raise an ARM undefined instruction exception.
                else if (cycleCount == 0)
                {
                    this.RequestException(ARMExceptions.UndefinedInstruction);
                }//else if

                //if we actually expended cycles, let the plugins know and update local cycle count
                if (cycleCount > 0)
                {
                    CycleCount += cycleCount;
                    //todo - check overflow
                    HandleCycles((ushort)cycleCount);
                }//if

                //test the PC against valid memory. If it is not within the memory block, we have a problem
                if (!this.InRange(mGPR.PC, opcodeSize))
                {
                    pcOutofRange(pcBefore);
                }//if

                //check if any exceptions have been raised.
                //it is assumed that only 1 exception can be raised in a single instruction cycle.
                if (mRequestedException != 0)
                {
                    if ((mRequestedException & (uint)ARMExceptions.SoftwareInterrupt) != 0)
                    {
                        SetExceptionState(ARMExceptions.SoftwareInterrupt);
                    }//if
                    //FIQ has highest priority
                    else if (((mRequestedException & (uint)ARMExceptions.FIQ) != 0) && !mCPSR.FIQDisable)
                    {
                        SetExceptionState(ARMExceptions.FIQ);
                    }
                    else if (((mRequestedException & (uint)ARMExceptions.IRQ) != 0) && !mCPSR.IRQDisable)
                    {
                        SetExceptionState(ARMExceptions.IRQ);
                    }
                    else if ((mRequestedException & (uint)ARMExceptions.UndefinedInstruction) != 0)
                    {
                        SetExceptionState(ARMExceptions.UndefinedInstruction);
                    }
                    else if ((mRequestedException & (uint)ARMExceptions.Reset) != 0)
                    {
                        SetExceptionState(ARMExceptions.Reset);
                    }
                    mRequestedException = 0;
                }//if

                //test the PC against valid memory. If it is not within the memory block, we have a problem
                if (!this.InRange(mGPR.PC, opcodeSize))
                {
                    ARMExceptions possibleReason = interruptKind(mGPR.PC);
                    if (possibleReason != ARMExceptions.None)
                    {
                        if (possibleReason == ARMExceptions.SoftwareInterrupt)
                        {
                            ReportRuntimeError(pcBefore, "Unimplemented SWI code: (0x{0:X6})\n" +
                                               "[Check File/Preferences/Plugins to see which SWI sets have been enabled]",
                                               opcode & 0xFFFFFF);
                        }
                        else
                        {
                            ReportRuntimeError(pcBefore, "Unhandled interrupt of kind {0}",
                                               interruptKind(mGPR.PC));
                        }
                        HaltSimulation();
                        mGPR.PC = pcBefore; // leave PC stuck on the interrupting instruction
                    }
                    else
                    {
                        pcOutofRange(pcBefore);
                    }
                }
            }//try
            catch (ARMPluginInterfaces.MemoryAccessException ex)
            {
                ReportRuntimeError(pcBefore, "Attempt to access memory out of valid range: 0x{0:X8}",
                                   ex.Address);
                HaltSimulation();
                mGPR.PC = pcBefore; // leave PC stuck on the bad instruction
            }//catch
        }//Execute
示例#23
0
 /// <summary>
 /// Write data to main memory.
 /// This is abstract so that the Application level can handle cache and plugin logic.
 /// </summary>
 /// <param name="address"></param>
 /// <param name="ms"></param>
 /// <param name="data"></param>
 public abstract void SetMemory(uint address, ARMPluginInterfaces.MemorySize ms, uint data);
 internal uint StoreMemory(uint address, uint Rd, ARMPluginInterfaces.MemorySize memorySize)
 {
     SetMemory(address, memorySize, get_reg(Rd));
     return(2);
 }
示例#25
0
        private void drawNormalLineCell(Graphics formGraphics, uint address, Point startPoint, int cellNo, ARMPluginInterfaces.MemorySize ms, SolidBrush textBrush)
        {
            Brush  drawBrush = get_changed(address, ms) ? new SolidBrush(_highlightColor) : textBrush;
            string dataChars;

            if (_JM.InRange(address, ARMPluginInterfaces.MemorySize.Byte))
            {
                uint data = this.GetMemory(address, ms);
                dataChars = MemoryToString(data, ms);
            }
            else
            {
                dataChars = MemoryToUnknownString(ms);
            }

            int xpos = startPoint.X + (cellNo * CellWidth(ms));

            for (int kk = 0; kk < dataChars.Length; kk++, xpos += mCharSize.Width)
            {
                formGraphics.DrawString(dataChars.Substring(kk, 1), CurrentFont, drawBrush, xpos, startPoint.Y);
            } //for kk
            if (drawBrush != textBrush)
            {
                drawBrush.Dispose();
            }
        }
示例#26
0
 private uint GetMemory(uint address, ARMPluginInterfaces.MemorySize ms)
 {
     return(_JM.GetMemoryNoSideEffect(address, ms));
 }
        internal InstructionFunc GenerateLoadStoreInstruction(ComputeOffsetFunc ComputeOffset, ComputeOffsetAddressFunc ComputeOffsetAddress, ComputeAddressFunc ComputeFinalAddress,
                                                              WritebackAddressFunc WritebackAddress, ARMPluginInterfaces.MemorySize memorySize, LoadStoreMemoryFunc LoadStoreMemory)
        {
            return(delegate(uint opcode)
            {
                uint Rd = (opcode & rd_mask) >> 12;
                uint Rn = (opcode & rn_mask) >> 16;
                uint base_address = get_reg(Rn);
                uint offset = ComputeOffset(opcode);
                uint offset_address = ComputeOffsetAddress(base_address, offset);
                uint address = ComputeFinalAddress(base_address, offset_address);
                if (TrapUnalignedMemoryAccess)
                {
                    if ((address & (uint)(memorySize - 1)) != 0)
                    {
                        throw new UnalignedAccessException(address);
                    }
                }
                //Writeback the address (if pre- or post-indexing is not being used,
                //the function will do nothing).
                WritebackAddress(Rn, offset_address);

                //Visit memory and perform whatever operation we came for.
                return LoadStoreMemory(address, Rd, memorySize);
            });
        }
 //The cycle counts in the below functions (i.e. 5 or 3 for loads, 2 for stores) were in the original code.
 //I have no idea where they came from originally - BB
 //TODO 10/16/2014 - The old code for LDRH contained some cryptic handling code for aligning the value
 //and toggling Thumb mode when loading into the PC. That code has been omitted here because I can't find
 //any explanation for it anywhere in the ARM documentation and it does not match the word load/store pattern...
 internal uint LoadMemory(uint address, uint Rd, ARMPluginInterfaces.MemorySize memorySize)
 {
     mGPR[Rd] = GetMemory(address, memorySize);
     return((Rd == GeneralPurposeRegisters.PCRegisterIndex) ? (uint)5 : (uint)3);
 }