~registry/dolphin-emu/triforce

« back to all changes in this revision

Viewing changes to Source/Core/Core/Src/PowerPC/PPCCache.cpp

  • Committer: Sérgio Benjamim
  • Date: 2015-02-13 05:54:40 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20150213055440-ey2rt3sjpy27km78
Dolphin Triforce branch from code.google, commit b957980 (4.0-315).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2013 Dolphin Emulator Project
 
2
// Licensed under GPLv2
 
3
// Refer to the license.txt file included.
 
4
 
 
5
#include "PPCCache.h"
 
6
#include "../HW/Memmap.h"
 
7
#include "PowerPC.h"
 
8
#include "JitCommon/JitBase.h"
 
9
#include "JitCommon/JitCache.h"
 
10
#include "JitInterface.h"
 
11
 
 
12
namespace PowerPC
 
13
{
 
14
 
 
15
        const u32 plru_mask[8] = {11,11,19,19,37,37,69,69};
 
16
        const u32 plru_value[8] = {11,3,17,1,36,4,64,0};
 
17
 
 
18
        InstructionCache::InstructionCache()
 
19
        {
 
20
                for (u32 m = 0; m < 0xff; m++)
 
21
                {
 
22
                        u32 w = 0;
 
23
                        while (m & (1<<w)) w++;
 
24
                        way_from_valid[m] = w;
 
25
                }
 
26
 
 
27
                for (u32 m = 0; m < 128; m++)
 
28
                {
 
29
                        u32 b[7];
 
30
                        for (int i = 0; i < 7; i++) b[i] = m & (1<<i);
 
31
                        u32 w;
 
32
                        if (b[0])
 
33
                                if (b[2])
 
34
                                        if (b[6])
 
35
                                                w = 7;
 
36
                                        else
 
37
                                                w = 6;
 
38
                                else
 
39
                                        if (b[5])
 
40
                                                w = 5;
 
41
                                        else
 
42
                                                w = 4;
 
43
                        else
 
44
                                if (b[1])
 
45
                                        if (b[4])
 
46
                                                w = 3;
 
47
                                        else
 
48
                                                w = 2;
 
49
                                else
 
50
                                        if (b[3])
 
51
                                                w = 1;
 
52
                                        else
 
53
                                                w = 0;
 
54
                        way_from_plru[m] = w;
 
55
                }
 
56
        }
 
57
 
 
58
        void InstructionCache::Reset()
 
59
        {
 
60
                memset(valid, 0, sizeof(valid));
 
61
                memset(plru, 0, sizeof(plru));
 
62
#ifdef FAST_ICACHE
 
63
                memset(lookup_table, 0xff, sizeof(lookup_table));
 
64
                memset(lookup_table_ex, 0xff, sizeof(lookup_table_ex));
 
65
                memset(lookup_table_vmem, 0xff, sizeof(lookup_table_vmem));
 
66
#endif
 
67
                JitInterface::ClearSafe();
 
68
        }
 
69
 
 
70
        void InstructionCache::Init()
 
71
        {
 
72
                memset(data, 0, sizeof(data));
 
73
                memset(tags, 0, sizeof(tags));
 
74
                memset(way_from_valid, 0, sizeof(way_from_valid));
 
75
                memset(way_from_plru, 0, sizeof(way_from_plru));
 
76
                
 
77
                Reset();
 
78
        }
 
79
 
 
80
        void InstructionCache::Invalidate(u32 addr)
 
81
        {
 
82
                if (!HID0.ICE)
 
83
                        return;
 
84
                // invalidates the whole set
 
85
                u32 set = (addr >> 5) & 0x7f;
 
86
#ifdef FAST_ICACHE
 
87
                for (int i = 0; i < 8; i++)
 
88
                        if (valid[set] & (1<<i))
 
89
                        {
 
90
                                if (tags[set][i] & (ICACHE_VMEM_BIT >> 12))
 
91
                                        lookup_table_vmem[((tags[set][i] << 7) | set) & 0xfffff] = 0xff;
 
92
                                else if (tags[set][i] & (ICACHE_EXRAM_BIT >> 12))
 
93
                                        lookup_table_ex[((tags[set][i] << 7) | set) & 0x1fffff] = 0xff;
 
94
                                else
 
95
                                        lookup_table[((tags[set][i] << 7) | set) & 0xfffff] = 0xff;
 
96
                        }
 
97
#endif
 
98
                valid[set] = 0;
 
99
                JitInterface::InvalidateICache(addr & ~0x1f, 32);
 
100
        }
 
101
 
 
102
        u32 InstructionCache::ReadInstruction(u32 addr)
 
103
        {               
 
104
                if (!HID0.ICE) // instruction cache is disabled
 
105
                        return Memory::ReadUnchecked_U32(addr);
 
106
                u32 set = (addr >> 5) & 0x7f;
 
107
                u32 tag = addr >> 12;
 
108
#ifdef FAST_ICACHE
 
109
                u32 t;
 
110
                if (addr & ICACHE_VMEM_BIT)
 
111
                {
 
112
                        t = lookup_table_vmem[(addr>>5) & 0xfffff];
 
113
                }
 
114
                else if (addr & ICACHE_EXRAM_BIT)
 
115
                {
 
116
                        t = lookup_table_ex[(addr>>5) & 0x1fffff];
 
117
                }
 
118
                else
 
119
                {
 
120
                        t = lookup_table[(addr>>5) & 0xfffff];
 
121
                }
 
122
#else
 
123
                u32 t = 0xff;
 
124
                for (u32 i = 0; i < 8; i++)
 
125
                        if (tags[set][i] == tag && (valid[set] & (1<<i)))
 
126
                        {
 
127
                                t = i;
 
128
                                break;
 
129
                        }
 
130
#endif
 
131
                if (t == 0xff) // load to the cache
 
132
                {
 
133
                        if (HID0.ILOCK) // instruction cache is locked
 
134
                                return Memory::ReadUnchecked_U32(addr);
 
135
                        // select a way
 
136
                        if (valid[set] != 0xff)
 
137
                                t = way_from_valid[valid[set]];
 
138
                        else
 
139
                                t = way_from_plru[plru[set]];
 
140
                        // load
 
141
                        u8 *p = Memory::GetPointer(addr & ~0x1f);
 
142
                        memcpy(data[set][t], p, 32);
 
143
#ifdef FAST_ICACHE
 
144
                        if (valid[set] & (1<<t))
 
145
                        {
 
146
                                if (tags[set][t] & (ICACHE_VMEM_BIT >> 12))
 
147
                                        lookup_table_vmem[((tags[set][t] << 7) | set) & 0xfffff] = 0xff;
 
148
                                else if (tags[set][t] & (ICACHE_EXRAM_BIT >> 12))
 
149
                                        lookup_table_ex[((tags[set][t] << 7) | set) & 0x1fffff] = 0xff;
 
150
                                else
 
151
                                        lookup_table[((tags[set][t] << 7) | set) & 0xfffff] = 0xff;
 
152
                        }
 
153
 
 
154
                        if (addr & ICACHE_VMEM_BIT)
 
155
                                lookup_table_vmem[(addr>>5) & 0xfffff] = t;
 
156
                        else if (addr & ICACHE_EXRAM_BIT)
 
157
                                lookup_table_ex[(addr>>5) & 0x1fffff] = t;
 
158
                        else
 
159
                                lookup_table[(addr>>5) & 0xfffff] = t;
 
160
#endif
 
161
                        tags[set][t] = tag;
 
162
                        valid[set] |= 1<<t;
 
163
                }
 
164
                // update plru
 
165
                plru[set] = (plru[set] & ~plru_mask[t]) | plru_value[t];
 
166
                u32 res = Common::swap32(data[set][t][(addr>>2)&7]);
 
167
                return res;
 
168
        }
 
169
 
 
170
}