Beispiel #1
0
        /// <summary>
        /// Get an instruction block from the cache at address. If not present then call getInstanceFunc and add to the cache.
        /// </summary>
        /// <param name="address"></param>
        /// <param name="getInstanceFunc"></param>
        /// <returns></returns>
        public IInstructionBlock GetOrSet(ushort address, Func <IInstructionBlock> getInstanceFunc)
        {
            ICachedInstructionBlock cachedInstructionBlock;

            if (_cache.TryGetValue(address, out cachedInstructionBlock))
            {
                cachedInstructionBlock.AccessedCount++;
            }
            else
            {
                var block  = getInstanceFunc();
                var ranges = AddressRange.GetRanges(block.Address, block.Length).ToArray();
                if (ranges.Length == 1)
                {
                    cachedInstructionBlock = new NormalCachedInstructionBlock(ranges[0], block);
                }
                else
                {
                    cachedInstructionBlock = new CachedInstructionBlock(ranges, block);
                }

                _cache.TryAdd(block.Address, cachedInstructionBlock);
                AddCachedRanges(cachedInstructionBlock.AddressRanges);
            }

            return(cachedInstructionBlock.InstructionBlock);
        }
Beispiel #2
0
        /// <summary>
        /// Invalidates all cache from address for length
        /// </summary>
        /// <param name="address"></param>
        /// <param name="length"></param>
        public void InvalidateCache(ushort address, ushort length)
        {
            var ranges = AddressRange.GetRanges(address, length).ToArray();

            if (ranges.Length == 1)
            {
                var range = ranges[0];

                // Lightweight check first.
                if (!_cachedRanges.Any(x => x.Intersects(range)))
                {
                    return;
                }

                foreach (var kvp in _cache.Where(x => x.Value.Intersects(range)).ToArray())
                {
                    ICachedInstructionBlock dummy;
                    _cache.TryRemove(kvp.Key, out dummy);
                    UpdateCachedRanges();
                }
            }
            else
            {
                var range0 = ranges[0];
                var range1 = ranges[1];

                // Lightweight check first.
                if (!_cachedRanges.Any(x => x.Intersects(range0) || x.Intersects(range1)))
                {
                    return;
                }

                foreach (var key in _cache.Keys)
                {
                    var cacheItem = _cache[key];
                    if (ranges.Any(range => cacheItem.Intersects(range)))
                    {
                        _cache.TryRemove(key, out cacheItem);
                        UpdateCachedRanges();
                    }
                }
            }
        }