diff options
| author | 2014-05-15 23:39:06 -0400 | |
|---|---|---|
| committer | 2014-05-15 23:39:06 -0400 | |
| commit | 9a642caee770db2632f4daa842b10801b47ffbfc (patch) | |
| tree | 5a1c63014d08d7200bc69c96549c49ba75553f2d /src | |
| parent | fixed armmmu imports (diff) | |
| download | yuzu-9a642caee770db2632f4daa842b10801b47ffbfc.tar.gz yuzu-9a642caee770db2632f4daa842b10801b47ffbfc.tar.xz yuzu-9a642caee770db2632f4daa842b10801b47ffbfc.zip | |
added missing skyeye mmu code
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | src/core/arm/interpreter/armmmu.h | 18 | ||||
| -rw-r--r-- | src/core/arm/interpreter/mmu/cache.cpp | 370 | ||||
| -rw-r--r-- | src/core/arm/interpreter/mmu/rb.cpp | 126 | ||||
| -rw-r--r-- | src/core/arm/interpreter/mmu/sa_mmu.cpp | 864 | ||||
| -rw-r--r-- | src/core/arm/interpreter/mmu/sa_mmu.h | 58 | ||||
| -rw-r--r-- | src/core/arm/interpreter/mmu/tlb.cpp | 307 | ||||
| -rw-r--r-- | src/core/arm/interpreter/mmu/tlb.h | 9 | ||||
| -rw-r--r-- | src/core/arm/interpreter/mmu/wb.cpp | 149 | ||||
| -rw-r--r-- | src/core/arm/interpreter/mmu/xscale_copro.cpp | 1388 | ||||
| -rw-r--r-- | src/core/core.vcxproj | 19 | ||||
| -rw-r--r-- | src/core/core.vcxproj.filters | 63 |
12 files changed, 3333 insertions, 44 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 0d4a0ca7a..35ef1c7b3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -19,6 +19,12 @@ set(SRCS core.cpp | |||
| 19 | arm/interpreter/vfp/vfpinsr.cpp | 19 | arm/interpreter/vfp/vfpinsr.cpp |
| 20 | arm/interpreter/vfp/vfpsingle.cpp | 20 | arm/interpreter/vfp/vfpsingle.cpp |
| 21 | arm/interpreter/mmu/arm1176jzf_s_mmu.cpp | 21 | arm/interpreter/mmu/arm1176jzf_s_mmu.cpp |
| 22 | arm/interpreter/mmu/cache.cpp | ||
| 23 | arm/interpreter/mmu/sa_mmu.cpp | ||
| 24 | arm/interpreter/mmu/rb.cpp | ||
| 25 | arm/interpreter/mmu/tlb.cpp | ||
| 26 | arm/interpreter/mmu/wb.cpp | ||
| 27 | arm/interpreter/mmu/xscale_copro.cpp | ||
| 22 | elf/elf_reader.cpp | 28 | elf/elf_reader.cpp |
| 23 | file_sys/directory_file_system.cpp | 29 | file_sys/directory_file_system.cpp |
| 24 | file_sys/meta_file_system.cpp | 30 | file_sys/meta_file_system.cpp |
diff --git a/src/core/arm/interpreter/armmmu.h b/src/core/arm/interpreter/armmmu.h index 2ceaa7c64..818108c9c 100644 --- a/src/core/arm/interpreter/armmmu.h +++ b/src/core/arm/interpreter/armmmu.h | |||
| @@ -178,12 +178,12 @@ typedef struct mmu_ops_s | |||
| 178 | #include "core/arm/interpreter/mmu/cache.h" | 178 | #include "core/arm/interpreter/mmu/cache.h" |
| 179 | 179 | ||
| 180 | /*special process mmu.h*/ | 180 | /*special process mmu.h*/ |
| 181 | //#include "core/arm/mmu/sa_mmu.h" | 181 | #include "core/arm/interpreter/mmu/sa_mmu.h" |
| 182 | //#include "core/arm/mmu/arm7100_mmu.h" | 182 | //#include "core/arm/interpreter/mmu/arm7100_mmu.h" |
| 183 | //#include "core/arm/mmu/arm920t_mmu.h" | 183 | //#include "core/arm/interpreter/mmu/arm920t_mmu.h" |
| 184 | //#include "core/arm/mmu/arm926ejs_mmu.h" | 184 | //#include "core/arm/interpreter/mmu/arm926ejs_mmu.h" |
| 185 | #include "core/arm/interpreter/mmu/arm1176jzf_s_mmu.h" | 185 | #include "core/arm/interpreter/mmu/arm1176jzf_s_mmu.h" |
| 186 | //#include "core/arm/mmu/cortex_a9_mmu.h" | 186 | //#include "core/arm/interpreter/mmu/cortex_a9_mmu.h" |
| 187 | 187 | ||
| 188 | typedef struct mmu_state_t | 188 | typedef struct mmu_state_t |
| 189 | { | 189 | { |
| @@ -213,13 +213,13 @@ typedef struct mmu_state_t | |||
| 213 | ARMword copro_access; // 15 | 213 | ARMword copro_access; // 15 |
| 214 | 214 | ||
| 215 | mmu_ops_t ops; | 215 | mmu_ops_t ops; |
| 216 | //union | 216 | union |
| 217 | //{ | 217 | { |
| 218 | //sa_mmu_t sa_mmu; | 218 | sa_mmu_t sa_mmu; |
| 219 | //arm7100_mmu_t arm7100_mmu; | 219 | //arm7100_mmu_t arm7100_mmu; |
| 220 | //arm920t_mmu_t arm920t_mmu; | 220 | //arm920t_mmu_t arm920t_mmu; |
| 221 | //arm926ejs_mmu_t arm926ejs_mmu; | 221 | //arm926ejs_mmu_t arm926ejs_mmu; |
| 222 | //} u; | 222 | } u; |
| 223 | } mmu_state_t; | 223 | } mmu_state_t; |
| 224 | 224 | ||
| 225 | int mmu_init (ARMul_State * state); | 225 | int mmu_init (ARMul_State * state); |
diff --git a/src/core/arm/interpreter/mmu/cache.cpp b/src/core/arm/interpreter/mmu/cache.cpp new file mode 100644 index 000000000..f3c4e0531 --- /dev/null +++ b/src/core/arm/interpreter/mmu/cache.cpp | |||
| @@ -0,0 +1,370 @@ | |||
| 1 | #include "core/arm/interpreter/armdefs.h" | ||
| 2 | |||
| 3 | /* mmu cache init | ||
| 4 | * | ||
| 5 | * @cache_t :cache_t to init | ||
| 6 | * @width :cache line width in byte | ||
| 7 | * @way :way of each cache set | ||
| 8 | * @set :cache set num | ||
| 9 | * | ||
| 10 | * $ -1: error | ||
| 11 | * 0: sucess | ||
| 12 | */ | ||
| 13 | int | ||
| 14 | mmu_cache_init (cache_s * cache_t, int width, int way, int set, int w_mode) | ||
| 15 | { | ||
| 16 | int i, j; | ||
| 17 | cache_set_t *sets; | ||
| 18 | cache_line_t *lines; | ||
| 19 | |||
| 20 | /*alloc cache set */ | ||
| 21 | sets = NULL; | ||
| 22 | lines = NULL; | ||
| 23 | //fprintf(stderr, "mmu_cache_init: mallloc beg size %d,sets 0x%x\n", sizeof(cache_set_t) * set,sets); | ||
| 24 | //exit(-1); | ||
| 25 | sets = (cache_set_t *) malloc (sizeof (cache_set_t) * set); | ||
| 26 | if (sets == NULL) { | ||
| 27 | ERROR_LOG(ARM11, "set malloc size %d\n", sizeof (cache_set_t) * set); | ||
| 28 | goto sets_error; | ||
| 29 | } | ||
| 30 | //fprintf(stderr, "mmu_cache_init: mallloc end sets 0x%x\n", sets); | ||
| 31 | cache_t->sets = sets; | ||
| 32 | |||
| 33 | /*init cache set */ | ||
| 34 | for (i = 0; i < set; i++) { | ||
| 35 | /*alloc cache line */ | ||
| 36 | lines = (cache_line_t *) malloc (sizeof (cache_line_t) * way); | ||
| 37 | if (lines == NULL) { | ||
| 38 | ERROR_LOG(ARM11, "line malloc size %d\n", | ||
| 39 | sizeof (cache_line_t) * way); | ||
| 40 | goto lines_error; | ||
| 41 | } | ||
| 42 | /*init cache line */ | ||
| 43 | for (j = 0; j < way; j++) { | ||
| 44 | lines[j].tag = 0; //invalid | ||
| 45 | lines[j].data = (ARMword *) malloc (width); | ||
| 46 | if (lines[j].data == NULL) { | ||
| 47 | ERROR_LOG(ARM11, "data alloc size %d\n", width); | ||
| 48 | goto data_error; | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | sets[i].lines = lines; | ||
| 53 | sets[i].cycle = 0; | ||
| 54 | |||
| 55 | } | ||
| 56 | cache_t->width = width; | ||
| 57 | cache_t->set = set; | ||
| 58 | cache_t->way = way; | ||
| 59 | cache_t->w_mode = w_mode; | ||
| 60 | return 0; | ||
| 61 | |||
| 62 | data_error: | ||
| 63 | /*free data */ | ||
| 64 | while (j-- > 0) | ||
| 65 | free (lines[j].data); | ||
| 66 | /*free data error line */ | ||
| 67 | free (lines); | ||
| 68 | lines_error: | ||
| 69 | /*free lines already alloced */ | ||
| 70 | while (i-- > 0) { | ||
| 71 | for (j = 0; j < way; j++) | ||
| 72 | free (sets[i].lines[j].data); | ||
| 73 | free (sets[i].lines); | ||
| 74 | } | ||
| 75 | /*free sets */ | ||
| 76 | free (sets); | ||
| 77 | sets_error: | ||
| 78 | return -1; | ||
| 79 | }; | ||
| 80 | |||
| 81 | /* free a cache_t's inner data, the ptr self is not freed, | ||
| 82 | * when needed do like below: | ||
| 83 | * mmu_cache_exit(cache); | ||
| 84 | * free(cache_t); | ||
| 85 | * | ||
| 86 | * @cache_t : the cache_t to free | ||
| 87 | */ | ||
| 88 | |||
| 89 | void | ||
| 90 | mmu_cache_exit (cache_s * cache_t) | ||
| 91 | { | ||
| 92 | int i, j; | ||
| 93 | cache_set_t *sets, *set; | ||
| 94 | cache_line_t *lines, *line; | ||
| 95 | |||
| 96 | /*free all set */ | ||
| 97 | sets = cache_t->sets; | ||
| 98 | for (set = sets, i = 0; i < cache_t->set; i++, set++) { | ||
| 99 | /*free all line */ | ||
| 100 | lines = set->lines; | ||
| 101 | for (line = lines, j = 0; j < cache_t->way; j++, line++) | ||
| 102 | free (line->data); | ||
| 103 | free (lines); | ||
| 104 | } | ||
| 105 | free (sets); | ||
| 106 | } | ||
| 107 | |||
| 108 | /* mmu cache search | ||
| 109 | * | ||
| 110 | * @state :ARMul_State | ||
| 111 | * @cache_t :cache_t to search | ||
| 112 | * @va :virtual address | ||
| 113 | * | ||
| 114 | * $ NULL: no cache match | ||
| 115 | * cache :cache matched | ||
| 116 | */ | ||
| 117 | cache_line_t * | ||
| 118 | mmu_cache_search (ARMul_State * state, cache_s * cache_t, ARMword va) | ||
| 119 | { | ||
| 120 | int i; | ||
| 121 | int set = va_cache_set (va, cache_t); | ||
| 122 | ARMword tag = va_cache_align (va, cache_t); | ||
| 123 | cache_line_t *cache; | ||
| 124 | |||
| 125 | cache_set_t *cache_set = cache_t->sets + set; | ||
| 126 | for (i = 0, cache = cache_set->lines; i < cache_t->way; i++, cache++) { | ||
| 127 | if ((cache->tag & TAG_VALID_FLAG) | ||
| 128 | && (tag == va_cache_align (cache->tag, cache_t))) | ||
| 129 | return cache; | ||
| 130 | } | ||
| 131 | return NULL; | ||
| 132 | } | ||
| 133 | |||
| 134 | /* mmu cache search by set/index | ||
| 135 | * | ||
| 136 | * @state :ARMul_State | ||
| 137 | * @cache_t :cache_t to search | ||
| 138 | * @index :set/index value. | ||
| 139 | * | ||
| 140 | * $ NULL: no cache match | ||
| 141 | * cache :cache matched | ||
| 142 | */ | ||
| 143 | cache_line_t * | ||
| 144 | mmu_cache_search_by_index (ARMul_State * state, cache_s * cache_t, | ||
| 145 | ARMword index) | ||
| 146 | { | ||
| 147 | int way = cache_t->way; | ||
| 148 | int set_v = index_cache_set (index, cache_t); | ||
| 149 | int i = 0, index_v = 0; | ||
| 150 | cache_set_t *set; | ||
| 151 | |||
| 152 | while ((way >>= 1) >= 1) | ||
| 153 | i++; | ||
| 154 | index_v = index >> (32 - i); | ||
| 155 | set = cache_t->sets + set_v; | ||
| 156 | |||
| 157 | return set->lines + index_v; | ||
| 158 | } | ||
| 159 | |||
| 160 | |||
| 161 | /* mmu cache alloc | ||
| 162 | * | ||
| 163 | * @state :ARMul_State | ||
| 164 | * @cache_t :cache_t to alloc from | ||
| 165 | * @va :virtual address that require cache alloc, need not cache aligned | ||
| 166 | * @pa :physical address of va | ||
| 167 | * | ||
| 168 | * $ cache_alloced, always alloc OK | ||
| 169 | */ | ||
| 170 | cache_line_t * | ||
| 171 | mmu_cache_alloc (ARMul_State * state, cache_s * cache_t, ARMword va, | ||
| 172 | ARMword pa) | ||
| 173 | { | ||
| 174 | cache_line_t *cache; | ||
| 175 | cache_set_t *set; | ||
| 176 | int i; | ||
| 177 | |||
| 178 | va = va_cache_align (va, cache_t); | ||
| 179 | pa = va_cache_align (pa, cache_t); | ||
| 180 | |||
| 181 | set = &cache_t->sets[va_cache_set (va, cache_t)]; | ||
| 182 | |||
| 183 | /*robin-round */ | ||
| 184 | cache = &set->lines[set->cycle++]; | ||
| 185 | if (set->cycle == cache_t->way) | ||
| 186 | set->cycle = 0; | ||
| 187 | |||
| 188 | if (cache_t->w_mode == CACHE_WRITE_BACK) { | ||
| 189 | ARMword t; | ||
| 190 | |||
| 191 | /*if cache valid, try to write back */ | ||
| 192 | if (cache->tag & TAG_VALID_FLAG) { | ||
| 193 | mmu_cache_write_back (state, cache_t, cache); | ||
| 194 | } | ||
| 195 | /*read in cache_line */ | ||
| 196 | t = pa; | ||
| 197 | for (i = 0; i < (cache_t->width >> WORD_SHT); | ||
| 198 | i++, t += WORD_SIZE) { | ||
| 199 | //cache->data[i] = mem_read_word (state, t); | ||
| 200 | bus_read(32, t, &cache->data[i]); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | /*store tag and pa */ | ||
| 204 | cache->tag = va | TAG_VALID_FLAG; | ||
| 205 | cache->pa = pa; | ||
| 206 | |||
| 207 | return cache; | ||
| 208 | }; | ||
| 209 | |||
| 210 | /* mmu_cache_write_back write cache data to memory | ||
| 211 | * @state | ||
| 212 | * @cache_t :cache_t of the cache line | ||
| 213 | * @cache : cache line | ||
| 214 | */ | ||
| 215 | void | ||
| 216 | mmu_cache_write_back (ARMul_State * state, cache_s * cache_t, | ||
| 217 | cache_line_t * cache) | ||
| 218 | { | ||
| 219 | ARMword pa = cache->pa; | ||
| 220 | int nw = cache_t->width >> WORD_SHT; | ||
| 221 | ARMword *data = cache->data; | ||
| 222 | int i; | ||
| 223 | int t0, t1, t2; | ||
| 224 | |||
| 225 | if ((cache->tag & 1) == 0) | ||
| 226 | return; | ||
| 227 | |||
| 228 | switch (cache-> | ||
| 229 | tag & ~1 & (TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY)) { | ||
| 230 | case 0: | ||
| 231 | return; | ||
| 232 | case TAG_FIRST_HALF_DIRTY: | ||
| 233 | nw /= 2; | ||
| 234 | break; | ||
| 235 | case TAG_LAST_HALF_DIRTY: | ||
| 236 | nw /= 2; | ||
| 237 | pa += nw << WORD_SHT; | ||
| 238 | data += nw; | ||
| 239 | break; | ||
| 240 | case TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY: | ||
| 241 | break; | ||
| 242 | } | ||
| 243 | for (i = 0; i < nw; i++, data++, pa += WORD_SIZE) | ||
| 244 | //mem_write_word (state, pa, *data); | ||
| 245 | bus_write(32, pa, *data); | ||
| 246 | |||
| 247 | cache->tag &= ~(TAG_FIRST_HALF_DIRTY | TAG_LAST_HALF_DIRTY); | ||
| 248 | }; | ||
| 249 | |||
| 250 | |||
| 251 | /* mmu_cache_clean: clean a cache of va in cache_t | ||
| 252 | * | ||
| 253 | * @state :ARMul_State | ||
| 254 | * @cache_t :cache_t to clean | ||
| 255 | * @va :virtaul address | ||
| 256 | */ | ||
| 257 | void | ||
| 258 | mmu_cache_clean (ARMul_State * state, cache_s * cache_t, ARMword va) | ||
| 259 | { | ||
| 260 | cache_line_t *cache; | ||
| 261 | |||
| 262 | cache = mmu_cache_search (state, cache_t, va); | ||
| 263 | if (cache) | ||
| 264 | mmu_cache_write_back (state, cache_t, cache); | ||
| 265 | } | ||
| 266 | |||
| 267 | /* mmu_cache_clean_by_index: clean a cache by set/index format value | ||
| 268 | * | ||
| 269 | * @state :ARMul_State | ||
| 270 | * @cache_t :cache_t to clean | ||
| 271 | * @va :set/index format value | ||
| 272 | */ | ||
| 273 | void | ||
| 274 | mmu_cache_clean_by_index (ARMul_State * state, cache_s * cache_t, | ||
| 275 | ARMword index) | ||
| 276 | { | ||
| 277 | cache_line_t *cache; | ||
| 278 | |||
| 279 | cache = mmu_cache_search_by_index (state, cache_t, index); | ||
| 280 | if (cache) | ||
| 281 | mmu_cache_write_back (state, cache_t, cache); | ||
| 282 | } | ||
| 283 | |||
| 284 | /* mmu_cache_invalidate : invalidate a cache of va | ||
| 285 | * | ||
| 286 | * @state :ARMul_State | ||
| 287 | * @cache_t :cache_t to invalid | ||
| 288 | * @va :virt_addr to invalid | ||
| 289 | */ | ||
| 290 | void | ||
| 291 | mmu_cache_invalidate (ARMul_State * state, cache_s * cache_t, ARMword va) | ||
| 292 | { | ||
| 293 | cache_line_t *cache; | ||
| 294 | |||
| 295 | cache = mmu_cache_search (state, cache_t, va); | ||
| 296 | if (cache) { | ||
| 297 | mmu_cache_write_back (state, cache_t, cache); | ||
| 298 | cache->tag = 0; | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | /* mmu_cache_invalidate_by_index : invalidate a cache by index format | ||
| 303 | * | ||
| 304 | * @state :ARMul_State | ||
| 305 | * @cache_t :cache_t to invalid | ||
| 306 | * @index :set/index data | ||
| 307 | */ | ||
| 308 | void | ||
| 309 | mmu_cache_invalidate_by_index (ARMul_State * state, cache_s * cache_t, | ||
| 310 | ARMword index) | ||
| 311 | { | ||
| 312 | cache_line_t *cache; | ||
| 313 | |||
| 314 | cache = mmu_cache_search_by_index (state, cache_t, index); | ||
| 315 | if (cache) { | ||
| 316 | mmu_cache_write_back (state, cache_t, cache); | ||
| 317 | cache->tag = 0; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | /* mmu_cache_invalidate_all | ||
| 322 | * | ||
| 323 | * @state: | ||
| 324 | * @cache_t | ||
| 325 | * */ | ||
| 326 | void | ||
| 327 | mmu_cache_invalidate_all (ARMul_State * state, cache_s * cache_t) | ||
| 328 | { | ||
| 329 | int i, j; | ||
| 330 | cache_set_t *set; | ||
| 331 | cache_line_t *cache; | ||
| 332 | |||
| 333 | set = cache_t->sets; | ||
| 334 | for (i = 0; i < cache_t->set; i++, set++) { | ||
| 335 | cache = set->lines; | ||
| 336 | for (j = 0; j < cache_t->way; j++, cache++) { | ||
| 337 | mmu_cache_write_back (state, cache_t, cache); | ||
| 338 | cache->tag = 0; | ||
| 339 | } | ||
| 340 | } | ||
| 341 | }; | ||
| 342 | |||
| 343 | void | ||
| 344 | mmu_cache_soft_flush (ARMul_State * state, cache_s * cache_t, ARMword pa) | ||
| 345 | { | ||
| 346 | ARMword set, way; | ||
| 347 | cache_line_t *cache; | ||
| 348 | pa = (pa / cache_t->width); | ||
| 349 | way = pa & (cache_t->way - 1); | ||
| 350 | set = (pa / cache_t->way) & (cache_t->set - 1); | ||
| 351 | cache = &cache_t->sets[set].lines[way]; | ||
| 352 | |||
| 353 | mmu_cache_write_back (state, cache_t, cache); | ||
| 354 | cache->tag = 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | cache_line_t* mmu_cache_dirty_cache(ARMul_State *state,cache_s *cache){ | ||
| 358 | int i; | ||
| 359 | int j; | ||
| 360 | cache_line_t *cache_line = NULL; | ||
| 361 | cache_set_t *cache_set = cache->sets; | ||
| 362 | int sets = cache->set; | ||
| 363 | for (i = 0; i < sets; i++){ | ||
| 364 | for(j = 0,cache_line = &cache_set[i].lines[0]; j < cache->way; j++,cache_line++){ | ||
| 365 | if((cache_line->tag & TAG_FIRST_HALF_DIRTY) || (cache_line->tag & TAG_LAST_HALF_DIRTY)) | ||
| 366 | return cache_line; | ||
| 367 | } | ||
| 368 | } | ||
| 369 | return NULL; | ||
| 370 | } | ||
diff --git a/src/core/arm/interpreter/mmu/rb.cpp b/src/core/arm/interpreter/mmu/rb.cpp new file mode 100644 index 000000000..07b11e311 --- /dev/null +++ b/src/core/arm/interpreter/mmu/rb.cpp | |||
| @@ -0,0 +1,126 @@ | |||
| 1 | #include "core/arm/interpreter/armdefs.h" | ||
| 2 | |||
| 3 | /*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu*/ | ||
| 4 | ARMword rb_masks[] = { | ||
| 5 | 0x0, //RB_INVALID | ||
| 6 | 4, //RB_1 | ||
| 7 | 16, //RB_4 | ||
| 8 | 32, //RB_8 | ||
| 9 | }; | ||
| 10 | |||
| 11 | /*mmu_rb_init | ||
| 12 | * @rb_t :rb_t to init | ||
| 13 | * @num :number of entry | ||
| 14 | * */ | ||
| 15 | int | ||
| 16 | mmu_rb_init (rb_s * rb_t, int num) | ||
| 17 | { | ||
| 18 | int i; | ||
| 19 | rb_entry_t *entrys; | ||
| 20 | |||
| 21 | entrys = (rb_entry_t *) malloc (sizeof (*entrys) * num); | ||
| 22 | if (entrys == NULL) { | ||
| 23 | printf ("SKYEYE:mmu_rb_init malloc error\n"); | ||
| 24 | return -1; | ||
| 25 | } | ||
| 26 | for (i = 0; i < num; i++) { | ||
| 27 | entrys[i].type = RB_INVALID; | ||
| 28 | entrys[i].fault = NO_FAULT; | ||
| 29 | } | ||
| 30 | |||
| 31 | rb_t->entrys = entrys; | ||
| 32 | rb_t->num = num; | ||
| 33 | return 0; | ||
| 34 | } | ||
| 35 | |||
| 36 | /*mmu_rb_exit*/ | ||
| 37 | void | ||
| 38 | mmu_rb_exit (rb_s * rb_t) | ||
| 39 | { | ||
| 40 | free (rb_t->entrys); | ||
| 41 | }; | ||
| 42 | |||
| 43 | /*mmu_rb_search | ||
| 44 | * @rb_t :rb_t to serach | ||
| 45 | * @va :va address to math | ||
| 46 | * | ||
| 47 | * $ NULL :not match | ||
| 48 | * NO-NULL: | ||
| 49 | * */ | ||
| 50 | rb_entry_t * | ||
| 51 | mmu_rb_search (rb_s * rb_t, ARMword va) | ||
| 52 | { | ||
| 53 | int i; | ||
| 54 | rb_entry_t *rb = rb_t->entrys; | ||
| 55 | |||
| 56 | DEBUG_LOG(ARM11, "va = %x\n", va); | ||
| 57 | for (i = 0; i < rb_t->num; i++, rb++) { | ||
| 58 | //2004-06-06 lyh bug from wenye@cs.ucsb.edu | ||
| 59 | if (rb->type) { | ||
| 60 | if ((va >= rb->va) | ||
| 61 | && (va < (rb->va + rb_masks[rb->type]))) | ||
| 62 | return rb; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | return NULL; | ||
| 66 | }; | ||
| 67 | |||
| 68 | void | ||
| 69 | mmu_rb_invalidate_entry (rb_s * rb_t, int i) | ||
| 70 | { | ||
| 71 | rb_t->entrys[i].type = RB_INVALID; | ||
| 72 | } | ||
| 73 | |||
| 74 | void | ||
| 75 | mmu_rb_invalidate_all (rb_s * rb_t) | ||
| 76 | { | ||
| 77 | int i; | ||
| 78 | |||
| 79 | for (i = 0; i < rb_t->num; i++) | ||
| 80 | mmu_rb_invalidate_entry (rb_t, i); | ||
| 81 | }; | ||
| 82 | |||
| 83 | void | ||
| 84 | mmu_rb_load (ARMul_State * state, rb_s * rb_t, int i_rb, int type, ARMword va) | ||
| 85 | { | ||
| 86 | rb_entry_t *rb; | ||
| 87 | int i; | ||
| 88 | ARMword max_start, min_end; | ||
| 89 | fault_t fault; | ||
| 90 | tlb_entry_t *tlb; | ||
| 91 | |||
| 92 | /*align va according to type */ | ||
| 93 | va &= ~(rb_masks[type] - 1); | ||
| 94 | /*invalidate all RB match [va, va + rb_masks[type]] */ | ||
| 95 | for (rb = rb_t->entrys, i = 0; i < rb_t->num; i++, rb++) { | ||
| 96 | if (rb->type) { | ||
| 97 | max_start = max (va, rb->va); | ||
| 98 | min_end = | ||
| 99 | min (va + rb_masks[type], | ||
| 100 | rb->va + rb_masks[rb->type]); | ||
| 101 | if (max_start < min_end) | ||
| 102 | rb->type = RB_INVALID; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | /*load word */ | ||
| 106 | rb = &rb_t->entrys[i_rb]; | ||
| 107 | rb->type = type; | ||
| 108 | fault = translate (state, va, D_TLB (), &tlb); | ||
| 109 | if (fault) { | ||
| 110 | rb->fault = fault; | ||
| 111 | return; | ||
| 112 | } | ||
| 113 | fault = check_access (state, va, tlb, 1); | ||
| 114 | if (fault) { | ||
| 115 | rb->fault = fault; | ||
| 116 | return; | ||
| 117 | } | ||
| 118 | |||
| 119 | rb->fault = NO_FAULT; | ||
| 120 | va = tlb_va_to_pa (tlb, va); | ||
| 121 | //2004-06-06 lyh bug from wenye@cs.ucsb.edu | ||
| 122 | for (i = 0; i < (rb_masks[type] / 4); i++, va += WORD_SIZE) { | ||
| 123 | //rb->data[i] = mem_read_word (state, va); | ||
| 124 | bus_read(32, va, &rb->data[i]); | ||
| 125 | }; | ||
| 126 | } | ||
diff --git a/src/core/arm/interpreter/mmu/sa_mmu.cpp b/src/core/arm/interpreter/mmu/sa_mmu.cpp new file mode 100644 index 000000000..eff5002de --- /dev/null +++ b/src/core/arm/interpreter/mmu/sa_mmu.cpp | |||
| @@ -0,0 +1,864 @@ | |||
| 1 | /* | ||
| 2 | armmmu.c - Memory Management Unit emulation. | ||
| 3 | ARMulator extensions for the ARM7100 family. | ||
| 4 | Copyright (C) 1999 Ben Williamson | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program; if not, write to the Free Software | ||
| 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <assert.h> | ||
| 22 | #include <string.h> | ||
| 23 | |||
| 24 | #include "core/arm/interpreter/armdefs.h" | ||
| 25 | |||
| 26 | /** | ||
| 27 | * The interface of read data from bus | ||
| 28 | */ | ||
| 29 | int bus_read(short size, int addr, uint32_t * value) { | ||
| 30 | ERROR_LOG(ARM11, "unimplemented bus_read"); | ||
| 31 | return 0; | ||
| 32 | } | ||
| 33 | |||
| 34 | /** | ||
| 35 | * The interface of write data from bus | ||
| 36 | */ | ||
| 37 | int bus_write(short size, int addr, uint32_t value) { | ||
| 38 | ERROR_LOG(ARM11, "unimplemented bus_write"); | ||
| 39 | return 0; | ||
| 40 | } | ||
| 41 | |||
| 42 | |||
| 43 | typedef struct sa_mmu_desc_s | ||
| 44 | { | ||
| 45 | int i_tlb; | ||
| 46 | cache_desc_t i_cache; | ||
| 47 | |||
| 48 | int d_tlb; | ||
| 49 | cache_desc_t main_d_cache; | ||
| 50 | cache_desc_t mini_d_cache; | ||
| 51 | int rb; | ||
| 52 | wb_desc_t wb; | ||
| 53 | } sa_mmu_desc_t; | ||
| 54 | |||
| 55 | static sa_mmu_desc_t sa11xx_mmu_desc = { | ||
| 56 | 32, | ||
| 57 | {32, 32, 16, CACHE_WRITE_BACK}, | ||
| 58 | |||
| 59 | 32, | ||
| 60 | {32, 32, 8, CACHE_WRITE_BACK}, | ||
| 61 | {32, 2, 8, CACHE_WRITE_BACK}, | ||
| 62 | 4, | ||
| 63 | //{8, 4}, for word size | ||
| 64 | {8, 16}, //for byte size, chy 2003-07-11 | ||
| 65 | }; | ||
| 66 | |||
| 67 | static fault_t sa_mmu_write (ARMul_State * state, ARMword va, ARMword data, | ||
| 68 | ARMword datatype); | ||
| 69 | static fault_t sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data, | ||
| 70 | ARMword datatype); | ||
| 71 | static fault_t update_cache (ARMul_State * state, ARMword va, ARMword data, | ||
| 72 | ARMword datatype, cache_line_t * cache, | ||
| 73 | cache_s * cache_t, ARMword real_va); | ||
| 74 | |||
| 75 | void | ||
| 76 | mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa, | ||
| 77 | ARMbyte * data, int n); | ||
| 78 | int | ||
| 79 | sa_mmu_init (ARMul_State * state) | ||
| 80 | { | ||
| 81 | sa_mmu_desc_t *desc; | ||
| 82 | cache_desc_t *c_desc; | ||
| 83 | |||
| 84 | state->mmu.control = 0x70; | ||
| 85 | state->mmu.translation_table_base = 0xDEADC0DE; | ||
| 86 | state->mmu.domain_access_control = 0xDEADC0DE; | ||
| 87 | state->mmu.fault_status = 0; | ||
| 88 | state->mmu.fault_address = 0; | ||
| 89 | state->mmu.process_id = 0; | ||
| 90 | |||
| 91 | desc = &sa11xx_mmu_desc; | ||
| 92 | if (mmu_tlb_init (I_TLB (), desc->i_tlb)) { | ||
| 93 | ERROR_LOG(ARM11, "i_tlb init %d\n", -1); | ||
| 94 | goto i_tlb_init_error; | ||
| 95 | } | ||
| 96 | |||
| 97 | c_desc = &desc->i_cache; | ||
| 98 | if (mmu_cache_init (I_CACHE (), c_desc->width, c_desc->way, | ||
| 99 | c_desc->set, c_desc->w_mode)) { | ||
| 100 | ERROR_LOG(ARM11, "i_cache init %d\n", -1); | ||
| 101 | goto i_cache_init_error; | ||
| 102 | } | ||
| 103 | |||
| 104 | if (mmu_tlb_init (D_TLB (), desc->d_tlb)) { | ||
| 105 | ERROR_LOG(ARM11, "d_tlb init %d\n", -1); | ||
| 106 | goto d_tlb_init_error; | ||
| 107 | } | ||
| 108 | |||
| 109 | c_desc = &desc->main_d_cache; | ||
| 110 | if (mmu_cache_init (MAIN_D_CACHE (), c_desc->width, c_desc->way, | ||
| 111 | c_desc->set, c_desc->w_mode)) { | ||
| 112 | ERROR_LOG(ARM11, "main_d_cache init %d\n", -1); | ||
| 113 | goto main_d_cache_init_error; | ||
| 114 | } | ||
| 115 | |||
| 116 | c_desc = &desc->mini_d_cache; | ||
| 117 | if (mmu_cache_init (MINI_D_CACHE (), c_desc->width, c_desc->way, | ||
| 118 | c_desc->set, c_desc->w_mode)) { | ||
| 119 | ERROR_LOG(ARM11, "mini_d_cache init %d\n", -1); | ||
| 120 | goto mini_d_cache_init_error; | ||
| 121 | } | ||
| 122 | |||
| 123 | if (mmu_wb_init (WB (), desc->wb.num, desc->wb.nb)) { | ||
| 124 | ERROR_LOG(ARM11, "wb init %d\n", -1); | ||
| 125 | goto wb_init_error; | ||
| 126 | } | ||
| 127 | |||
| 128 | if (mmu_rb_init (RB (), desc->rb)) { | ||
| 129 | ERROR_LOG(ARM11, "rb init %d\n", -1); | ||
| 130 | goto rb_init_error; | ||
| 131 | } | ||
| 132 | return 0; | ||
| 133 | |||
| 134 | rb_init_error: | ||
| 135 | mmu_wb_exit (WB ()); | ||
| 136 | wb_init_error: | ||
| 137 | mmu_cache_exit (MINI_D_CACHE ()); | ||
| 138 | mini_d_cache_init_error: | ||
| 139 | mmu_cache_exit (MAIN_D_CACHE ()); | ||
| 140 | main_d_cache_init_error: | ||
| 141 | mmu_tlb_exit (D_TLB ()); | ||
| 142 | d_tlb_init_error: | ||
| 143 | mmu_cache_exit (I_CACHE ()); | ||
| 144 | i_cache_init_error: | ||
| 145 | mmu_tlb_exit (I_TLB ()); | ||
| 146 | i_tlb_init_error: | ||
| 147 | return -1; | ||
| 148 | } | ||
| 149 | |||
| 150 | void | ||
| 151 | sa_mmu_exit (ARMul_State * state) | ||
| 152 | { | ||
| 153 | mmu_rb_exit (RB ()); | ||
| 154 | mmu_wb_exit (WB ()); | ||
| 155 | mmu_cache_exit (MINI_D_CACHE ()); | ||
| 156 | mmu_cache_exit (MAIN_D_CACHE ()); | ||
| 157 | mmu_tlb_exit (D_TLB ()); | ||
| 158 | mmu_cache_exit (I_CACHE ()); | ||
| 159 | mmu_tlb_exit (I_TLB ()); | ||
| 160 | }; | ||
| 161 | |||
| 162 | |||
| 163 | static fault_t | ||
| 164 | sa_mmu_load_instr (ARMul_State * state, ARMword va, ARMword * instr) | ||
| 165 | { | ||
| 166 | fault_t fault; | ||
| 167 | tlb_entry_t *tlb; | ||
| 168 | cache_line_t *cache; | ||
| 169 | int c; //cache bit | ||
| 170 | ARMword pa; //physical addr | ||
| 171 | |||
| 172 | static int debug_count = 0; //used for debug | ||
| 173 | |||
| 174 | DEBUG_LOG(ARM11, "va = %x\n", va); | ||
| 175 | |||
| 176 | va = mmu_pid_va_map (va); | ||
| 177 | if (MMU_Enabled) { | ||
| 178 | /*align check */ | ||
| 179 | if ((va & (WORD_SIZE - 1)) && MMU_Aligned) { | ||
| 180 | DEBUG_LOG(ARM11, "align\n"); | ||
| 181 | return ALIGNMENT_FAULT; | ||
| 182 | } | ||
| 183 | else | ||
| 184 | va &= ~(WORD_SIZE - 1); | ||
| 185 | |||
| 186 | /*translate tlb */ | ||
| 187 | fault = translate (state, va, I_TLB (), &tlb); | ||
| 188 | if (fault) { | ||
| 189 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 190 | return fault; | ||
| 191 | } | ||
| 192 | |||
| 193 | /*check access */ | ||
| 194 | fault = check_access (state, va, tlb, 1); | ||
| 195 | if (fault) { | ||
| 196 | DEBUG_LOG(ARM11, "check_fault\n"); | ||
| 197 | return fault; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | /*search cache no matter MMU enabled/disabled */ | ||
| 202 | cache = mmu_cache_search (state, I_CACHE (), va); | ||
| 203 | if (cache) { | ||
| 204 | *instr = cache->data[va_cache_index (va, I_CACHE ())]; | ||
| 205 | return NO_FAULT; | ||
| 206 | } | ||
| 207 | |||
| 208 | /*if MMU disabled or C flag is set alloc cache */ | ||
| 209 | if (MMU_Disabled) { | ||
| 210 | c = 1; | ||
| 211 | pa = va; | ||
| 212 | } | ||
| 213 | else { | ||
| 214 | c = tlb_c_flag (tlb); | ||
| 215 | pa = tlb_va_to_pa (tlb, va); | ||
| 216 | } | ||
| 217 | |||
| 218 | if (c) { | ||
| 219 | int index; | ||
| 220 | |||
| 221 | debug_count++; | ||
| 222 | cache = mmu_cache_alloc (state, I_CACHE (), va, pa); | ||
| 223 | index = va_cache_index (va, I_CACHE ()); | ||
| 224 | *instr = cache->data[va_cache_index (va, I_CACHE ())]; | ||
| 225 | } | ||
| 226 | else | ||
| 227 | //*instr = mem_read_word (state, pa); | ||
| 228 | bus_read(32, pa, instr); | ||
| 229 | |||
| 230 | return NO_FAULT; | ||
| 231 | }; | ||
| 232 | |||
| 233 | |||
| 234 | |||
| 235 | static fault_t | ||
| 236 | sa_mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data) | ||
| 237 | { | ||
| 238 | //ARMword temp,offset; | ||
| 239 | fault_t fault; | ||
| 240 | fault = sa_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE); | ||
| 241 | return fault; | ||
| 242 | } | ||
| 243 | |||
| 244 | static fault_t | ||
| 245 | sa_mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data) | ||
| 246 | { | ||
| 247 | //ARMword temp,offset; | ||
| 248 | fault_t fault; | ||
| 249 | fault = sa_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE); | ||
| 250 | return fault; | ||
| 251 | } | ||
| 252 | |||
| 253 | static fault_t | ||
| 254 | sa_mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data) | ||
| 255 | { | ||
| 256 | return sa_mmu_read (state, virt_addr, data, ARM_WORD_TYPE); | ||
| 257 | } | ||
| 258 | |||
| 259 | |||
| 260 | |||
| 261 | |||
| 262 | static fault_t | ||
| 263 | sa_mmu_read (ARMul_State * state, ARMword va, ARMword * data, | ||
| 264 | ARMword datatype) | ||
| 265 | { | ||
| 266 | fault_t fault; | ||
| 267 | rb_entry_t *rb; | ||
| 268 | tlb_entry_t *tlb; | ||
| 269 | cache_line_t *cache; | ||
| 270 | ARMword pa, real_va, temp, offset; | ||
| 271 | |||
| 272 | DEBUG_LOG(ARM11, "va = %x\n", va); | ||
| 273 | |||
| 274 | va = mmu_pid_va_map (va); | ||
| 275 | real_va = va; | ||
| 276 | /*if MMU disabled, memory_read */ | ||
| 277 | if (MMU_Disabled) { | ||
| 278 | //*data = mem_read_word(state, va); | ||
| 279 | if (datatype == ARM_BYTE_TYPE) | ||
| 280 | //*data = mem_read_byte (state, va); | ||
| 281 | bus_read(8, va, data); | ||
| 282 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 283 | //*data = mem_read_halfword (state, va); | ||
| 284 | bus_read(16, va, data); | ||
| 285 | else if (datatype == ARM_WORD_TYPE) | ||
| 286 | //*data = mem_read_word (state, va); | ||
| 287 | bus_read(32, va, data); | ||
| 288 | else { | ||
| 289 | printf ("SKYEYE:1 sa_mmu_read error: unknown data type %d\n", datatype); | ||
| 290 | // skyeye_exit (-1); | ||
| 291 | } | ||
| 292 | |||
| 293 | return NO_FAULT; | ||
| 294 | } | ||
| 295 | |||
| 296 | /*align check */ | ||
| 297 | if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) || | ||
| 298 | ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) { | ||
| 299 | DEBUG_LOG(ARM11, "align\n"); | ||
| 300 | return ALIGNMENT_FAULT; | ||
| 301 | } // else | ||
| 302 | |||
| 303 | va &= ~(WORD_SIZE - 1); | ||
| 304 | |||
| 305 | /*translate va to tlb */ | ||
| 306 | fault = translate (state, va, D_TLB (), &tlb); | ||
| 307 | if (fault) { | ||
| 308 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 309 | return fault; | ||
| 310 | } | ||
| 311 | /*check access permission */ | ||
| 312 | fault = check_access (state, va, tlb, 1); | ||
| 313 | if (fault) | ||
| 314 | return fault; | ||
| 315 | /*search in read buffer */ | ||
| 316 | rb = mmu_rb_search (RB (), va); | ||
| 317 | if (rb) { | ||
| 318 | if (rb->fault) | ||
| 319 | return rb->fault; | ||
| 320 | *data = rb->data[(va & (rb_masks[rb->type] - 1)) >> WORD_SHT]; | ||
| 321 | goto datatrans; | ||
| 322 | //return 0; | ||
| 323 | }; | ||
| 324 | /*search main cache */ | ||
| 325 | cache = mmu_cache_search (state, MAIN_D_CACHE (), va); | ||
| 326 | if (cache) { | ||
| 327 | *data = cache->data[va_cache_index (va, MAIN_D_CACHE ())]; | ||
| 328 | goto datatrans; | ||
| 329 | //return 0; | ||
| 330 | } | ||
| 331 | /*search mini cache */ | ||
| 332 | cache = mmu_cache_search (state, MINI_D_CACHE (), va); | ||
| 333 | if (cache) { | ||
| 334 | *data = cache->data[va_cache_index (va, MINI_D_CACHE ())]; | ||
| 335 | goto datatrans; | ||
| 336 | //return 0; | ||
| 337 | } | ||
| 338 | |||
| 339 | /*get phy_addr */ | ||
| 340 | pa = tlb_va_to_pa (tlb, va); | ||
| 341 | if ((pa >= 0xe0000000) && (pa < 0xe8000000)) { | ||
| 342 | if (tlb_c_flag (tlb)) { | ||
| 343 | if (tlb_b_flag (tlb)) { | ||
| 344 | mmu_cache_soft_flush (state, MAIN_D_CACHE (), | ||
| 345 | pa); | ||
| 346 | } | ||
| 347 | else { | ||
| 348 | mmu_cache_soft_flush (state, MINI_D_CACHE (), | ||
| 349 | pa); | ||
| 350 | } | ||
| 351 | } | ||
| 352 | return NO_FAULT; | ||
| 353 | } | ||
| 354 | |||
| 355 | /*if Buffer, drain Write Buffer first */ | ||
| 356 | if (tlb_b_flag (tlb)) | ||
| 357 | mmu_wb_drain_all (state, WB ()); | ||
| 358 | |||
| 359 | /*alloc cache or mem_read */ | ||
| 360 | if (tlb_c_flag (tlb) && MMU_DCacheEnabled) { | ||
| 361 | cache_s *cache_t; | ||
| 362 | |||
| 363 | if (tlb_b_flag (tlb)) | ||
| 364 | cache_t = MAIN_D_CACHE (); | ||
| 365 | else | ||
| 366 | cache_t = MINI_D_CACHE (); | ||
| 367 | cache = mmu_cache_alloc (state, cache_t, va, pa); | ||
| 368 | *data = cache->data[va_cache_index (va, cache_t)]; | ||
| 369 | } | ||
| 370 | else { | ||
| 371 | //*data = mem_read_word(state, pa); | ||
| 372 | if (datatype == ARM_BYTE_TYPE) | ||
| 373 | //*data = mem_read_byte (state, pa | (real_va & 3)); | ||
| 374 | bus_read(8, pa | (real_va & 3), data); | ||
| 375 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 376 | //*data = mem_read_halfword (state, pa | (real_va & 2)); | ||
| 377 | bus_read(16, pa | (real_va & 2), data); | ||
| 378 | else if (datatype == ARM_WORD_TYPE) | ||
| 379 | //*data = mem_read_word (state, pa); | ||
| 380 | bus_read(32, pa, data); | ||
| 381 | else { | ||
| 382 | printf ("SKYEYE:2 sa_mmu_read error: unknown data type %d\n", datatype); | ||
| 383 | // skyeye_exit (-1); | ||
| 384 | } | ||
| 385 | return NO_FAULT; | ||
| 386 | } | ||
| 387 | |||
| 388 | |||
| 389 | datatrans: | ||
| 390 | if (datatype == ARM_HALFWORD_TYPE) { | ||
| 391 | temp = *data; | ||
| 392 | offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */ | ||
| 393 | *data = (temp >> offset) & 0xffff; | ||
| 394 | } | ||
| 395 | else if (datatype == ARM_BYTE_TYPE) { | ||
| 396 | temp = *data; | ||
| 397 | offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */ | ||
| 398 | *data = (temp >> offset & 0xffL); | ||
| 399 | } | ||
| 400 | end: | ||
| 401 | return NO_FAULT; | ||
| 402 | } | ||
| 403 | |||
| 404 | |||
| 405 | static fault_t | ||
| 406 | sa_mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data) | ||
| 407 | { | ||
| 408 | return sa_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE); | ||
| 409 | } | ||
| 410 | |||
| 411 | static fault_t | ||
| 412 | sa_mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data) | ||
| 413 | { | ||
| 414 | return sa_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE); | ||
| 415 | } | ||
| 416 | |||
| 417 | static fault_t | ||
| 418 | sa_mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data) | ||
| 419 | { | ||
| 420 | return sa_mmu_write (state, virt_addr, data, ARM_WORD_TYPE); | ||
| 421 | } | ||
| 422 | |||
| 423 | |||
| 424 | |||
| 425 | static fault_t | ||
| 426 | sa_mmu_write (ARMul_State * state, ARMword va, ARMword data, ARMword datatype) | ||
| 427 | { | ||
| 428 | tlb_entry_t *tlb; | ||
| 429 | cache_line_t *cache; | ||
| 430 | int b; | ||
| 431 | ARMword pa, real_va; | ||
| 432 | fault_t fault; | ||
| 433 | |||
| 434 | DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data); | ||
| 435 | va = mmu_pid_va_map (va); | ||
| 436 | real_va = va; | ||
| 437 | |||
| 438 | /*search instruction cache */ | ||
| 439 | cache = mmu_cache_search (state, I_CACHE (), va); | ||
| 440 | if (cache) { | ||
| 441 | update_cache (state, va, data, datatype, cache, I_CACHE (), | ||
| 442 | real_va); | ||
| 443 | } | ||
| 444 | |||
| 445 | if (MMU_Disabled) { | ||
| 446 | //mem_write_word(state, va, data); | ||
| 447 | if (datatype == ARM_BYTE_TYPE) | ||
| 448 | //mem_write_byte (state, va, data); | ||
| 449 | bus_write(8, va, data); | ||
| 450 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 451 | //mem_write_halfword (state, va, data); | ||
| 452 | bus_write(16, va, data); | ||
| 453 | else if (datatype == ARM_WORD_TYPE) | ||
| 454 | //mem_write_word (state, va, data); | ||
| 455 | bus_write(32, va, data); | ||
| 456 | else { | ||
| 457 | printf ("SKYEYE:1 sa_mmu_write error: unknown data type %d\n", datatype); | ||
| 458 | // skyeye_exit (-1); | ||
| 459 | } | ||
| 460 | |||
| 461 | return NO_FAULT; | ||
| 462 | } | ||
| 463 | /*align check */ | ||
| 464 | //if ((va & (WORD_SIZE - 1)) && MMU_Aligned){ | ||
| 465 | if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) || | ||
| 466 | ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) { | ||
| 467 | DEBUG_LOG(ARM11, "align\n"); | ||
| 468 | return ALIGNMENT_FAULT; | ||
| 469 | } //else | ||
| 470 | va &= ~(WORD_SIZE - 1); | ||
| 471 | /*tlb translate */ | ||
| 472 | fault = translate (state, va, D_TLB (), &tlb); | ||
| 473 | if (fault) { | ||
| 474 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 475 | return fault; | ||
| 476 | } | ||
| 477 | /*tlb check access */ | ||
| 478 | fault = check_access (state, va, tlb, 0); | ||
| 479 | if (fault) { | ||
| 480 | DEBUG_LOG(ARM11, "check_access\n"); | ||
| 481 | return fault; | ||
| 482 | } | ||
| 483 | /*search main cache */ | ||
| 484 | cache = mmu_cache_search (state, MAIN_D_CACHE (), va); | ||
| 485 | if (cache) { | ||
| 486 | update_cache (state, va, data, datatype, cache, | ||
| 487 | MAIN_D_CACHE (), real_va); | ||
| 488 | } | ||
| 489 | else { | ||
| 490 | /*search mini cache */ | ||
| 491 | cache = mmu_cache_search (state, MINI_D_CACHE (), va); | ||
| 492 | if (cache) { | ||
| 493 | update_cache (state, va, data, datatype, cache, | ||
| 494 | MINI_D_CACHE (), real_va); | ||
| 495 | } | ||
| 496 | } | ||
| 497 | |||
| 498 | if (!cache) { | ||
| 499 | b = tlb_b_flag (tlb); | ||
| 500 | pa = tlb_va_to_pa (tlb, va); | ||
| 501 | if (b) { | ||
| 502 | if (MMU_WBEnabled) { | ||
| 503 | if (datatype == ARM_WORD_TYPE) | ||
| 504 | mmu_wb_write_bytes (state, WB (), pa, | ||
| 505 | (ARMbyte*)&data, 4); | ||
| 506 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 507 | mmu_wb_write_bytes (state, WB (), | ||
| 508 | (pa | | ||
| 509 | (real_va & 2)), | ||
| 510 | (ARMbyte*)&data, 2); | ||
| 511 | else if (datatype == ARM_BYTE_TYPE) | ||
| 512 | mmu_wb_write_bytes (state, WB (), | ||
| 513 | (pa | | ||
| 514 | (real_va & 3)), | ||
| 515 | (ARMbyte*)&data, 1); | ||
| 516 | |||
| 517 | } | ||
| 518 | else { | ||
| 519 | if (datatype == ARM_WORD_TYPE) | ||
| 520 | //mem_write_word (state, pa, data); | ||
| 521 | bus_write(32, pa, data); | ||
| 522 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 523 | /* | ||
| 524 | mem_write_halfword (state, | ||
| 525 | (pa | | ||
| 526 | (real_va & 2)), | ||
| 527 | data); | ||
| 528 | */ | ||
| 529 | bus_write(16, pa | (real_va & 2), data); | ||
| 530 | else if (datatype == ARM_BYTE_TYPE) | ||
| 531 | /* | ||
| 532 | mem_write_byte (state, | ||
| 533 | (pa | (real_va & 3)), | ||
| 534 | data); | ||
| 535 | */ | ||
| 536 | bus_write(8, pa | (real_va & 3), data); | ||
| 537 | } | ||
| 538 | } | ||
| 539 | else { | ||
| 540 | mmu_wb_drain_all (state, WB ()); | ||
| 541 | |||
| 542 | if (datatype == ARM_WORD_TYPE) | ||
| 543 | //mem_write_word (state, pa, data); | ||
| 544 | bus_write(32, pa, data); | ||
| 545 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 546 | /* | ||
| 547 | mem_write_halfword (state, | ||
| 548 | (pa | (real_va & 2)), | ||
| 549 | data); | ||
| 550 | */ | ||
| 551 | bus_write(16, pa | (real_va & 2), data); | ||
| 552 | else if (datatype == ARM_BYTE_TYPE) | ||
| 553 | /* | ||
| 554 | mem_write_byte (state, (pa | (real_va & 3)), | ||
| 555 | data); | ||
| 556 | */ | ||
| 557 | bus_write(8, pa | (real_va & 3), data); | ||
| 558 | } | ||
| 559 | } | ||
| 560 | return NO_FAULT; | ||
| 561 | } | ||
| 562 | |||
| 563 | static fault_t | ||
| 564 | update_cache (ARMul_State * state, ARMword va, ARMword data, ARMword datatype, | ||
| 565 | cache_line_t * cache, cache_s * cache_t, ARMword real_va) | ||
| 566 | { | ||
| 567 | ARMword temp, offset; | ||
| 568 | |||
| 569 | ARMword index = va_cache_index (va, cache_t); | ||
| 570 | |||
| 571 | //cache->data[index] = data; | ||
| 572 | |||
| 573 | if (datatype == ARM_WORD_TYPE) | ||
| 574 | cache->data[index] = data; | ||
| 575 | else if (datatype == ARM_HALFWORD_TYPE) { | ||
| 576 | temp = cache->data[index]; | ||
| 577 | offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */ | ||
| 578 | cache->data[index] = | ||
| 579 | (temp & ~(0xffffL << offset)) | ((data & 0xffffL) << | ||
| 580 | offset); | ||
| 581 | } | ||
| 582 | else if (datatype == ARM_BYTE_TYPE) { | ||
| 583 | temp = cache->data[index]; | ||
| 584 | offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */ | ||
| 585 | cache->data[index] = | ||
| 586 | (temp & ~(0xffL << offset)) | ((data & 0xffL) << | ||
| 587 | offset); | ||
| 588 | } | ||
| 589 | |||
| 590 | if (index < (cache_t->width >> (WORD_SHT + 1))) | ||
| 591 | cache->tag |= TAG_FIRST_HALF_DIRTY; | ||
| 592 | else | ||
| 593 | cache->tag |= TAG_LAST_HALF_DIRTY; | ||
| 594 | |||
| 595 | return NO_FAULT; | ||
| 596 | } | ||
| 597 | |||
| 598 | ARMword | ||
| 599 | sa_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value) | ||
| 600 | { | ||
| 601 | mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15); | ||
| 602 | ARMword data; | ||
| 603 | |||
| 604 | switch (creg) { | ||
| 605 | case MMU_ID: | ||
| 606 | // printf("mmu_mrc read ID "); | ||
| 607 | data = 0x41007100; /* v3 */ | ||
| 608 | data = state->cpu->cpu_val; | ||
| 609 | break; | ||
| 610 | case MMU_CONTROL: | ||
| 611 | // printf("mmu_mrc read CONTROL"); | ||
| 612 | data = state->mmu.control; | ||
| 613 | break; | ||
| 614 | case MMU_TRANSLATION_TABLE_BASE: | ||
| 615 | // printf("mmu_mrc read TTB "); | ||
| 616 | data = state->mmu.translation_table_base; | ||
| 617 | break; | ||
| 618 | case MMU_DOMAIN_ACCESS_CONTROL: | ||
| 619 | // printf("mmu_mrc read DACR "); | ||
| 620 | data = state->mmu.domain_access_control; | ||
| 621 | break; | ||
| 622 | case MMU_FAULT_STATUS: | ||
| 623 | // printf("mmu_mrc read FSR "); | ||
| 624 | data = state->mmu.fault_status; | ||
| 625 | break; | ||
| 626 | case MMU_FAULT_ADDRESS: | ||
| 627 | // printf("mmu_mrc read FAR "); | ||
| 628 | data = state->mmu.fault_address; | ||
| 629 | break; | ||
| 630 | case MMU_PID: | ||
| 631 | data = state->mmu.process_id; | ||
| 632 | default: | ||
| 633 | printf ("mmu_mrc read UNKNOWN - reg %d\n", creg); | ||
| 634 | data = 0; | ||
| 635 | break; | ||
| 636 | } | ||
| 637 | // printf("\t\t\t\t\tpc = 0x%08x\n", state->Reg[15]); | ||
| 638 | *value = data; | ||
| 639 | return data; | ||
| 640 | } | ||
| 641 | |||
| 642 | void | ||
| 643 | sa_mmu_cache_ops (ARMul_State * state, ARMword instr, ARMword value) | ||
| 644 | { | ||
| 645 | int CRm, OPC_2; | ||
| 646 | |||
| 647 | CRm = BITS (0, 3); | ||
| 648 | OPC_2 = BITS (5, 7); | ||
| 649 | |||
| 650 | if (OPC_2 == 0 && CRm == 7) { | ||
| 651 | mmu_cache_invalidate_all (state, I_CACHE ()); | ||
| 652 | mmu_cache_invalidate_all (state, MAIN_D_CACHE ()); | ||
| 653 | mmu_cache_invalidate_all (state, MINI_D_CACHE ()); | ||
| 654 | return; | ||
| 655 | } | ||
| 656 | |||
| 657 | if (OPC_2 == 0 && CRm == 5) { | ||
| 658 | mmu_cache_invalidate_all (state, I_CACHE ()); | ||
| 659 | return; | ||
| 660 | } | ||
| 661 | |||
| 662 | if (OPC_2 == 0 && CRm == 6) { | ||
| 663 | mmu_cache_invalidate_all (state, MAIN_D_CACHE ()); | ||
| 664 | mmu_cache_invalidate_all (state, MINI_D_CACHE ()); | ||
| 665 | return; | ||
| 666 | } | ||
| 667 | |||
| 668 | if (OPC_2 == 1 && CRm == 6) { | ||
| 669 | mmu_cache_invalidate (state, MAIN_D_CACHE (), value); | ||
| 670 | mmu_cache_invalidate (state, MINI_D_CACHE (), value); | ||
| 671 | return; | ||
| 672 | } | ||
| 673 | |||
| 674 | if (OPC_2 == 1 && CRm == 0xa) { | ||
| 675 | mmu_cache_clean (state, MAIN_D_CACHE (), value); | ||
| 676 | mmu_cache_clean (state, MINI_D_CACHE (), value); | ||
| 677 | return; | ||
| 678 | } | ||
| 679 | |||
| 680 | if (OPC_2 == 4 && CRm == 0xa) { | ||
| 681 | mmu_wb_drain_all (state, WB ()); | ||
| 682 | return; | ||
| 683 | } | ||
| 684 | ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm); | ||
| 685 | } | ||
| 686 | |||
| 687 | static void | ||
| 688 | sa_mmu_tlb_ops (ARMul_State * state, ARMword instr, ARMword value) | ||
| 689 | { | ||
| 690 | int CRm, OPC_2; | ||
| 691 | |||
| 692 | CRm = BITS (0, 3); | ||
| 693 | OPC_2 = BITS (5, 7); | ||
| 694 | |||
| 695 | |||
| 696 | if (OPC_2 == 0 && CRm == 0x7) { | ||
| 697 | mmu_tlb_invalidate_all (state, I_TLB ()); | ||
| 698 | mmu_tlb_invalidate_all (state, D_TLB ()); | ||
| 699 | return; | ||
| 700 | } | ||
| 701 | |||
| 702 | if (OPC_2 == 0 && CRm == 0x5) { | ||
| 703 | mmu_tlb_invalidate_all (state, I_TLB ()); | ||
| 704 | return; | ||
| 705 | } | ||
| 706 | |||
| 707 | if (OPC_2 == 0 && CRm == 0x6) { | ||
| 708 | mmu_tlb_invalidate_all (state, D_TLB ()); | ||
| 709 | return; | ||
| 710 | } | ||
| 711 | |||
| 712 | if (OPC_2 == 1 && CRm == 0x6) { | ||
| 713 | mmu_tlb_invalidate_entry (state, D_TLB (), value); | ||
| 714 | return; | ||
| 715 | } | ||
| 716 | |||
| 717 | ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm); | ||
| 718 | } | ||
| 719 | |||
| 720 | static void | ||
| 721 | sa_mmu_rb_ops (ARMul_State * state, ARMword instr, ARMword value) | ||
| 722 | { | ||
| 723 | int CRm, OPC_2; | ||
| 724 | |||
| 725 | CRm = BITS (0, 3); | ||
| 726 | OPC_2 = BITS (5, 7); | ||
| 727 | |||
| 728 | if (OPC_2 == 0x0 && CRm == 0x0) { | ||
| 729 | mmu_rb_invalidate_all (RB ()); | ||
| 730 | return; | ||
| 731 | } | ||
| 732 | |||
| 733 | if (OPC_2 == 0x2) { | ||
| 734 | int idx = CRm & 0x3; | ||
| 735 | int type = ((CRm >> 2) & 0x3) + 1; | ||
| 736 | |||
| 737 | if ((idx < 4) && (type < 4)) | ||
| 738 | mmu_rb_load (state, RB (), idx, type, value); | ||
| 739 | return; | ||
| 740 | } | ||
| 741 | |||
| 742 | if ((OPC_2 == 1) && (CRm < 4)) { | ||
| 743 | mmu_rb_invalidate_entry (RB (), CRm); | ||
| 744 | return; | ||
| 745 | } | ||
| 746 | |||
| 747 | ERROR_LOG(ARM11, "Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm); | ||
| 748 | } | ||
| 749 | |||
| 750 | static ARMword | ||
| 751 | sa_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value) | ||
| 752 | { | ||
| 753 | mmu_regnum_t creg = (mmu_regnum_t)(BITS (16, 19) & 15); | ||
| 754 | if (!strncmp (state->cpu->cpu_arch_name, "armv4", 5)) { | ||
| 755 | switch (creg) { | ||
| 756 | case MMU_CONTROL: | ||
| 757 | // printf("mmu_mcr wrote CONTROL "); | ||
| 758 | state->mmu.control = (value | 0x70) & 0xFFFD; | ||
| 759 | break; | ||
| 760 | case MMU_TRANSLATION_TABLE_BASE: | ||
| 761 | // printf("mmu_mcr wrote TTB "); | ||
| 762 | state->mmu.translation_table_base = | ||
| 763 | value & 0xFFFFC000; | ||
| 764 | break; | ||
| 765 | case MMU_DOMAIN_ACCESS_CONTROL: | ||
| 766 | // printf("mmu_mcr wrote DACR "); | ||
| 767 | state->mmu.domain_access_control = value; | ||
| 768 | break; | ||
| 769 | |||
| 770 | case MMU_FAULT_STATUS: | ||
| 771 | state->mmu.fault_status = value & 0xFF; | ||
| 772 | break; | ||
| 773 | case MMU_FAULT_ADDRESS: | ||
| 774 | state->mmu.fault_address = value; | ||
| 775 | break; | ||
| 776 | |||
| 777 | case MMU_CACHE_OPS: | ||
| 778 | sa_mmu_cache_ops (state, instr, value); | ||
| 779 | break; | ||
| 780 | case MMU_TLB_OPS: | ||
| 781 | sa_mmu_tlb_ops (state, instr, value); | ||
| 782 | break; | ||
| 783 | case MMU_SA_RB_OPS: | ||
| 784 | sa_mmu_rb_ops (state, instr, value); | ||
| 785 | break; | ||
| 786 | case MMU_SA_DEBUG: | ||
| 787 | break; | ||
| 788 | case MMU_SA_CP15_R15: | ||
| 789 | break; | ||
| 790 | case MMU_PID: | ||
| 791 | //2004-06-06 lyh, bug provided by wen ye wenye@cs.ucsb.edu | ||
| 792 | state->mmu.process_id = value & 0x7e000000; | ||
| 793 | break; | ||
| 794 | |||
| 795 | default: | ||
| 796 | printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); | ||
| 797 | break; | ||
| 798 | } | ||
| 799 | } | ||
| 800 | return 0; | ||
| 801 | } | ||
| 802 | |||
| 803 | //teawater add for arm2x86 2005.06.24------------------------------------------- | ||
| 804 | static int | ||
| 805 | sa_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr) | ||
| 806 | { | ||
| 807 | fault_t fault; | ||
| 808 | tlb_entry_t *tlb; | ||
| 809 | |||
| 810 | virt_addr = mmu_pid_va_map (virt_addr); | ||
| 811 | if (MMU_Enabled) { | ||
| 812 | |||
| 813 | /*align check */ | ||
| 814 | if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) { | ||
| 815 | DEBUG_LOG(ARM11, "align\n"); | ||
| 816 | return ALIGNMENT_FAULT; | ||
| 817 | } | ||
| 818 | else | ||
| 819 | virt_addr &= ~(WORD_SIZE - 1); | ||
| 820 | |||
| 821 | /*translate tlb */ | ||
| 822 | fault = translate (state, virt_addr, I_TLB (), &tlb); | ||
| 823 | if (fault) { | ||
| 824 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 825 | return fault; | ||
| 826 | } | ||
| 827 | |||
| 828 | /*check access */ | ||
| 829 | fault = check_access (state, virt_addr, tlb, 1); | ||
| 830 | if (fault) { | ||
| 831 | DEBUG_LOG(ARM11, "check_fault\n"); | ||
| 832 | return fault; | ||
| 833 | } | ||
| 834 | } | ||
| 835 | |||
| 836 | if (MMU_Disabled) { | ||
| 837 | *phys_addr = virt_addr; | ||
| 838 | } | ||
| 839 | else { | ||
| 840 | *phys_addr = tlb_va_to_pa (tlb, virt_addr); | ||
| 841 | } | ||
| 842 | |||
| 843 | return (0); | ||
| 844 | } | ||
| 845 | |||
| 846 | //AJ2D-------------------------------------------------------------------------- | ||
| 847 | |||
| 848 | /*sa mmu_ops_t*/ | ||
| 849 | mmu_ops_t sa_mmu_ops = { | ||
| 850 | sa_mmu_init, | ||
| 851 | sa_mmu_exit, | ||
| 852 | sa_mmu_read_byte, | ||
| 853 | sa_mmu_write_byte, | ||
| 854 | sa_mmu_read_halfword, | ||
| 855 | sa_mmu_write_halfword, | ||
| 856 | sa_mmu_read_word, | ||
| 857 | sa_mmu_write_word, | ||
| 858 | sa_mmu_load_instr, | ||
| 859 | sa_mmu_mcr, | ||
| 860 | sa_mmu_mrc, | ||
| 861 | //teawater add for arm2x86 2005.06.24------------------------------------------- | ||
| 862 | sa_mmu_v2p_dbct, | ||
| 863 | //AJ2D-------------------------------------------------------------------------- | ||
| 864 | }; | ||
diff --git a/src/core/arm/interpreter/mmu/sa_mmu.h b/src/core/arm/interpreter/mmu/sa_mmu.h new file mode 100644 index 000000000..64b1c5470 --- /dev/null +++ b/src/core/arm/interpreter/mmu/sa_mmu.h | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /* | ||
| 2 | sa_mmu.h - StrongARM Memory Management Unit emulation. | ||
| 3 | ARMulator extensions for SkyEye. | ||
| 4 | <lyhost@263.net> | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program; if not, write to the Free Software | ||
| 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef _SA_MMU_H_ | ||
| 22 | #define _SA_MMU_H_ | ||
| 23 | |||
| 24 | |||
| 25 | /** | ||
| 26 | * The interface of read data from bus | ||
| 27 | */ | ||
| 28 | int bus_read(short size, int addr, uint32_t * value); | ||
| 29 | |||
| 30 | /** | ||
| 31 | * The interface of write data from bus | ||
| 32 | */ | ||
| 33 | int bus_write(short size, int addr, uint32_t value); | ||
| 34 | |||
| 35 | |||
| 36 | typedef struct sa_mmu_s | ||
| 37 | { | ||
| 38 | tlb_s i_tlb; | ||
| 39 | cache_s i_cache; | ||
| 40 | |||
| 41 | tlb_s d_tlb; | ||
| 42 | cache_s main_d_cache; | ||
| 43 | cache_s mini_d_cache; | ||
| 44 | rb_s rb_t; | ||
| 45 | wb_s wb_t; | ||
| 46 | } sa_mmu_t; | ||
| 47 | |||
| 48 | #define I_TLB() (&state->mmu.u.sa_mmu.i_tlb) | ||
| 49 | #define I_CACHE() (&state->mmu.u.sa_mmu.i_cache) | ||
| 50 | |||
| 51 | #define D_TLB() (&state->mmu.u.sa_mmu.d_tlb) | ||
| 52 | #define MAIN_D_CACHE() (&state->mmu.u.sa_mmu.main_d_cache) | ||
| 53 | #define MINI_D_CACHE() (&state->mmu.u.sa_mmu.mini_d_cache) | ||
| 54 | #define WB() (&state->mmu.u.sa_mmu.wb_t) | ||
| 55 | #define RB() (&state->mmu.u.sa_mmu.rb_t) | ||
| 56 | |||
| 57 | extern mmu_ops_t sa_mmu_ops; | ||
| 58 | #endif /*_SA_MMU_H_*/ | ||
diff --git a/src/core/arm/interpreter/mmu/tlb.cpp b/src/core/arm/interpreter/mmu/tlb.cpp new file mode 100644 index 000000000..ca60ac1a1 --- /dev/null +++ b/src/core/arm/interpreter/mmu/tlb.cpp | |||
| @@ -0,0 +1,307 @@ | |||
| 1 | #include <assert.h> | ||
| 2 | |||
| 3 | #include "core/arm/interpreter/armdefs.h" | ||
| 4 | |||
| 5 | ARMword tlb_masks[] = { | ||
| 6 | 0x00000000, /* TLB_INVALID */ | ||
| 7 | 0xFFFFF000, /* TLB_SMALLPAGE */ | ||
| 8 | 0xFFFF0000, /* TLB_LARGEPAGE */ | ||
| 9 | 0xFFF00000, /* TLB_SECTION */ | ||
| 10 | 0xFFFFF000, /*TLB_ESMALLPAGE, have TEX attirbute, only for XScale */ | ||
| 11 | 0xFFFFFC00 /* TLB_TINYPAGE */ | ||
| 12 | }; | ||
| 13 | |||
| 14 | /* This function encodes table 8-2 Interpreting AP bits, | ||
| 15 | returning non-zero if access is allowed. */ | ||
| 16 | static int | ||
| 17 | check_perms (ARMul_State * state, int ap, int read) | ||
| 18 | { | ||
| 19 | int s, r, user; | ||
| 20 | |||
| 21 | s = state->mmu.control & CONTROL_SYSTEM; | ||
| 22 | r = state->mmu.control & CONTROL_ROM; | ||
| 23 | //chy 2006-02-15 , should consider system mode, don't conside 26bit mode | ||
| 24 | user = (state->Mode == USER32MODE) || (state->Mode == USER26MODE) || (state->Mode == SYSTEM32MODE); | ||
| 25 | |||
| 26 | switch (ap) { | ||
| 27 | case 0: | ||
| 28 | return read && ((s && !user) || r); | ||
| 29 | case 1: | ||
| 30 | return !user; | ||
| 31 | case 2: | ||
| 32 | return read || !user; | ||
| 33 | case 3: | ||
| 34 | return 1; | ||
| 35 | } | ||
| 36 | return 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | fault_t | ||
| 40 | check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb, | ||
| 41 | int read) | ||
| 42 | { | ||
| 43 | int access; | ||
| 44 | |||
| 45 | state->mmu.last_domain = tlb->domain; | ||
| 46 | access = (state->mmu.domain_access_control >> (tlb->domain * 2)) & 3; | ||
| 47 | if ((access == 0) || (access == 2)) { | ||
| 48 | /* It's unclear from the documentation whether this | ||
| 49 | should always raise a section domain fault, or if | ||
| 50 | it should be a page domain fault in the case of an | ||
| 51 | L1 that describes a page table. In the ARM710T | ||
| 52 | datasheets, "Figure 8-9: Sequence for checking faults" | ||
| 53 | seems to indicate the former, while "Table 8-4: Priority | ||
| 54 | encoding of fault status" gives a value for FS[3210] in | ||
| 55 | the event of a domain fault for a page. Hmm. */ | ||
| 56 | return SECTION_DOMAIN_FAULT; | ||
| 57 | } | ||
| 58 | if (access == 1) { | ||
| 59 | /* client access - check perms */ | ||
| 60 | int subpage, ap; | ||
| 61 | |||
| 62 | switch (tlb->mapping) { | ||
| 63 | /*ks 2004-05-09 | ||
| 64 | * only for XScale | ||
| 65 | * Extend Small Page(ESP) Format | ||
| 66 | * 31-12 bits the base addr of ESP | ||
| 67 | * 11-10 bits SBZ | ||
| 68 | * 9-6 bits TEX | ||
| 69 | * 5-4 bits AP | ||
| 70 | * 3 bit C | ||
| 71 | * 2 bit B | ||
| 72 | * 1-0 bits 11 | ||
| 73 | * */ | ||
| 74 | case TLB_ESMALLPAGE: //xj | ||
| 75 | subpage = 0; | ||
| 76 | //printf("TLB_ESMALLPAGE virt_addr=0x%x \n",virt_addr ); | ||
| 77 | break; | ||
| 78 | |||
| 79 | case TLB_TINYPAGE: | ||
| 80 | subpage = 0; | ||
| 81 | //printf("TLB_TINYPAGE virt_addr=0x%x \n",virt_addr ); | ||
| 82 | break; | ||
| 83 | |||
| 84 | case TLB_SMALLPAGE: | ||
| 85 | subpage = (virt_addr >> 10) & 3; | ||
| 86 | break; | ||
| 87 | case TLB_LARGEPAGE: | ||
| 88 | subpage = (virt_addr >> 14) & 3; | ||
| 89 | break; | ||
| 90 | case TLB_SECTION: | ||
| 91 | subpage = 3; | ||
| 92 | break; | ||
| 93 | default: | ||
| 94 | assert (0); | ||
| 95 | subpage = 0; /* cleans a warning */ | ||
| 96 | } | ||
| 97 | ap = (tlb->perms >> (subpage * 2 + 4)) & 3; | ||
| 98 | if (!check_perms (state, ap, read)) { | ||
| 99 | if (tlb->mapping == TLB_SECTION) { | ||
| 100 | return SECTION_PERMISSION_FAULT; | ||
| 101 | } | ||
| 102 | else { | ||
| 103 | return SUBPAGE_PERMISSION_FAULT; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | } | ||
| 107 | else { /* access == 3 */ | ||
| 108 | /* manager access - don't check perms */ | ||
| 109 | } | ||
| 110 | return NO_FAULT; | ||
| 111 | } | ||
| 112 | |||
| 113 | fault_t | ||
| 114 | translate (ARMul_State * state, ARMword virt_addr, tlb_s * tlb_t, | ||
| 115 | tlb_entry_t ** tlb) | ||
| 116 | { | ||
| 117 | *tlb = mmu_tlb_search (state, tlb_t, virt_addr); | ||
| 118 | if (!*tlb) { | ||
| 119 | /* walk the translation tables */ | ||
| 120 | ARMword l1addr, l1desc; | ||
| 121 | tlb_entry_t entry; | ||
| 122 | |||
| 123 | l1addr = state->mmu.translation_table_base & 0xFFFFC000; | ||
| 124 | l1addr = (l1addr | (virt_addr >> 18)) & ~3; | ||
| 125 | //l1desc = mem_read_word (state, l1addr); | ||
| 126 | bus_read(32, l1addr, &l1desc); | ||
| 127 | switch (l1desc & 3) { | ||
| 128 | case 0: | ||
| 129 | /* | ||
| 130 | * according to Figure 3-9 Sequence for checking faults in arm manual, | ||
| 131 | * section translation fault should be returned here. | ||
| 132 | */ | ||
| 133 | { | ||
| 134 | return SECTION_TRANSLATION_FAULT; | ||
| 135 | } | ||
| 136 | case 3: | ||
| 137 | /* fine page table */ | ||
| 138 | // dcl 2006-01-08 | ||
| 139 | { | ||
| 140 | ARMword l2addr, l2desc; | ||
| 141 | |||
| 142 | l2addr = l1desc & 0xFFFFF000; | ||
| 143 | l2addr = (l2addr | | ||
| 144 | ((virt_addr & 0x000FFC00) >> 8)) & | ||
| 145 | ~3; | ||
| 146 | //l2desc = mem_read_word (state, l2addr); | ||
| 147 | bus_read(32, l2addr, &l2desc); | ||
| 148 | |||
| 149 | entry.virt_addr = virt_addr; | ||
| 150 | entry.phys_addr = l2desc; | ||
| 151 | entry.perms = l2desc & 0x00000FFC; | ||
| 152 | entry.domain = (l1desc >> 5) & 0x0000000F; | ||
| 153 | switch (l2desc & 3) { | ||
| 154 | case 0: | ||
| 155 | state->mmu.last_domain = entry.domain; | ||
| 156 | return PAGE_TRANSLATION_FAULT; | ||
| 157 | case 3: | ||
| 158 | entry.mapping = TLB_TINYPAGE; | ||
| 159 | break; | ||
| 160 | case 1: | ||
| 161 | // this is untested | ||
| 162 | entry.mapping = TLB_LARGEPAGE; | ||
| 163 | break; | ||
| 164 | case 2: | ||
| 165 | // this is untested | ||
| 166 | entry.mapping = TLB_SMALLPAGE; | ||
| 167 | break; | ||
| 168 | } | ||
| 169 | } | ||
| 170 | break; | ||
| 171 | case 1: | ||
| 172 | /* coarse page table */ | ||
| 173 | { | ||
| 174 | ARMword l2addr, l2desc; | ||
| 175 | |||
| 176 | l2addr = l1desc & 0xFFFFFC00; | ||
| 177 | l2addr = (l2addr | | ||
| 178 | ((virt_addr & 0x000FF000) >> 10)) & | ||
| 179 | ~3; | ||
| 180 | //l2desc = mem_read_word (state, l2addr); | ||
| 181 | bus_read(32, l2addr, &l2desc); | ||
| 182 | |||
| 183 | entry.virt_addr = virt_addr; | ||
| 184 | entry.phys_addr = l2desc; | ||
| 185 | entry.perms = l2desc & 0x00000FFC; | ||
| 186 | entry.domain = (l1desc >> 5) & 0x0000000F; | ||
| 187 | //printf("SKYEYE:PAGE virt_addr = %x,l1desc=%x,phys_addr=%x\n",virt_addr,l1desc,entry.phys_addr); | ||
| 188 | //chy 2003-09-02 for xscale | ||
| 189 | switch (l2desc & 3) { | ||
| 190 | case 0: | ||
| 191 | state->mmu.last_domain = entry.domain; | ||
| 192 | return PAGE_TRANSLATION_FAULT; | ||
| 193 | case 3: | ||
| 194 | if (!state->is_XScale) { | ||
| 195 | state->mmu.last_domain = | ||
| 196 | entry.domain; | ||
| 197 | return PAGE_TRANSLATION_FAULT; | ||
| 198 | }; | ||
| 199 | //ks 2004-05-09 xscale shold use Extend Small Page | ||
| 200 | //entry.mapping = TLB_SMALLPAGE; | ||
| 201 | entry.mapping = TLB_ESMALLPAGE; //xj | ||
| 202 | break; | ||
| 203 | case 1: | ||
| 204 | entry.mapping = TLB_LARGEPAGE; | ||
| 205 | break; | ||
| 206 | case 2: | ||
| 207 | entry.mapping = TLB_SMALLPAGE; | ||
| 208 | break; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | break; | ||
| 212 | case 2: | ||
| 213 | /* section */ | ||
| 214 | //printf("SKYEYE:WARNING: not implement section mapping incompletely\n"); | ||
| 215 | //printf("SKYEYE:SECTION virt_addr = %x,l1desc=%x\n",virt_addr,l1desc); | ||
| 216 | //return SECTION_DOMAIN_FAULT; | ||
| 217 | //#if 0 | ||
| 218 | entry.virt_addr = virt_addr; | ||
| 219 | entry.phys_addr = l1desc; | ||
| 220 | entry.perms = l1desc & 0x00000C0C; | ||
| 221 | entry.domain = (l1desc >> 5) & 0x0000000F; | ||
| 222 | entry.mapping = TLB_SECTION; | ||
| 223 | break; | ||
| 224 | //#endif | ||
| 225 | } | ||
| 226 | entry.virt_addr &= tlb_masks[entry.mapping]; | ||
| 227 | entry.phys_addr &= tlb_masks[entry.mapping]; | ||
| 228 | |||
| 229 | /* place entry in the tlb */ | ||
| 230 | *tlb = &tlb_t->entrys[tlb_t->cycle]; | ||
| 231 | tlb_t->cycle = (tlb_t->cycle + 1) % tlb_t->num; | ||
| 232 | **tlb = entry; | ||
| 233 | } | ||
| 234 | state->mmu.last_domain = (*tlb)->domain; | ||
| 235 | return NO_FAULT; | ||
| 236 | } | ||
| 237 | |||
| 238 | int | ||
| 239 | mmu_tlb_init (tlb_s * tlb_t, int num) | ||
| 240 | { | ||
| 241 | tlb_entry_t *e; | ||
| 242 | int i; | ||
| 243 | |||
| 244 | e = (tlb_entry_t *) malloc (sizeof (*e) * num); | ||
| 245 | if (e == NULL) { | ||
| 246 | ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*e) * num); | ||
| 247 | goto tlb_malloc_error; | ||
| 248 | } | ||
| 249 | tlb_t->entrys = e; | ||
| 250 | for (i = 0; i < num; i++, e++) | ||
| 251 | e->mapping = TLB_INVALID; | ||
| 252 | tlb_t->cycle = 0; | ||
| 253 | tlb_t->num = num; | ||
| 254 | return 0; | ||
| 255 | |||
| 256 | tlb_malloc_error: | ||
| 257 | return -1; | ||
| 258 | } | ||
| 259 | |||
| 260 | void | ||
| 261 | mmu_tlb_exit (tlb_s * tlb_t) | ||
| 262 | { | ||
| 263 | free (tlb_t->entrys); | ||
| 264 | }; | ||
| 265 | |||
| 266 | void | ||
| 267 | mmu_tlb_invalidate_all (ARMul_State * state, tlb_s * tlb_t) | ||
| 268 | { | ||
| 269 | int entry; | ||
| 270 | |||
| 271 | for (entry = 0; entry < tlb_t->num; entry++) { | ||
| 272 | tlb_t->entrys[entry].mapping = TLB_INVALID; | ||
| 273 | } | ||
| 274 | tlb_t->cycle = 0; | ||
| 275 | } | ||
| 276 | |||
| 277 | void | ||
| 278 | mmu_tlb_invalidate_entry (ARMul_State * state, tlb_s * tlb_t, ARMword addr) | ||
| 279 | { | ||
| 280 | tlb_entry_t *tlb; | ||
| 281 | |||
| 282 | tlb = mmu_tlb_search (state, tlb_t, addr); | ||
| 283 | if (tlb) { | ||
| 284 | tlb->mapping = TLB_INVALID; | ||
| 285 | } | ||
| 286 | } | ||
| 287 | |||
| 288 | tlb_entry_t * | ||
| 289 | mmu_tlb_search (ARMul_State * state, tlb_s * tlb_t, ARMword virt_addr) | ||
| 290 | { | ||
| 291 | int entry; | ||
| 292 | |||
| 293 | for (entry = 0; entry < tlb_t->num; entry++) { | ||
| 294 | tlb_entry_t *tlb; | ||
| 295 | ARMword mask; | ||
| 296 | |||
| 297 | tlb = &(tlb_t->entrys[entry]); | ||
| 298 | if (tlb->mapping == TLB_INVALID) { | ||
| 299 | continue; | ||
| 300 | } | ||
| 301 | mask = tlb_masks[tlb->mapping]; | ||
| 302 | if ((virt_addr & mask) == (tlb->virt_addr & mask)) { | ||
| 303 | return tlb; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | return NULL; | ||
| 307 | } | ||
diff --git a/src/core/arm/interpreter/mmu/tlb.h b/src/core/arm/interpreter/mmu/tlb.h index 938c01786..40856567b 100644 --- a/src/core/arm/interpreter/mmu/tlb.h +++ b/src/core/arm/interpreter/mmu/tlb.h | |||
| @@ -63,14 +63,7 @@ typedef struct tlb_s | |||
| 63 | #define tlb_b_flag(tlb) \ | 63 | #define tlb_b_flag(tlb) \ |
| 64 | ((tlb)->perms & 0x4) | 64 | ((tlb)->perms & 0x4) |
| 65 | 65 | ||
| 66 | #define tlb_va_to_pa(tlb, va) \ | 66 | #define tlb_va_to_pa(tlb, va) ((tlb->phys_addr & tlb_masks[tlb->mapping]) | (va & ~tlb_masks[tlb->mapping])) |
| 67 | (\ | ||
| 68 | {\ | ||
| 69 | ARMword mask = tlb_masks[tlb->mapping]; \ | ||
| 70 | (tlb->phys_addr & mask) | (va & ~mask);\ | ||
| 71 | }\ | ||
| 72 | ) | ||
| 73 | |||
| 74 | fault_t | 67 | fault_t |
| 75 | check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb, | 68 | check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb, |
| 76 | int read); | 69 | int read); |
diff --git a/src/core/arm/interpreter/mmu/wb.cpp b/src/core/arm/interpreter/mmu/wb.cpp new file mode 100644 index 000000000..82c0cec02 --- /dev/null +++ b/src/core/arm/interpreter/mmu/wb.cpp | |||
| @@ -0,0 +1,149 @@ | |||
| 1 | #include "core/arm/interpreter/armdefs.h" | ||
| 2 | |||
| 3 | /* wb_init | ||
| 4 | * @wb_t :wb_t to init | ||
| 5 | * @num :num of entrys | ||
| 6 | * @nb :num of byte of each entry | ||
| 7 | * | ||
| 8 | * $ -1:error | ||
| 9 | * 0:ok | ||
| 10 | * */ | ||
| 11 | int | ||
| 12 | mmu_wb_init (wb_s * wb_t, int num, int nb) | ||
| 13 | { | ||
| 14 | int i; | ||
| 15 | wb_entry_t *entrys, *wb; | ||
| 16 | |||
| 17 | entrys = (wb_entry_t *) malloc (sizeof (*entrys) * num); | ||
| 18 | if (entrys == NULL) { | ||
| 19 | ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*entrys) * num); | ||
| 20 | goto entrys_malloc_error; | ||
| 21 | } | ||
| 22 | |||
| 23 | for (wb = entrys, i = 0; i < num; i++, wb++) { | ||
| 24 | /*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu */ | ||
| 25 | //wb->data = (ARMword *)malloc(sizeof(ARMword) * nb); | ||
| 26 | wb->data = (ARMbyte *) malloc (nb); | ||
| 27 | if (wb->data == NULL) { | ||
| 28 | ERROR_LOG(ARM11, "malloc size of %d\n", nb); | ||
| 29 | goto data_malloc_error; | ||
| 30 | } | ||
| 31 | |||
| 32 | }; | ||
| 33 | |||
| 34 | wb_t->first = wb_t->last = wb_t->used = 0; | ||
| 35 | wb_t->num = num; | ||
| 36 | wb_t->nb = nb; | ||
| 37 | wb_t->entrys = entrys; | ||
| 38 | return 0; | ||
| 39 | |||
| 40 | data_malloc_error: | ||
| 41 | while (--i >= 0) | ||
| 42 | free (entrys[i].data); | ||
| 43 | free (entrys); | ||
| 44 | entrys_malloc_error: | ||
| 45 | return -1; | ||
| 46 | }; | ||
| 47 | |||
| 48 | /* wb_exit | ||
| 49 | * @wb_t :wb_t to exit | ||
| 50 | * */ | ||
| 51 | void | ||
| 52 | mmu_wb_exit (wb_s * wb_t) | ||
| 53 | { | ||
| 54 | int i; | ||
| 55 | wb_entry_t *wb; | ||
| 56 | |||
| 57 | wb = wb_t->entrys; | ||
| 58 | for (i = 0; i < wb_t->num; i++, wb++) { | ||
| 59 | free (wb->data); | ||
| 60 | } | ||
| 61 | free (wb_t->entrys); | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* wb_write_words :put words in Write Buffer | ||
| 65 | * @state: ARMul_State | ||
| 66 | * @wb_t: write buffer | ||
| 67 | * @pa: physical address | ||
| 68 | * @data: data ptr | ||
| 69 | * @n number of word to write | ||
| 70 | * | ||
| 71 | * Note: write buffer merge is not implemented, can be done late | ||
| 72 | * */ | ||
| 73 | void | ||
| 74 | mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa, | ||
| 75 | ARMbyte * data, int n) | ||
| 76 | { | ||
| 77 | int i; | ||
| 78 | wb_entry_t *wb; | ||
| 79 | |||
| 80 | while (n) { | ||
| 81 | if (wb_t->num == wb_t->used) { | ||
| 82 | /*clean the last wb entry */ | ||
| 83 | ARMword t; | ||
| 84 | |||
| 85 | wb = &wb_t->entrys[wb_t->last]; | ||
| 86 | t = wb->pa; | ||
| 87 | for (i = 0; i < wb->nb; i++) { | ||
| 88 | //mem_write_byte (state, t, wb->data[i]); | ||
| 89 | bus_write(8, t, wb->data[i]); | ||
| 90 | //t += WORD_SIZE; | ||
| 91 | t++; | ||
| 92 | } | ||
| 93 | wb_t->last++; | ||
| 94 | if (wb_t->last == wb_t->num) | ||
| 95 | wb_t->last = 0; | ||
| 96 | wb_t->used--; | ||
| 97 | } | ||
| 98 | |||
| 99 | wb = &wb_t->entrys[wb_t->first]; | ||
| 100 | i = (n < wb_t->nb) ? n : wb_t->nb; | ||
| 101 | |||
| 102 | wb->pa = pa; | ||
| 103 | //pa += i << WORD_SHT; | ||
| 104 | pa += i; | ||
| 105 | |||
| 106 | wb->nb = i; | ||
| 107 | //memcpy(wb->data, data, i << WORD_SHT); | ||
| 108 | memcpy (wb->data, data, i); | ||
| 109 | data += i; | ||
| 110 | n -= i; | ||
| 111 | wb_t->first++; | ||
| 112 | if (wb_t->first == wb_t->num) | ||
| 113 | wb_t->first = 0; | ||
| 114 | wb_t->used++; | ||
| 115 | }; | ||
| 116 | //teawater add for set_dirty fflash cache function 2005.07.18------------------- | ||
| 117 | #ifdef DBCT | ||
| 118 | if (!skyeye_config.no_dbct) { | ||
| 119 | tb_setdirty (state, pa, NULL); | ||
| 120 | } | ||
| 121 | #endif | ||
| 122 | //AJ2D-------------------------------------------------------------------------- | ||
| 123 | } | ||
| 124 | |||
| 125 | /* wb_drain_all | ||
| 126 | * @wb_t wb_t to drain | ||
| 127 | * */ | ||
| 128 | void | ||
| 129 | mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t) | ||
| 130 | { | ||
| 131 | ARMword pa; | ||
| 132 | wb_entry_t *wb; | ||
| 133 | int i; | ||
| 134 | |||
| 135 | while (wb_t->used) { | ||
| 136 | wb = &wb_t->entrys[wb_t->last]; | ||
| 137 | pa = wb->pa; | ||
| 138 | for (i = 0; i < wb->nb; i++) { | ||
| 139 | //mem_write_byte (state, pa, wb->data[i]); | ||
| 140 | bus_write(8, pa, wb->data[i]); | ||
| 141 | //pa += WORD_SIZE; | ||
| 142 | pa++; | ||
| 143 | } | ||
| 144 | wb_t->last++; | ||
| 145 | if (wb_t->last == wb_t->num) | ||
| 146 | wb_t->last = 0; | ||
| 147 | wb_t->used--; | ||
| 148 | }; | ||
| 149 | } | ||
diff --git a/src/core/arm/interpreter/mmu/xscale_copro.cpp b/src/core/arm/interpreter/mmu/xscale_copro.cpp new file mode 100644 index 000000000..99cd77737 --- /dev/null +++ b/src/core/arm/interpreter/mmu/xscale_copro.cpp | |||
| @@ -0,0 +1,1388 @@ | |||
| 1 | /* | ||
| 2 | armmmu.c - Memory Management Unit emulation. | ||
| 3 | ARMulator extensions for the ARM7100 family. | ||
| 4 | Copyright (C) 1999 Ben Williamson | ||
| 5 | |||
| 6 | This program is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 2 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program; if not, write to the Free Software | ||
| 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <assert.h> | ||
| 22 | #include <string.h> | ||
| 23 | |||
| 24 | #include "core/arm/interpreter/armdefs.h" | ||
| 25 | #include "core/arm/interpreter/armemu.h" | ||
| 26 | |||
| 27 | /*#include "pxa.h" */ | ||
| 28 | |||
| 29 | /* chy 2005-09-19 */ | ||
| 30 | |||
| 31 | /* extern pxa270_io_t pxa270_io; */ | ||
| 32 | /* chy 2005-09-19 -----end */ | ||
| 33 | |||
| 34 | typedef struct xscale_mmu_desc_s | ||
| 35 | { | ||
| 36 | int i_tlb; | ||
| 37 | cache_desc_t i_cache; | ||
| 38 | |||
| 39 | int d_tlb; | ||
| 40 | cache_desc_t main_d_cache; | ||
| 41 | cache_desc_t mini_d_cache; | ||
| 42 | //int rb; xscale has no read buffer | ||
| 43 | wb_desc_t wb; | ||
| 44 | } xscale_mmu_desc_t; | ||
| 45 | |||
| 46 | static xscale_mmu_desc_t pxa_mmu_desc = { | ||
| 47 | 32, | ||
| 48 | {32, 32, 32, CACHE_WRITE_BACK}, | ||
| 49 | |||
| 50 | 32, | ||
| 51 | {32, 32, 32, CACHE_WRITE_BACK}, | ||
| 52 | {32, 2, 8, CACHE_WRITE_BACK}, | ||
| 53 | {8, 16}, //for byte size, | ||
| 54 | }; | ||
| 55 | |||
| 56 | //chy 2005-09-19 for cp6 | ||
| 57 | #define CR0_ICIP 0 | ||
| 58 | #define CR1_ICMR 1 | ||
| 59 | //chy 2005-09-19 ---end | ||
| 60 | //----------- for cp14----------------- | ||
| 61 | #define CCLKCFG 6 | ||
| 62 | #define PWRMODE 7 | ||
| 63 | typedef struct xscale_cp14_reg_s | ||
| 64 | { | ||
| 65 | unsigned cclkcfg; //reg6 | ||
| 66 | unsigned pwrmode; //reg7 | ||
| 67 | } xscale_cp14_reg_s; | ||
| 68 | |||
| 69 | xscale_cp14_reg_s pxa_cp14_regs; | ||
| 70 | |||
| 71 | //-------------------------------------- | ||
| 72 | |||
| 73 | static fault_t xscale_mmu_write (ARMul_State * state, ARMword va, | ||
| 74 | ARMword data, ARMword datatype); | ||
| 75 | static fault_t xscale_mmu_read (ARMul_State * state, ARMword va, | ||
| 76 | ARMword * data, ARMword datatype); | ||
| 77 | |||
| 78 | ARMword xscale_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value); | ||
| 79 | ARMword xscale_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value); | ||
| 80 | |||
| 81 | |||
| 82 | /* jeff add 2010.9.26 for pxa270 cp6*/ | ||
| 83 | #define PXA270_ICMR 0x40D00004 | ||
| 84 | #define PXA270_ICPR 0x40D00010 | ||
| 85 | #define PXA270_ICLR 0x40D00008 | ||
| 86 | //chy 2005-09-19 for xscale pxa27x cp6 | ||
| 87 | //unsigned | ||
| 88 | //xscale_cp6_mrc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 89 | // ARMword * data) | ||
| 90 | //{ | ||
| 91 | // unsigned opcode_2 = BITS (5, 7); | ||
| 92 | // unsigned CRm = BITS (0, 3); | ||
| 93 | // unsigned reg = BITS (16, 19); | ||
| 94 | // unsigned result; | ||
| 95 | // | ||
| 96 | // //printf("SKYEYE: xscale_cp6_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,state->Reg[15], instr); | ||
| 97 | // | ||
| 98 | // switch (reg) { | ||
| 99 | // case CR0_ICIP: { // cp 6 reg 0 | ||
| 100 | // //printf("cp6_mrc cr0 ICIP \n"); | ||
| 101 | // /* *data = (pxa270_io.icmr & pxa270_io.icpr) & ~pxa270_io.iclr; */ | ||
| 102 | // /* use bus_read get the pxa270 machine registers 2010.9.26 jeff*/ | ||
| 103 | // int icmr, icpr, iclr; | ||
| 104 | // bus_read(32, PXA270_ICMR, &icmr); | ||
| 105 | // bus_read(32, PXA270_ICPR, &icpr); | ||
| 106 | // bus_read(32, PXA270_ICLR, &iclr); | ||
| 107 | // *data = (icmr & icpr) & ~iclr; | ||
| 108 | // } | ||
| 109 | // break; | ||
| 110 | // case CR1_ICMR: { // cp 6 reg 1 | ||
| 111 | // //printf("cp6_mrc cr1 ICMR\n"); | ||
| 112 | // /* *data = pxa270_io.icmr; */ | ||
| 113 | // int icmr; | ||
| 114 | // /* use bus_read get the pxa270 machine registers 2010.9.26 jeff*/ | ||
| 115 | // bus_read(32, PXA270_ICMR, &icmr); | ||
| 116 | // *data = icmr; | ||
| 117 | // } | ||
| 118 | // break; | ||
| 119 | // default: | ||
| 120 | // *data = 0; | ||
| 121 | // printf ("SKYEYE:cp6_mrc unknown cp6 regs!!!!!!\n"); | ||
| 122 | // printf ("SKYEYE: xscale_cp6_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n", opcode_2, CRm, reg, state->Reg[15], instr); | ||
| 123 | // break; | ||
| 124 | // } | ||
| 125 | // return 0; | ||
| 126 | //} | ||
| 127 | // | ||
| 128 | ////chy 2005-09-19 end | ||
| 129 | ////xscale cp13 ---------------------------------------------------- | ||
| 130 | //unsigned | ||
| 131 | //xscale_cp13_init (ARMul_State * state) | ||
| 132 | //{ | ||
| 133 | // //printf("SKYEYE: xscale_cp13_init: begin\n"); | ||
| 134 | // return 0; | ||
| 135 | //} | ||
| 136 | // | ||
| 137 | //unsigned | ||
| 138 | //xscale_cp13_exit (ARMul_State * state) | ||
| 139 | //{ | ||
| 140 | // //printf("SKYEYE: xscale_cp13_exit: begin\n"); | ||
| 141 | // return 0; | ||
| 142 | //} | ||
| 143 | // | ||
| 144 | //unsigned | ||
| 145 | //xscale_cp13_ldc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 146 | // ARMword data) | ||
| 147 | //{ | ||
| 148 | // printf ("SKYEYE: xscale_cp13_ldc: ERROR isn't existed,"); | ||
| 149 | // SKYEYE_OUTREGS (stderr); | ||
| 150 | // fprintf (stderr, "\n"); | ||
| 151 | // // skyeye_exit (-1); | ||
| 152 | // return 0; //No matter return value, only for compiler. | ||
| 153 | //} | ||
| 154 | // | ||
| 155 | //unsigned | ||
| 156 | //xscale_cp13_stc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 157 | // ARMword * data) | ||
| 158 | //{ | ||
| 159 | // printf ("SKYEYE: xscale_cp13_stc: ERROR isn't existed,"); | ||
| 160 | // SKYEYE_OUTREGS (stderr); | ||
| 161 | // fprintf (stderr, "\n"); | ||
| 162 | // // skyeye_exit (-1); | ||
| 163 | // return 0; //No matter return value, only for compiler. | ||
| 164 | //} | ||
| 165 | // | ||
| 166 | //unsigned | ||
| 167 | //xscale_cp13_mrc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 168 | // ARMword * data) | ||
| 169 | //{ | ||
| 170 | // printf ("SKYEYE: xscale_cp13_mrc: ERROR isn't existed,"); | ||
| 171 | // SKYEYE_OUTREGS (stderr); | ||
| 172 | // fprintf (stderr, "\n"); | ||
| 173 | // // skyeye_exit (-1); | ||
| 174 | // return 0; //No matter return value, only for compiler. | ||
| 175 | //} | ||
| 176 | // | ||
| 177 | //unsigned | ||
| 178 | //xscale_cp13_mcr (ARMul_State * state, unsigned type, ARMword instr, | ||
| 179 | // ARMword data) | ||
| 180 | //{ | ||
| 181 | // printf ("SKYEYE: xscale_cp13_mcr: ERROR isn't existed,"); | ||
| 182 | // SKYEYE_OUTREGS (stderr); | ||
| 183 | // fprintf (stderr, "\n"); | ||
| 184 | // // skyeye_exit (-1); | ||
| 185 | // return 0; //No matter return value, only for compiler. | ||
| 186 | //} | ||
| 187 | // | ||
| 188 | //unsigned | ||
| 189 | //xscale_cp13_cdp (ARMul_State * state, unsigned type, ARMword instr) | ||
| 190 | //{ | ||
| 191 | // printf ("SKYEYE: xscale_cp13_cdp: ERROR isn't existed,"); | ||
| 192 | // SKYEYE_OUTREGS (stderr); | ||
| 193 | // fprintf (stderr, "\n"); | ||
| 194 | // // skyeye_exit (-1); | ||
| 195 | // return 0; //No matter return value, only for compiler. | ||
| 196 | //} | ||
| 197 | // | ||
| 198 | //unsigned | ||
| 199 | //xscale_cp13_read_reg (ARMul_State * state, unsigned reg, ARMword * data) | ||
| 200 | //{ | ||
| 201 | // printf ("SKYEYE: xscale_cp13_read_reg: ERROR isn't existed,"); | ||
| 202 | // SKYEYE_OUTREGS (stderr); | ||
| 203 | // fprintf (stderr, "\n"); | ||
| 204 | // return 0; | ||
| 205 | // //exit(-1); | ||
| 206 | //} | ||
| 207 | // | ||
| 208 | //unsigned | ||
| 209 | //xscale_cp13_write_reg (ARMul_State * state, unsigned reg, ARMword data) | ||
| 210 | //{ | ||
| 211 | // printf ("SKYEYE: xscale_cp13_write_reg: ERROR isn't existed,"); | ||
| 212 | // SKYEYE_OUTREGS (stderr); | ||
| 213 | // fprintf (stderr, "\n"); | ||
| 214 | // // skyeye_exit (-1); | ||
| 215 | // return 0; //No matter return value, only for compiler. | ||
| 216 | //} | ||
| 217 | // | ||
| 218 | ////------------------------------------------------------------------ | ||
| 219 | ////xscale cp14 ---------------------------------------------------- | ||
| 220 | //unsigned | ||
| 221 | //xscale_cp14_init (ARMul_State * state) | ||
| 222 | //{ | ||
| 223 | // //printf("SKYEYE: xscale_cp14_init: begin\n"); | ||
| 224 | // pxa_cp14_regs.cclkcfg = 0; | ||
| 225 | // pxa_cp14_regs.pwrmode = 0; | ||
| 226 | // return 0; | ||
| 227 | //} | ||
| 228 | // | ||
| 229 | //unsigned | ||
| 230 | //xscale_cp14_exit (ARMul_State * state) | ||
| 231 | //{ | ||
| 232 | // //printf("SKYEYE: xscale_cp14_exit: begin\n"); | ||
| 233 | // return 0; | ||
| 234 | //} | ||
| 235 | // | ||
| 236 | //unsigned | ||
| 237 | //xscale_cp14_ldc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 238 | // ARMword data) | ||
| 239 | //{ | ||
| 240 | // printf ("SKYEYE: xscale_cp14_ldc: ERROR isn't existed, reg15 0x%x\n", | ||
| 241 | // state->Reg[15]); | ||
| 242 | // SKYEYE_OUTREGS (stderr); | ||
| 243 | // // skyeye_exit (-1); | ||
| 244 | // return 0; //No matter return value, only for compiler. | ||
| 245 | //} | ||
| 246 | // | ||
| 247 | //unsigned | ||
| 248 | //xscale_cp14_stc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 249 | // ARMword * data) | ||
| 250 | //{ | ||
| 251 | // printf ("SKYEYE: xscale_cp14_stc: ERROR isn't existed, reg15 0x%x\n", | ||
| 252 | // state->Reg[15]); | ||
| 253 | // SKYEYE_OUTREGS (stderr); | ||
| 254 | // // skyeye_exit (-1); | ||
| 255 | // return 0; //No matter return value, only for compiler. | ||
| 256 | //} | ||
| 257 | // | ||
| 258 | //unsigned | ||
| 259 | //xscale_cp14_mrc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 260 | // ARMword * data) | ||
| 261 | //{ | ||
| 262 | // unsigned opcode_2 = BITS (5, 7); | ||
| 263 | // unsigned CRm = BITS (0, 3); | ||
| 264 | // unsigned reg = BITS (16, 19); | ||
| 265 | // unsigned result; | ||
| 266 | // | ||
| 267 | // //printf("SKYEYE: xscale_cp14_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,\ | ||
| 268 | // state->Reg[15], instr); | ||
| 269 | // | ||
| 270 | // switch (reg) { | ||
| 271 | // case CCLKCFG: // cp 14 reg 6 | ||
| 272 | // //printf("cp14_mrc cclkcfg \n"); | ||
| 273 | // *data = pxa_cp14_regs.cclkcfg; | ||
| 274 | // break; | ||
| 275 | // case PWRMODE: // cp 14 reg 7 | ||
| 276 | // //printf("cp14_mrc pwrmode \n"); | ||
| 277 | // *data = pxa_cp14_regs.pwrmode; | ||
| 278 | // break; | ||
| 279 | // default: | ||
| 280 | // *data = 0; | ||
| 281 | // printf ("SKYEYE:cp14_mrc unknown cp14 regs!!!!!!\n"); | ||
| 282 | // break; | ||
| 283 | // } | ||
| 284 | // return 0; | ||
| 285 | //} | ||
| 286 | //unsigned xscale_cp14_mcr (ARMul_State * state, unsigned type, ARMword instr, | ||
| 287 | // ARMword data) | ||
| 288 | //{ | ||
| 289 | // unsigned opcode_2 = BITS (5, 7); | ||
| 290 | // unsigned CRm = BITS (0, 3); | ||
| 291 | // unsigned reg = BITS (16, 19); | ||
| 292 | // unsigned result; | ||
| 293 | // | ||
| 294 | // //printf("SKYEYE: xscale_cp14_mcr:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,\ | ||
| 295 | // state->Reg[15], instr); | ||
| 296 | // | ||
| 297 | // switch (reg) { | ||
| 298 | // case CCLKCFG: // cp 14 reg 6 | ||
| 299 | // //printf("cp14_mcr cclkcfg \n"); | ||
| 300 | // pxa_cp14_regs.cclkcfg = data & 0xf; | ||
| 301 | // break; | ||
| 302 | // case PWRMODE: // cp 14 reg 7 | ||
| 303 | // //printf("cp14_mcr pwrmode \n"); | ||
| 304 | // pxa_cp14_regs.pwrmode = data & 0x3; | ||
| 305 | // break; | ||
| 306 | // default:printf ("SKYEYE: cp14_mcr unknown cp14 regs!!!!!!\n"); | ||
| 307 | // break; | ||
| 308 | // } | ||
| 309 | // return 0; | ||
| 310 | //} | ||
| 311 | //unsigned xscale_cp14_cdp (ARMul_State * state, unsigned type, ARMword instr) | ||
| 312 | //{ | ||
| 313 | // printf ("SKYEYE: xscale_cp14_cdp: ERROR isn't existed, reg15 0x%x\n", | ||
| 314 | // state->Reg[15]); | ||
| 315 | // SKYEYE_OUTREGS (stderr); | ||
| 316 | // // skyeye_exit (-1); | ||
| 317 | // return 0; //No matter return value, only for compiler. | ||
| 318 | //} | ||
| 319 | //unsigned xscale_cp14_read_reg (ARMul_State * state, unsigned reg, | ||
| 320 | // ARMword * data) | ||
| 321 | //{ | ||
| 322 | // printf ("SKYEYE: xscale_cp14_read_reg: ERROR isn't existed, reg15 0x%x\n", state->Reg[15]); | ||
| 323 | // SKYEYE_OUTREGS (stderr); | ||
| 324 | // // skyeye_exit (-1); | ||
| 325 | // return 0; //No matter return value, only for compiler. | ||
| 326 | //} | ||
| 327 | //unsigned xscale_cp14_write_reg (ARMul_State * state, unsigned reg, | ||
| 328 | // ARMword data) | ||
| 329 | //{ | ||
| 330 | // printf ("SKYEYE: xscale_cp14_write_reg: ERROR isn't existed, reg15 0x%x\n", state->Reg[15]); | ||
| 331 | // SKYEYE_OUTREGS (stderr); | ||
| 332 | // // skyeye_exit (-1); | ||
| 333 | // | ||
| 334 | // return 0; //No matter return value, only for compiler. | ||
| 335 | //} | ||
| 336 | |||
| 337 | //------------------------------------------------------------------ | ||
| 338 | //cp15 ------------------------------------- | ||
| 339 | unsigned xscale_cp15_ldc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 340 | ARMword data) | ||
| 341 | { | ||
| 342 | printf ("SKYEYE: xscale_cp15_ldc: ERROR isn't existed\n"); | ||
| 343 | SKYEYE_OUTREGS (stderr); | ||
| 344 | // skyeye_exit (-1); | ||
| 345 | |||
| 346 | return 0; //No matter return value, only for compiler. | ||
| 347 | } | ||
| 348 | unsigned xscale_cp15_stc (ARMul_State * state, unsigned type, ARMword instr, | ||
| 349 | ARMword * data) | ||
| 350 | { | ||
| 351 | printf ("SKYEYE: xscale_cp15_stc: ERROR isn't existed\n"); | ||
| 352 | SKYEYE_OUTREGS (stderr); | ||
| 353 | // skyeye_exit (-1); | ||
| 354 | |||
| 355 | return 0; //No matter return value, only for compiler. | ||
| 356 | } | ||
| 357 | unsigned xscale_cp15_cdp (ARMul_State * state, unsigned type, ARMword instr) | ||
| 358 | { | ||
| 359 | printf ("SKYEYE: xscale_cp15_cdp: ERROR isn't existed\n"); | ||
| 360 | SKYEYE_OUTREGS (stderr); | ||
| 361 | // skyeye_exit (-1); | ||
| 362 | |||
| 363 | return 0; //No matter return value, only for compiler. | ||
| 364 | } | ||
| 365 | unsigned xscale_cp15_read_reg (ARMul_State * state, unsigned reg, | ||
| 366 | ARMword * data) | ||
| 367 | { | ||
| 368 | //chy 2003-09-03: for xsacle_cp15_cp_access_allowed | ||
| 369 | if (reg == 15) { | ||
| 370 | *data = state->mmu.copro_access; | ||
| 371 | //printf("SKYEYE: xscale_cp15_read_reg: reg 0x%x,data %x\n",reg,*data); | ||
| 372 | return 0; | ||
| 373 | } | ||
| 374 | printf ("SKYEYE: xscale_cp15_read_reg: reg 0x%x, ERROR isn't existed\n", reg); | ||
| 375 | SKYEYE_OUTREGS (stderr); | ||
| 376 | // skyeye_exit (-1); | ||
| 377 | |||
| 378 | return 0; //No matter return value, only for compiler. | ||
| 379 | } | ||
| 380 | |||
| 381 | //chy 2003-09-03 used by macro CP_ACCESS_ALLOWED in armemu.h | ||
| 382 | unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, | ||
| 383 | unsigned cpnum) | ||
| 384 | { | ||
| 385 | unsigned data; | ||
| 386 | |||
| 387 | xscale_cp15_read_reg (state, reg, &data); | ||
| 388 | //printf("SKYEYE: cp15_cp_access_allowed data %x, cpnum %x, result %x\n", data, cpnum, (data & 1<<cpnum)); | ||
| 389 | if (data & 1 << cpnum) | ||
| 390 | return 1; | ||
| 391 | else | ||
| 392 | return 0; | ||
| 393 | } | ||
| 394 | |||
| 395 | unsigned xscale_cp15_write_reg (ARMul_State * state, unsigned reg, | ||
| 396 | ARMword value) | ||
| 397 | { | ||
| 398 | switch (reg) { | ||
| 399 | case MMU_FAULT_STATUS: | ||
| 400 | //printf("SKYEYE:cp15_write_reg wrote FS val 0x%x \n",value); | ||
| 401 | state->mmu.fault_status = value & 0x6FF; | ||
| 402 | break; | ||
| 403 | case MMU_FAULT_ADDRESS: | ||
| 404 | //printf("SKYEYE:cp15_write_reg wrote FA val 0x%x \n",value); | ||
| 405 | state->mmu.fault_address = value; | ||
| 406 | break; | ||
| 407 | default: | ||
| 408 | printf ("SKYEYE: xscale_cp15_write_reg: reg 0x%x R15 %x ERROR isn't existed\n", reg, state->Reg[15]); | ||
| 409 | SKYEYE_OUTREGS (stderr); | ||
| 410 | // skyeye_exit (-1); | ||
| 411 | } | ||
| 412 | return 0; | ||
| 413 | } | ||
| 414 | |||
| 415 | int xscale_cp15_init (ARMul_State * state) | ||
| 416 | { | ||
| 417 | xscale_mmu_desc_t *desc; | ||
| 418 | cache_desc_t *c_desc; | ||
| 419 | |||
| 420 | state->mmu.control = 0; | ||
| 421 | state->mmu.translation_table_base = 0xDEADC0DE; | ||
| 422 | state->mmu.domain_access_control = 0xDEADC0DE; | ||
| 423 | state->mmu.fault_status = 0; | ||
| 424 | state->mmu.fault_address = 0; | ||
| 425 | state->mmu.process_id = 0; | ||
| 426 | state->mmu.cache_type = 0xB1AA1AA; //0000 1011 0001 1010 1010 0001 1010 1010 | ||
| 427 | state->mmu.aux_control = 0; | ||
| 428 | |||
| 429 | desc = &pxa_mmu_desc; | ||
| 430 | |||
| 431 | if (mmu_tlb_init (I_TLB (), desc->i_tlb)) { | ||
| 432 | ERROR_LOG(ARM11, "i_tlb init %d\n", -1); | ||
| 433 | goto i_tlb_init_error; | ||
| 434 | } | ||
| 435 | |||
| 436 | c_desc = &desc->i_cache; | ||
| 437 | if (mmu_cache_init (I_CACHE (), c_desc->width, c_desc->way, | ||
| 438 | c_desc->set, c_desc->w_mode)) { | ||
| 439 | ERROR_LOG(ARM11, "i_cache init %d\n", -1); | ||
| 440 | goto i_cache_init_error; | ||
| 441 | } | ||
| 442 | |||
| 443 | if (mmu_tlb_init (D_TLB (), desc->d_tlb)) { | ||
| 444 | ERROR_LOG(ARM11, "d_tlb init %d\n", -1); | ||
| 445 | goto d_tlb_init_error; | ||
| 446 | } | ||
| 447 | |||
| 448 | c_desc = &desc->main_d_cache; | ||
| 449 | if (mmu_cache_init (MAIN_D_CACHE (), c_desc->width, c_desc->way, | ||
| 450 | c_desc->set, c_desc->w_mode)) { | ||
| 451 | ERROR_LOG(ARM11, "main_d_cache init %d\n", -1); | ||
| 452 | goto main_d_cache_init_error; | ||
| 453 | } | ||
| 454 | |||
| 455 | c_desc = &desc->mini_d_cache; | ||
| 456 | if (mmu_cache_init (MINI_D_CACHE (), c_desc->width, c_desc->way, | ||
| 457 | c_desc->set, c_desc->w_mode)) { | ||
| 458 | ERROR_LOG(ARM11, "mini_d_cache init %d\n", -1); | ||
| 459 | goto mini_d_cache_init_error; | ||
| 460 | } | ||
| 461 | |||
| 462 | if (mmu_wb_init (WB (), desc->wb.num, desc->wb.nb)) { | ||
| 463 | ERROR_LOG(ARM11, "wb init %d\n", -1); | ||
| 464 | goto wb_init_error; | ||
| 465 | } | ||
| 466 | #if 0 | ||
| 467 | if (mmu_rb_init (RB (), desc->rb)) { | ||
| 468 | ERROR_LOG(ARM11, "rb init %d\n", -1); | ||
| 469 | goto rb_init_error; | ||
| 470 | } | ||
| 471 | #endif | ||
| 472 | |||
| 473 | return 0; | ||
| 474 | #if 0 | ||
| 475 | rb_init_error: | ||
| 476 | mmu_wb_exit (WB ()); | ||
| 477 | #endif | ||
| 478 | wb_init_error: | ||
| 479 | mmu_cache_exit (MINI_D_CACHE ()); | ||
| 480 | mini_d_cache_init_error: | ||
| 481 | mmu_cache_exit (MAIN_D_CACHE ()); | ||
| 482 | main_d_cache_init_error: | ||
| 483 | mmu_tlb_exit (D_TLB ()); | ||
| 484 | d_tlb_init_error: | ||
| 485 | mmu_cache_exit (I_CACHE ()); | ||
| 486 | i_cache_init_error: | ||
| 487 | mmu_tlb_exit (I_TLB ()); | ||
| 488 | i_tlb_init_error: | ||
| 489 | return -1; | ||
| 490 | } | ||
| 491 | |||
| 492 | void xscale_cp15_exit (ARMul_State * state) | ||
| 493 | { | ||
| 494 | //mmu_rb_exit(RB()); | ||
| 495 | mmu_wb_exit (WB ()); | ||
| 496 | mmu_cache_exit (MINI_D_CACHE ()); | ||
| 497 | mmu_cache_exit (MAIN_D_CACHE ()); | ||
| 498 | mmu_tlb_exit (D_TLB ()); | ||
| 499 | mmu_cache_exit (I_CACHE ()); | ||
| 500 | mmu_tlb_exit (I_TLB ()); | ||
| 501 | }; | ||
| 502 | |||
| 503 | |||
| 504 | static fault_t | ||
| 505 | xscale_mmu_load_instr (ARMul_State * state, ARMword va, | ||
| 506 | ARMword * instr) | ||
| 507 | { | ||
| 508 | fault_t fault; | ||
| 509 | tlb_entry_t *tlb; | ||
| 510 | cache_line_t *cache; | ||
| 511 | int c; //cache bit | ||
| 512 | ARMword pa; //physical addr | ||
| 513 | |||
| 514 | static int debug_count = 0; //used for debug | ||
| 515 | |||
| 516 | DEBUG_LOG(ARM11, "va = %x\n", va); | ||
| 517 | |||
| 518 | va = mmu_pid_va_map (va); | ||
| 519 | if (MMU_Enabled) { | ||
| 520 | /*align check */ | ||
| 521 | if ((va & (INSN_SIZE - 1)) && MMU_Aligned) { | ||
| 522 | DEBUG_LOG(ARM11, "align\n"); | ||
| 523 | return ALIGNMENT_FAULT; | ||
| 524 | } | ||
| 525 | else | ||
| 526 | va &= ~(INSN_SIZE - 1); | ||
| 527 | |||
| 528 | /*translate tlb */ | ||
| 529 | fault = translate (state, va, I_TLB (), &tlb); | ||
| 530 | if (fault) { | ||
| 531 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 532 | return fault; | ||
| 533 | } | ||
| 534 | |||
| 535 | /*check access */ | ||
| 536 | fault = check_access (state, va, tlb, 1); | ||
| 537 | if (fault) { | ||
| 538 | DEBUG_LOG(ARM11, "check_fault\n"); | ||
| 539 | return fault; | ||
| 540 | } | ||
| 541 | } | ||
| 542 | //chy 2003-09-02 for test, don't use cache ????? | ||
| 543 | #if 0 | ||
| 544 | /*search cache no matter MMU enabled/disabled */ | ||
| 545 | cache = mmu_cache_search (state, I_CACHE (), va); | ||
| 546 | if (cache) { | ||
| 547 | *instr = cache->data[va_cache_index (va, I_CACHE ())]; | ||
| 548 | return 0; | ||
| 549 | } | ||
| 550 | #endif | ||
| 551 | /*if MMU disabled or C flag is set alloc cache */ | ||
| 552 | if (MMU_Disabled) { | ||
| 553 | c = 1; | ||
| 554 | pa = va; | ||
| 555 | } | ||
| 556 | else { | ||
| 557 | c = tlb_c_flag (tlb); | ||
| 558 | pa = tlb_va_to_pa (tlb, va); | ||
| 559 | } | ||
| 560 | |||
| 561 | //chy 2003-09-03 only read mem, don't use cache now,will change later ???? | ||
| 562 | //*instr = mem_read_word (state, pa); | ||
| 563 | bus_read(32, pa, instr); | ||
| 564 | #if 0 | ||
| 565 | //----------------------------------------------------------- | ||
| 566 | //chy 2003-09-02 for test???? | ||
| 567 | if (pa >= 0xa01c8000 && pa <= 0xa01c8020) { | ||
| 568 | printf ("SKYEYE:load_instr: pa %x, va %x,instr %x, R15 %x\n", | ||
| 569 | pa, va, *instr, state->Reg[15]); | ||
| 570 | } | ||
| 571 | |||
| 572 | //---------------------------------------------------------------------- | ||
| 573 | #endif | ||
| 574 | return NO_FAULT; | ||
| 575 | |||
| 576 | if (c) { | ||
| 577 | int index; | ||
| 578 | |||
| 579 | debug_count++; | ||
| 580 | cache = mmu_cache_alloc (state, I_CACHE (), va, pa); | ||
| 581 | index = va_cache_index (va, I_CACHE ()); | ||
| 582 | *instr = cache->data[va_cache_index (va, I_CACHE ())]; | ||
| 583 | } | ||
| 584 | else | ||
| 585 | //*instr = mem_read_word (state, pa); | ||
| 586 | bus_read(32, pa, instr); | ||
| 587 | |||
| 588 | return NO_FAULT; | ||
| 589 | }; | ||
| 590 | |||
| 591 | |||
| 592 | |||
| 593 | static fault_t | ||
| 594 | xscale_mmu_read_byte (ARMul_State * state, ARMword virt_addr, | ||
| 595 | ARMword * data) | ||
| 596 | { | ||
| 597 | //ARMword temp,offset; | ||
| 598 | fault_t fault; | ||
| 599 | fault = xscale_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE); | ||
| 600 | return fault; | ||
| 601 | } | ||
| 602 | |||
| 603 | static fault_t | ||
| 604 | xscale_mmu_read_halfword (ARMul_State * state, ARMword virt_addr, | ||
| 605 | ARMword * data) | ||
| 606 | { | ||
| 607 | //ARMword temp,offset; | ||
| 608 | fault_t fault; | ||
| 609 | fault = xscale_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE); | ||
| 610 | return fault; | ||
| 611 | } | ||
| 612 | |||
| 613 | static fault_t | ||
| 614 | xscale_mmu_read_word (ARMul_State * state, ARMword virt_addr, | ||
| 615 | ARMword * data) | ||
| 616 | { | ||
| 617 | return xscale_mmu_read (state, virt_addr, data, ARM_WORD_TYPE); | ||
| 618 | } | ||
| 619 | |||
| 620 | |||
| 621 | |||
| 622 | |||
| 623 | static fault_t | ||
| 624 | xscale_mmu_read (ARMul_State * state, ARMword va, ARMword * data, | ||
| 625 | ARMword datatype) | ||
| 626 | { | ||
| 627 | fault_t fault; | ||
| 628 | // rb_entry_t *rb; | ||
| 629 | tlb_entry_t *tlb; | ||
| 630 | cache_line_t *cache; | ||
| 631 | ARMword pa, real_va, temp, offset; | ||
| 632 | //chy 2003-09-02 for test ???? | ||
| 633 | static unsigned chyst1 = 0, chyst2 = 0; | ||
| 634 | |||
| 635 | DEBUG_LOG(ARM11, "va = %x\n", va); | ||
| 636 | |||
| 637 | va = mmu_pid_va_map (va); | ||
| 638 | real_va = va; | ||
| 639 | /*if MMU disabled, memory_read */ | ||
| 640 | if (MMU_Disabled) { | ||
| 641 | //*data = mem_read_word(state, va); | ||
| 642 | if (datatype == ARM_BYTE_TYPE) | ||
| 643 | //*data = mem_read_byte (state, va); | ||
| 644 | bus_read(8, va, data); | ||
| 645 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 646 | //*data = mem_read_halfword (state, va); | ||
| 647 | bus_read(16, va, data); | ||
| 648 | else if (datatype == ARM_WORD_TYPE) | ||
| 649 | //*data = mem_read_word (state, va); | ||
| 650 | bus_read(32, va, data); | ||
| 651 | else { | ||
| 652 | printf ("SKYEYE:1 xscale_mmu_read error: unknown data type %d\n", datatype); | ||
| 653 | // skyeye_exit (-1); | ||
| 654 | } | ||
| 655 | |||
| 656 | return NO_FAULT; | ||
| 657 | } | ||
| 658 | |||
| 659 | /*align check */ | ||
| 660 | if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) || | ||
| 661 | ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) { | ||
| 662 | DEBUG_LOG(ARM11, "align\n"); | ||
| 663 | return ALIGNMENT_FAULT; | ||
| 664 | } // else | ||
| 665 | |||
| 666 | va &= ~(WORD_SIZE - 1); | ||
| 667 | |||
| 668 | /*translate va to tlb */ | ||
| 669 | fault = translate (state, va, D_TLB (), &tlb); | ||
| 670 | if (fault) { | ||
| 671 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 672 | return fault; | ||
| 673 | } | ||
| 674 | /*check access permission */ | ||
| 675 | fault = check_access (state, va, tlb, 1); | ||
| 676 | if (fault) | ||
| 677 | return fault; | ||
| 678 | |||
| 679 | #if 0 | ||
| 680 | //------------------------------------------------ | ||
| 681 | //chy 2003-09-02 for test only ,should commit ???? | ||
| 682 | if (datatype == ARM_WORD_TYPE) { | ||
| 683 | if (real_va >= 0xffff0000 && real_va <= 0xffff0020) { | ||
| 684 | pa = tlb_va_to_pa (tlb, va); | ||
| 685 | *data = mem_read_word (state, pa); | ||
| 686 | chyst1++; | ||
| 687 | printf ("**SKYEYE:mmu_read word %d: pa %x, va %x, data %x, R15 %x\n", chyst1, pa, real_va, *data, state->Reg[15]); | ||
| 688 | /* | ||
| 689 | cache==mmu_cache_search(state,MAIN_D_CACHE(),va); | ||
| 690 | if(cache){ | ||
| 691 | *data = cache->data[va_cache_index(va, MAIN_D_CACHE())]; | ||
| 692 | printf("cached data %x\n",*data); | ||
| 693 | }else printf("no cached data\n"); | ||
| 694 | */ | ||
| 695 | } | ||
| 696 | } | ||
| 697 | //------------------------------------------------- | ||
| 698 | #endif | ||
| 699 | #if 0 | ||
| 700 | /*search in read buffer */ | ||
| 701 | rb = mmu_rb_search (RB (), va); | ||
| 702 | if (rb) { | ||
| 703 | if (rb->fault) | ||
| 704 | return rb->fault; | ||
| 705 | *data = rb->data[(va & (rb_masks[rb->type] - 1)) >> WORD_SHT]; | ||
| 706 | goto datatrans; | ||
| 707 | //return 0; | ||
| 708 | }; | ||
| 709 | #endif | ||
| 710 | |||
| 711 | /*2004-07-19 chy: add support of xscale MMU CacheDisabled option */ | ||
| 712 | if (MMU_CacheDisabled) { | ||
| 713 | //if(1){ can be used to test cache error | ||
| 714 | /*get phy_addr */ | ||
| 715 | pa = tlb_va_to_pa (tlb, real_va); | ||
| 716 | if (datatype == ARM_BYTE_TYPE) | ||
| 717 | //*data = mem_read_byte (state, pa); | ||
| 718 | bus_read(8, pa, data); | ||
| 719 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 720 | //*data = mem_read_halfword (state, pa); | ||
| 721 | bus_read(16, pa, data); | ||
| 722 | else if (datatype == ARM_WORD_TYPE) | ||
| 723 | //*data = mem_read_word (state, pa); | ||
| 724 | bus_read(32, pa, data); | ||
| 725 | else { | ||
| 726 | printf ("SKYEYE:MMU_CacheDisabled xscale_mmu_read error: unknown data type %d\n", datatype); | ||
| 727 | // skyeye_exit (-1); | ||
| 728 | } | ||
| 729 | return NO_FAULT; | ||
| 730 | } | ||
| 731 | |||
| 732 | |||
| 733 | /*search main cache */ | ||
| 734 | cache = mmu_cache_search (state, MAIN_D_CACHE (), va); | ||
| 735 | if (cache) { | ||
| 736 | *data = cache->data[va_cache_index (va, MAIN_D_CACHE ())]; | ||
| 737 | #if 0 | ||
| 738 | //------------------------------------------------------------------------ | ||
| 739 | //chy 2003-09-02 for test only ,should commit ???? | ||
| 740 | if (real_va >= 0xffff0000 && real_va <= 0xffff0020) { | ||
| 741 | pa = tlb_va_to_pa (tlb, va); | ||
| 742 | chyst2++; | ||
| 743 | printf ("**SKYEYE:mmu_read wordk:cache %d: pa %x, va %x, data %x, R15 %x\n", chyst2, pa, real_va, *data, state->Reg[15]); | ||
| 744 | } | ||
| 745 | //------------------------------------------------------------------- | ||
| 746 | #endif | ||
| 747 | goto datatrans; | ||
| 748 | //return 0; | ||
| 749 | } | ||
| 750 | //chy 2003-08-24, now maybe we don't need minidcache ???? | ||
| 751 | #if 0 | ||
| 752 | /*search mini cache */ | ||
| 753 | cache = mmu_cache_search (state, MINI_D_CACHE (), va); | ||
| 754 | if (cache) { | ||
| 755 | *data = cache->data[va_cache_index (va, MINI_D_CACHE ())]; | ||
| 756 | goto datatrans; | ||
| 757 | //return 0; | ||
| 758 | } | ||
| 759 | #endif | ||
| 760 | /*get phy_addr */ | ||
| 761 | pa = tlb_va_to_pa (tlb, va); | ||
| 762 | //chy 2003-08-24 , in xscale it means what ????? | ||
| 763 | #if 0 | ||
| 764 | if ((pa >= 0xe0000000) && (pa < 0xe8000000)) { | ||
| 765 | |||
| 766 | if (tlb_c_flag (tlb)) { | ||
| 767 | if (tlb_b_flag (tlb)) { | ||
| 768 | mmu_cache_soft_flush (state, MAIN_D_CACHE (), | ||
| 769 | pa); | ||
| 770 | } | ||
| 771 | else { | ||
| 772 | mmu_cache_soft_flush (state, MINI_D_CACHE (), | ||
| 773 | pa); | ||
| 774 | } | ||
| 775 | } | ||
| 776 | return 0; | ||
| 777 | } | ||
| 778 | #endif | ||
| 779 | //chy 2003-08-24, check phy addr | ||
| 780 | //ywc 2004-11-30, inactive this check because of using 0xc0000000 as the framebuffer start address | ||
| 781 | /* | ||
| 782 | if(pa >= 0xb0000000){ | ||
| 783 | printf("SKYEYE:xscale_mmu_read: phy address 0x%x error,reg[15] 0x%x\n",pa,state->Reg[15]); | ||
| 784 | return 0; | ||
| 785 | } | ||
| 786 | */ | ||
| 787 | |||
| 788 | //chy 2003-08-24, now maybe we don't need wb ???? | ||
| 789 | #if 0 | ||
| 790 | /*if Buffer, drain Write Buffer first */ | ||
| 791 | if (tlb_b_flag (tlb)) | ||
| 792 | mmu_wb_drain_all (state, WB ()); | ||
| 793 | #endif | ||
| 794 | /*alloc cache or mem_read */ | ||
| 795 | if (tlb_c_flag (tlb) && MMU_DCacheEnabled) { | ||
| 796 | cache_s *cache_t; | ||
| 797 | |||
| 798 | if (tlb_b_flag (tlb)) | ||
| 799 | cache_t = MAIN_D_CACHE (); | ||
| 800 | else | ||
| 801 | cache_t = MINI_D_CACHE (); | ||
| 802 | cache = mmu_cache_alloc (state, cache_t, va, pa); | ||
| 803 | *data = cache->data[va_cache_index (va, cache_t)]; | ||
| 804 | } | ||
| 805 | else { | ||
| 806 | //*data = mem_read_word(state, pa); | ||
| 807 | if (datatype == ARM_BYTE_TYPE) | ||
| 808 | //*data = mem_read_byte (state, pa | (real_va & 3)); | ||
| 809 | bus_read(8, pa | (real_va & 3), data); | ||
| 810 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 811 | //*data = mem_read_halfword (state, pa | (real_va & 2)); | ||
| 812 | bus_read(16, pa | (real_va & 2), data); | ||
| 813 | else if (datatype == ARM_WORD_TYPE) | ||
| 814 | //*data = mem_read_word (state, pa); | ||
| 815 | bus_read(32, pa, data); | ||
| 816 | else { | ||
| 817 | printf ("SKYEYE:2 xscale_mmu_read error: unknown data type %d\n", datatype); | ||
| 818 | // skyeye_exit (-1); | ||
| 819 | } | ||
| 820 | return NO_FAULT; | ||
| 821 | } | ||
| 822 | |||
| 823 | |||
| 824 | datatrans: | ||
| 825 | if (datatype == ARM_HALFWORD_TYPE) { | ||
| 826 | temp = *data; | ||
| 827 | offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */ | ||
| 828 | *data = (temp >> offset) & 0xffff; | ||
| 829 | } | ||
| 830 | else if (datatype == ARM_BYTE_TYPE) { | ||
| 831 | temp = *data; | ||
| 832 | offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */ | ||
| 833 | *data = (temp >> offset & 0xffL); | ||
| 834 | } | ||
| 835 | end: | ||
| 836 | return NO_FAULT; | ||
| 837 | } | ||
| 838 | |||
| 839 | |||
| 840 | static fault_t | ||
| 841 | xscale_mmu_write_byte (ARMul_State * state, ARMword virt_addr, | ||
| 842 | ARMword data) | ||
| 843 | { | ||
| 844 | return xscale_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE); | ||
| 845 | } | ||
| 846 | |||
| 847 | static fault_t | ||
| 848 | xscale_mmu_write_halfword (ARMul_State * state, ARMword virt_addr, | ||
| 849 | ARMword data) | ||
| 850 | { | ||
| 851 | return xscale_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE); | ||
| 852 | } | ||
| 853 | |||
| 854 | static fault_t | ||
| 855 | xscale_mmu_write_word (ARMul_State * state, ARMword virt_addr, | ||
| 856 | ARMword data) | ||
| 857 | { | ||
| 858 | return xscale_mmu_write (state, virt_addr, data, ARM_WORD_TYPE); | ||
| 859 | } | ||
| 860 | |||
| 861 | |||
| 862 | |||
| 863 | static fault_t | ||
| 864 | xscale_mmu_write (ARMul_State * state, ARMword va, ARMword data, | ||
| 865 | ARMword datatype) | ||
| 866 | { | ||
| 867 | tlb_entry_t *tlb; | ||
| 868 | cache_line_t *cache; | ||
| 869 | cache_s *cache_t; | ||
| 870 | int b; | ||
| 871 | ARMword pa, real_va, temp, offset; | ||
| 872 | fault_t fault; | ||
| 873 | |||
| 874 | ARMword index; | ||
| 875 | //chy 2003-09-02 for test ???? | ||
| 876 | // static unsigned chyst1=0,chyst2=0; | ||
| 877 | |||
| 878 | DEBUG_LOG(ARM11, "va = %x, val = %x\n", va, data); | ||
| 879 | va = mmu_pid_va_map (va); | ||
| 880 | real_va = va; | ||
| 881 | |||
| 882 | if (MMU_Disabled) { | ||
| 883 | //mem_write_word(state, va, data); | ||
| 884 | if (datatype == ARM_BYTE_TYPE) | ||
| 885 | //mem_write_byte (state, va, data); | ||
| 886 | bus_write(8, va, data); | ||
| 887 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 888 | //mem_write_halfword (state, va, data); | ||
| 889 | bus_write(16, va, data); | ||
| 890 | else if (datatype == ARM_WORD_TYPE) | ||
| 891 | //mem_write_word (state, va, data); | ||
| 892 | bus_write(32, va, data); | ||
| 893 | else { | ||
| 894 | printf ("SKYEYE:1 xscale_mmu_write error: unknown data type %d\n", datatype); | ||
| 895 | // skyeye_exit (-1); | ||
| 896 | } | ||
| 897 | |||
| 898 | return NO_FAULT; | ||
| 899 | } | ||
| 900 | /*align check */ | ||
| 901 | if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) || | ||
| 902 | ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) { | ||
| 903 | DEBUG_LOG(ARM11, "align\n"); | ||
| 904 | return ALIGNMENT_FAULT; | ||
| 905 | } //else | ||
| 906 | va &= ~(WORD_SIZE - 1); | ||
| 907 | /*tlb translate */ | ||
| 908 | fault = translate (state, va, D_TLB (), &tlb); | ||
| 909 | if (fault) { | ||
| 910 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 911 | return fault; | ||
| 912 | } | ||
| 913 | /*tlb check access */ | ||
| 914 | fault = check_access (state, va, tlb, 0); | ||
| 915 | if (fault) { | ||
| 916 | DEBUG_LOG(ARM11, "check_access\n"); | ||
| 917 | return fault; | ||
| 918 | } | ||
| 919 | |||
| 920 | /*2004-07-19 chy: add support for xscale MMU_CacheDisabled */ | ||
| 921 | if (MMU_CacheDisabled) { | ||
| 922 | //if(1){ can be used to test the cache error | ||
| 923 | /*get phy_addr */ | ||
| 924 | pa = tlb_va_to_pa (tlb, real_va); | ||
| 925 | if (datatype == ARM_BYTE_TYPE) | ||
| 926 | //mem_write_byte (state, pa, data); | ||
| 927 | bus_write(8, pa, data); | ||
| 928 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 929 | //mem_write_halfword (state, pa, data); | ||
| 930 | bus_write(16, pa, data); | ||
| 931 | else if (datatype == ARM_WORD_TYPE) | ||
| 932 | //mem_write_word (state, pa, data); | ||
| 933 | bus_write(32, pa , data); | ||
| 934 | else { | ||
| 935 | printf ("SKYEYE:MMU_CacheDisabled xscale_mmu_write error: unknown data type %d\n", datatype); | ||
| 936 | // skyeye_exit (-1); | ||
| 937 | } | ||
| 938 | |||
| 939 | return NO_FAULT; | ||
| 940 | } | ||
| 941 | |||
| 942 | /*search main cache */ | ||
| 943 | b = tlb_b_flag (tlb); | ||
| 944 | pa = tlb_va_to_pa (tlb, va); | ||
| 945 | cache = mmu_cache_search (state, MAIN_D_CACHE (), va); | ||
| 946 | if (cache) { | ||
| 947 | cache_t = MAIN_D_CACHE (); | ||
| 948 | goto has_cache; | ||
| 949 | } | ||
| 950 | //chy 2003-08-24, now maybe we don't need minidcache ???? | ||
| 951 | #if 0 | ||
| 952 | /*search mini cache */ | ||
| 953 | cache = mmu_cache_search (state, MINI_D_CACHE (), va); | ||
| 954 | if (cache) { | ||
| 955 | cache_t = MINI_D_CACHE (); | ||
| 956 | goto has_cache; | ||
| 957 | } | ||
| 958 | #endif | ||
| 959 | b = tlb_b_flag (tlb); | ||
| 960 | pa = tlb_va_to_pa (tlb, va); | ||
| 961 | //chy 2003-08-24, check phy addr 0xa0000000, size 0x04000000 | ||
| 962 | //ywc 2004-11-30, inactive this check because of using 0xc0000000 as the framebuffer start address | ||
| 963 | /* | ||
| 964 | if(pa >= 0xb0000000){ | ||
| 965 | printf("SKYEYE:xscale_mmu_write phy address 0x%x error,reg[15] 0x%x\n",pa,state->Reg[15]); | ||
| 966 | return 0; | ||
| 967 | } | ||
| 968 | */ | ||
| 969 | |||
| 970 | //chy 2003-08-24, now maybe we don't need WB ???? | ||
| 971 | #if 0 | ||
| 972 | if (b) { | ||
| 973 | if (MMU_WBEnabled) { | ||
| 974 | if (datatype == ARM_WORD_TYPE) | ||
| 975 | mmu_wb_write_bytes (state, WB (), pa, &data, | ||
| 976 | 4); | ||
| 977 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 978 | mmu_wb_write_bytes (state, WB (), | ||
| 979 | (pa | (real_va & 2)), | ||
| 980 | &data, 2); | ||
| 981 | else if (datatype == ARM_BYTE_TYPE) | ||
| 982 | mmu_wb_write_bytes (state, WB (), | ||
| 983 | (pa | (real_va & 3)), | ||
| 984 | &data, 1); | ||
| 985 | |||
| 986 | } | ||
| 987 | else { | ||
| 988 | if (datatype == ARM_WORD_TYPE) | ||
| 989 | mem_write_word (state, pa, data); | ||
| 990 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 991 | mem_write_halfword (state, | ||
| 992 | (pa | (real_va & 2)), | ||
| 993 | data); | ||
| 994 | else if (datatype == ARM_BYTE_TYPE) | ||
| 995 | mem_write_byte (state, (pa | (real_va & 3)), | ||
| 996 | data); | ||
| 997 | } | ||
| 998 | } | ||
| 999 | else { | ||
| 1000 | |||
| 1001 | mmu_wb_drain_all (state, WB ()); | ||
| 1002 | |||
| 1003 | if (datatype == ARM_WORD_TYPE) | ||
| 1004 | mem_write_word (state, pa, data); | ||
| 1005 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 1006 | mem_write_halfword (state, (pa | (real_va & 2)), | ||
| 1007 | data); | ||
| 1008 | else if (datatype == ARM_BYTE_TYPE) | ||
| 1009 | mem_write_byte (state, (pa | (real_va & 3)), data); | ||
| 1010 | } | ||
| 1011 | #endif | ||
| 1012 | //chy 2003-08-24, just write phy addr | ||
| 1013 | if (datatype == ARM_WORD_TYPE) | ||
| 1014 | //mem_write_word (state, pa, data); | ||
| 1015 | bus_write(32, pa, data); | ||
| 1016 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 1017 | //mem_write_halfword (state, (pa | (real_va & 2)), data); | ||
| 1018 | bus_write(16, pa | (real_va & 2), data); | ||
| 1019 | else if (datatype == ARM_BYTE_TYPE) | ||
| 1020 | //mem_write_byte (state, (pa | (real_va & 3)), data); | ||
| 1021 | bus_write(8, (pa | (real_va & 3)), data); | ||
| 1022 | #if 0 | ||
| 1023 | //------------------------------------------------------------- | ||
| 1024 | //chy 2003-09-02 for test ???? | ||
| 1025 | if (datatype == ARM_WORD_TYPE) { | ||
| 1026 | if (real_va >= 0xffff0000 && real_va <= 0xffff0020) { | ||
| 1027 | printf ("**SKYEYE:mmu_write word: pa %x, va %x, data %x, R15 %x \n", pa, real_va, data, state->Reg[15]); | ||
| 1028 | } | ||
| 1029 | } | ||
| 1030 | //-------------------------------------------------------------- | ||
| 1031 | #endif | ||
| 1032 | return NO_FAULT; | ||
| 1033 | |||
| 1034 | has_cache: | ||
| 1035 | index = va_cache_index (va, cache_t); | ||
| 1036 | //cache->data[index] = data; | ||
| 1037 | |||
| 1038 | if (datatype == ARM_WORD_TYPE) | ||
| 1039 | cache->data[index] = data; | ||
| 1040 | else if (datatype == ARM_HALFWORD_TYPE) { | ||
| 1041 | temp = cache->data[index]; | ||
| 1042 | offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3; /* bit offset into the word */ | ||
| 1043 | cache->data[index] = | ||
| 1044 | (temp & ~(0xffffL << offset)) | ((data & 0xffffL) << | ||
| 1045 | offset); | ||
| 1046 | } | ||
| 1047 | else if (datatype == ARM_BYTE_TYPE) { | ||
| 1048 | temp = cache->data[index]; | ||
| 1049 | offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3; /* bit offset into the word */ | ||
| 1050 | cache->data[index] = | ||
| 1051 | (temp & ~(0xffL << offset)) | ((data & 0xffL) << | ||
| 1052 | offset); | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | if (index < (cache_t->width >> (WORD_SHT + 1))) | ||
| 1056 | cache->tag |= TAG_FIRST_HALF_DIRTY; | ||
| 1057 | else | ||
| 1058 | cache->tag |= TAG_LAST_HALF_DIRTY; | ||
| 1059 | //------------------------------------------------------------- | ||
| 1060 | //chy 2003-09-03 be sure the changed value will be in memory as soon as possible, so I cache can get the newest value | ||
| 1061 | #if 0 | ||
| 1062 | { | ||
| 1063 | if (datatype == ARM_WORD_TYPE) | ||
| 1064 | mem_write_word (state, pa, data); | ||
| 1065 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 1066 | mem_write_halfword (state, (pa | (real_va & 2)), | ||
| 1067 | data); | ||
| 1068 | else if (datatype == ARM_BYTE_TYPE) | ||
| 1069 | mem_write_byte (state, (pa | (real_va & 3)), data); | ||
| 1070 | } | ||
| 1071 | #endif | ||
| 1072 | #if 0 | ||
| 1073 | //chy 2003-09-02 for test ???? | ||
| 1074 | if (datatype == ARM_WORD_TYPE) { | ||
| 1075 | if (real_va >= 0xffff0000 && real_va <= 0xffff0020) { | ||
| 1076 | printf ("**SKYEYE:mmu_write word:cache: pa %x, va %x, data %x, R15 %x\n", pa, real_va, data, state->Reg[15]); | ||
| 1077 | } | ||
| 1078 | } | ||
| 1079 | //------------------------------------------------------------- | ||
| 1080 | #endif | ||
| 1081 | if (datatype == ARM_WORD_TYPE) | ||
| 1082 | //mem_write_word (state, pa, data); | ||
| 1083 | bus_write(32, pa, data); | ||
| 1084 | else if (datatype == ARM_HALFWORD_TYPE) | ||
| 1085 | //mem_write_halfword (state, (pa | (real_va & 2)), data); | ||
| 1086 | bus_write(16, pa | (real_va & 2), data); | ||
| 1087 | else if (datatype == ARM_BYTE_TYPE) | ||
| 1088 | //mem_write_byte (state, (pa | (real_va & 3)), data); | ||
| 1089 | bus_write(8, (pa | (real_va & 3)), data); | ||
| 1090 | return NO_FAULT; | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | ARMword xscale_cp15_mrc (ARMul_State * state, | ||
| 1094 | unsigned type, ARMword instr, ARMword * value) | ||
| 1095 | { | ||
| 1096 | return xscale_mmu_mrc (state, instr, value); | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | ARMword xscale_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value) | ||
| 1100 | { | ||
| 1101 | ARMword data; | ||
| 1102 | unsigned opcode_2 = BITS (5, 7); | ||
| 1103 | unsigned CRm = BITS (0, 3); | ||
| 1104 | unsigned reg = BITS (16, 19); | ||
| 1105 | unsigned result; | ||
| 1106 | mmu_regnum_t creg = (mmu_regnum_t)reg; | ||
| 1107 | |||
| 1108 | /* | ||
| 1109 | printf("SKYEYE: xscale_cp15_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,\ | ||
| 1110 | state->Reg[15], instr); | ||
| 1111 | */ | ||
| 1112 | switch (creg) { | ||
| 1113 | case MMU_ID: //XSCALE_CP15 | ||
| 1114 | //printf("mmu_mrc read ID \n"); | ||
| 1115 | data = (opcode_2 ? state->mmu.cache_type : state->cpu-> | ||
| 1116 | cpu_val); | ||
| 1117 | break; | ||
| 1118 | case MMU_CONTROL: //XSCALE_CP15_AUX_CONTROL | ||
| 1119 | //printf("mmu_mrc read CONTROL \n"); | ||
| 1120 | data = (opcode_2 ? state->mmu.aux_control : state->mmu. | ||
| 1121 | control); | ||
| 1122 | break; | ||
| 1123 | case MMU_TRANSLATION_TABLE_BASE: | ||
| 1124 | //printf("mmu_mrc read TTB \n"); | ||
| 1125 | data = state->mmu.translation_table_base; | ||
| 1126 | break; | ||
| 1127 | case MMU_DOMAIN_ACCESS_CONTROL: | ||
| 1128 | //printf("mmu_mrc read DACR \n"); | ||
| 1129 | data = state->mmu.domain_access_control; | ||
| 1130 | break; | ||
| 1131 | case MMU_FAULT_STATUS: | ||
| 1132 | //printf("mmu_mrc read FSR \n"); | ||
| 1133 | data = state->mmu.fault_status; | ||
| 1134 | break; | ||
| 1135 | case MMU_FAULT_ADDRESS: | ||
| 1136 | //printf("mmu_mrc read FAR \n"); | ||
| 1137 | data = state->mmu.fault_address; | ||
| 1138 | break; | ||
| 1139 | case MMU_PID: | ||
| 1140 | //printf("mmu_mrc read PID \n"); | ||
| 1141 | data = state->mmu.process_id; | ||
| 1142 | case XSCALE_CP15_COPRO_ACCESS: | ||
| 1143 | //printf("xscale cp15 read coprocessor access\n"); | ||
| 1144 | data = state->mmu.copro_access; | ||
| 1145 | break; | ||
| 1146 | default: | ||
| 1147 | data = 0; | ||
| 1148 | printf ("SKYEYE: xscale_cp15_mrc read UNKNOWN - reg %d, pc 0x%x\n", creg, state->Reg[15]); | ||
| 1149 | // skyeye_exit (-1); | ||
| 1150 | break; | ||
| 1151 | } | ||
| 1152 | *value = data; | ||
| 1153 | //printf("SKYEYE: xscale_cp15_mrc:end value 0x%x\n",data); | ||
| 1154 | return ARMul_DONE; | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | void xscale_cp15_cache_ops (ARMul_State * state, ARMword instr, ARMword value) | ||
| 1158 | { | ||
| 1159 | //chy: 2003-08-24 now, the BTB isn't simualted ....???? | ||
| 1160 | |||
| 1161 | unsigned CRm, OPC_2; | ||
| 1162 | |||
| 1163 | CRm = BITS (0, 3); | ||
| 1164 | OPC_2 = BITS (5, 7); | ||
| 1165 | //err_msg("SKYEYE: xscale cp15_cache_ops:OPC_2 = 0x%x CRm = 0x%x, Reg15 0x%x\n", OPC_2, CRm,state->Reg[15]); | ||
| 1166 | |||
| 1167 | if (OPC_2 == 0 && CRm == 7) { | ||
| 1168 | mmu_cache_invalidate_all (state, I_CACHE ()); | ||
| 1169 | mmu_cache_invalidate_all (state, MAIN_D_CACHE ()); | ||
| 1170 | return; | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | if (OPC_2 == 0 && CRm == 5) { | ||
| 1174 | mmu_cache_invalidate_all (state, I_CACHE ()); | ||
| 1175 | return; | ||
| 1176 | } | ||
| 1177 | if (OPC_2 == 1 && CRm == 5) { | ||
| 1178 | mmu_cache_invalidate (state, I_CACHE (), value); | ||
| 1179 | return; | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | if (OPC_2 == 0 && CRm == 6) { | ||
| 1183 | mmu_cache_invalidate_all (state, MAIN_D_CACHE ()); | ||
| 1184 | return; | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | if (OPC_2 == 1 && CRm == 6) { | ||
| 1188 | mmu_cache_invalidate (state, MAIN_D_CACHE (), value); | ||
| 1189 | return; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | if (OPC_2 == 1 && CRm == 0xa) { | ||
| 1193 | mmu_cache_clean (state, MAIN_D_CACHE (), value); | ||
| 1194 | return; | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | if (OPC_2 == 4 && CRm == 0xa) { | ||
| 1198 | mmu_wb_drain_all (state, WB ()); | ||
| 1199 | return; | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | if (OPC_2 == 6 && CRm == 5) { | ||
| 1203 | //chy 2004-07-19 shoud fix in the future????!!!! | ||
| 1204 | //printf("SKYEYE: xscale_cp15_cache_ops:invalidate BTB CANT!!!!!!!!!!\n"); | ||
| 1205 | //exit(-1); | ||
| 1206 | return; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | if (OPC_2 == 5 && CRm == 2) { | ||
| 1210 | //printf("SKYEYE: cp15_c_o: A L in D C, value %x, reg15 %x\n",value, state->Reg[15]); | ||
| 1211 | //exit(-1); | ||
| 1212 | //chy 2003-09-01 for test | ||
| 1213 | mmu_cache_invalidate_all (state, MAIN_D_CACHE ()); | ||
| 1214 | return; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | ERROR_LOG(ARM11, "SKYEYE: xscale cp15_cache_ops:Unknown OPC_2 = 0x%x CRm = 0x%x, Reg15 0x%x\n", OPC_2, CRm, state->Reg[15]); | ||
| 1218 | // skyeye_exit (-1); | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | static void | ||
| 1222 | xscale_cp15_tlb_ops (ARMul_State * state, ARMword instr, | ||
| 1223 | ARMword value) | ||
| 1224 | { | ||
| 1225 | int CRm, OPC_2; | ||
| 1226 | |||
| 1227 | CRm = BITS (0, 3); | ||
| 1228 | OPC_2 = BITS (5, 7); | ||
| 1229 | |||
| 1230 | |||
| 1231 | //err_msg("SKYEYE:xscale_cp15_tlb_ops:OPC_2 = 0x%x CRm = 0x%x,Reg[15] 0x%x\n", OPC_2, CRm,state->Reg[15]); | ||
| 1232 | if (OPC_2 == 0 && CRm == 0x7) { | ||
| 1233 | mmu_tlb_invalidate_all (state, I_TLB ()); | ||
| 1234 | mmu_tlb_invalidate_all (state, D_TLB ()); | ||
| 1235 | return; | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | if (OPC_2 == 0 && CRm == 0x5) { | ||
| 1239 | mmu_tlb_invalidate_all (state, I_TLB ()); | ||
| 1240 | return; | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | if (OPC_2 == 1 && CRm == 0x5) { | ||
| 1244 | mmu_tlb_invalidate_entry (state, I_TLB (), value); | ||
| 1245 | return; | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | if (OPC_2 == 0 && CRm == 0x6) { | ||
| 1249 | mmu_tlb_invalidate_all (state, D_TLB ()); | ||
| 1250 | return; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | if (OPC_2 == 1 && CRm == 0x6) { | ||
| 1254 | mmu_tlb_invalidate_entry (state, D_TLB (), value); | ||
| 1255 | return; | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | ERROR_LOG(ARM11, "SKYEYE:xscale_cp15_tlb_ops:Unknow OPC_2 = 0x%x CRm = 0x%x,Reg[15] 0x%x\n", OPC_2, CRm, state->Reg[15]); | ||
| 1259 | // skyeye_exit (-1); | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | |||
| 1263 | ARMword xscale_cp15_mcr (ARMul_State * state, | ||
| 1264 | unsigned type, ARMword instr, ARMword value) | ||
| 1265 | { | ||
| 1266 | return xscale_mmu_mcr (state, instr, value); | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | ARMword xscale_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value) | ||
| 1270 | { | ||
| 1271 | ARMword data; | ||
| 1272 | unsigned opcode_2 = BITS (5, 7); | ||
| 1273 | unsigned CRm = BITS (0, 3); | ||
| 1274 | unsigned reg = BITS (16, 19); | ||
| 1275 | unsigned result; | ||
| 1276 | mmu_regnum_t creg = (mmu_regnum_t)reg; | ||
| 1277 | |||
| 1278 | //printf("SKYEYE: xscale_cp15_mcr: opcode_2 0x%x, CRm 0x%x, reg ox%x, value 0x%x, reg[15] 0x%x, instr 0x%x\n",opcode_2,CRm,reg, value, state->Reg[15], instr); | ||
| 1279 | |||
| 1280 | switch (creg) { | ||
| 1281 | case MMU_CONTROL: | ||
| 1282 | //printf("mmu_mcr wrote CONTROL val 0x%x \n",value); | ||
| 1283 | state->mmu.control = | ||
| 1284 | (opcode_2 ? (value & 0x33) : (value & 0x3FFF)); | ||
| 1285 | break; | ||
| 1286 | case MMU_TRANSLATION_TABLE_BASE: | ||
| 1287 | //printf("mmu_mcr wrote TTB val 0x%x \n",value); | ||
| 1288 | state->mmu.translation_table_base = value & 0xFFFFC000; | ||
| 1289 | break; | ||
| 1290 | case MMU_DOMAIN_ACCESS_CONTROL: | ||
| 1291 | //printf("mmu_mcr wrote DACR val 0x%x \n",value); | ||
| 1292 | state->mmu.domain_access_control = value; | ||
| 1293 | break; | ||
| 1294 | |||
| 1295 | case MMU_FAULT_STATUS: | ||
| 1296 | //printf("mmu_mcr wrote FS val 0x%x \n",value); | ||
| 1297 | state->mmu.fault_status = value & 0x6FF; | ||
| 1298 | break; | ||
| 1299 | case MMU_FAULT_ADDRESS: | ||
| 1300 | //printf("mmu_mcr wrote FA val 0x%x \n",value); | ||
| 1301 | state->mmu.fault_address = value; | ||
| 1302 | break; | ||
| 1303 | |||
| 1304 | case MMU_CACHE_OPS: | ||
| 1305 | // printf("mmu_mcr wrote CO val 0x%x \n",value); | ||
| 1306 | xscale_cp15_cache_ops (state, instr, value); | ||
| 1307 | break; | ||
| 1308 | case MMU_TLB_OPS: | ||
| 1309 | //printf("mmu_mcr wrote TO val 0x%x \n",value); | ||
| 1310 | xscale_cp15_tlb_ops (state, instr, value); | ||
| 1311 | break; | ||
| 1312 | case MMU_PID: | ||
| 1313 | //printf("mmu_mcr wrote PID val 0x%x \n",value); | ||
| 1314 | state->mmu.process_id = value & 0xfe000000; | ||
| 1315 | break; | ||
| 1316 | case XSCALE_CP15_COPRO_ACCESS: | ||
| 1317 | //printf("xscale cp15 write coprocessor access val 0x %x\n",value); | ||
| 1318 | state->mmu.copro_access = value & 0x3ff; | ||
| 1319 | break; | ||
| 1320 | |||
| 1321 | default: | ||
| 1322 | printf ("SKYEYE: xscale_cp15_mcr wrote UNKNOWN - reg %d, reg15 0x%x\n", creg, state->Reg[15]); | ||
| 1323 | break; | ||
| 1324 | } | ||
| 1325 | //printf("SKYEYE: xscale_cp15_mcr wrote val 0x%x\n", value); | ||
| 1326 | return 0; | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | //teawater add for arm2x86 2005.06.24------------------------------------------- | ||
| 1330 | static int xscale_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, | ||
| 1331 | ARMword * phys_addr) | ||
| 1332 | { | ||
| 1333 | fault_t fault; | ||
| 1334 | tlb_entry_t *tlb; | ||
| 1335 | |||
| 1336 | virt_addr = mmu_pid_va_map (virt_addr); | ||
| 1337 | if (MMU_Enabled) { | ||
| 1338 | |||
| 1339 | /*align check */ | ||
| 1340 | if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) { | ||
| 1341 | DEBUG_LOG(ARM11, "align\n"); | ||
| 1342 | return ALIGNMENT_FAULT; | ||
| 1343 | } | ||
| 1344 | else | ||
| 1345 | virt_addr &= ~(WORD_SIZE - 1); | ||
| 1346 | |||
| 1347 | /*translate tlb */ | ||
| 1348 | fault = translate (state, virt_addr, I_TLB (), &tlb); | ||
| 1349 | if (fault) { | ||
| 1350 | DEBUG_LOG(ARM11, "translate\n"); | ||
| 1351 | return fault; | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | /*check access */ | ||
| 1355 | fault = check_access (state, virt_addr, tlb, 1); | ||
| 1356 | if (fault) { | ||
| 1357 | DEBUG_LOG(ARM11, "check_fault\n"); | ||
| 1358 | return fault; | ||
| 1359 | } | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | if (MMU_Disabled) { | ||
| 1363 | *phys_addr = virt_addr; | ||
| 1364 | } | ||
| 1365 | else { | ||
| 1366 | *phys_addr = tlb_va_to_pa (tlb, virt_addr); | ||
| 1367 | } | ||
| 1368 | |||
| 1369 | return (0); | ||
| 1370 | } | ||
| 1371 | |||
| 1372 | //AJ2D-------------------------------------------------------------------------- | ||
| 1373 | |||
| 1374 | /*xscale mmu_ops_t*/ | ||
| 1375 | mmu_ops_t xscale_mmu_ops = { | ||
| 1376 | xscale_cp15_init, | ||
| 1377 | xscale_cp15_exit, | ||
| 1378 | xscale_mmu_read_byte, | ||
| 1379 | xscale_mmu_write_byte, | ||
| 1380 | xscale_mmu_read_halfword, | ||
| 1381 | xscale_mmu_write_halfword, | ||
| 1382 | xscale_mmu_read_word, | ||
| 1383 | xscale_mmu_write_word, | ||
| 1384 | xscale_mmu_load_instr, xscale_mmu_mcr, xscale_mmu_mrc, | ||
| 1385 | //teawater add for arm2x86 2005.06.24------------------------------------------- | ||
| 1386 | xscale_mmu_v2p_dbct, | ||
| 1387 | //AJ2D-------------------------------------------------------------------------- | ||
| 1388 | }; | ||
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index 1aaf28eee..02d0387af 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj | |||
| @@ -146,12 +146,18 @@ | |||
| 146 | <ClCompile Include="arm\interpreter\armsupp.cpp" /> | 146 | <ClCompile Include="arm\interpreter\armsupp.cpp" /> |
| 147 | <ClCompile Include="arm\interpreter\armvirt.cpp" /> | 147 | <ClCompile Include="arm\interpreter\armvirt.cpp" /> |
| 148 | <ClCompile Include="arm\interpreter\arm_interpreter.cpp" /> | 148 | <ClCompile Include="arm\interpreter\arm_interpreter.cpp" /> |
| 149 | <ClCompile Include="arm\interpreter\mmu\arm1176jzf_s_mmu.cpp" /> | ||
| 150 | <ClCompile Include="arm\interpreter\mmu\cache.cpp" /> | ||
| 151 | <ClCompile Include="arm\interpreter\mmu\rb.cpp" /> | ||
| 152 | <ClCompile Include="arm\interpreter\mmu\sa_mmu.cpp" /> | ||
| 153 | <ClCompile Include="arm\interpreter\mmu\tlb.cpp" /> | ||
| 154 | <ClCompile Include="arm\interpreter\mmu\wb.cpp" /> | ||
| 155 | <ClCompile Include="arm\interpreter\mmu\xscale_copro.cpp" /> | ||
| 149 | <ClCompile Include="arm\interpreter\thumbemu.cpp" /> | 156 | <ClCompile Include="arm\interpreter\thumbemu.cpp" /> |
| 150 | <ClCompile Include="arm\interpreter\vfp\vfp.cpp" /> | 157 | <ClCompile Include="arm\interpreter\vfp\vfp.cpp" /> |
| 151 | <ClCompile Include="arm\interpreter\vfp\vfpdouble.cpp" /> | 158 | <ClCompile Include="arm\interpreter\vfp\vfpdouble.cpp" /> |
| 152 | <ClCompile Include="arm\interpreter\vfp\vfpinstr.cpp" /> | 159 | <ClCompile Include="arm\interpreter\vfp\vfpinstr.cpp" /> |
| 153 | <ClCompile Include="arm\interpreter\vfp\vfpsingle.cpp" /> | 160 | <ClCompile Include="arm\interpreter\vfp\vfpsingle.cpp" /> |
| 154 | <ClCompile Include="arm\mmu\arm1176jzf_s_mmu.cpp" /> | ||
| 155 | <ClCompile Include="core.cpp" /> | 161 | <ClCompile Include="core.cpp" /> |
| 156 | <ClCompile Include="core_timing.cpp" /> | 162 | <ClCompile Include="core_timing.cpp" /> |
| 157 | <ClCompile Include="elf\elf_reader.cpp" /> | 163 | <ClCompile Include="elf\elf_reader.cpp" /> |
| @@ -185,15 +191,16 @@ | |||
| 185 | <ClInclude Include="arm\interpreter\armos.h" /> | 191 | <ClInclude Include="arm\interpreter\armos.h" /> |
| 186 | <ClInclude Include="arm\interpreter\arm_interpreter.h" /> | 192 | <ClInclude Include="arm\interpreter\arm_interpreter.h" /> |
| 187 | <ClInclude Include="arm\interpreter\arm_regformat.h" /> | 193 | <ClInclude Include="arm\interpreter\arm_regformat.h" /> |
| 194 | <ClInclude Include="arm\interpreter\mmu\arm1176jzf_s_mmu.h" /> | ||
| 195 | <ClInclude Include="arm\interpreter\mmu\cache.h" /> | ||
| 196 | <ClInclude Include="arm\interpreter\mmu\rb.h" /> | ||
| 197 | <ClInclude Include="arm\interpreter\mmu\sa_mmu.h" /> | ||
| 198 | <ClInclude Include="arm\interpreter\mmu\tlb.h" /> | ||
| 199 | <ClInclude Include="arm\interpreter\mmu\wb.h" /> | ||
| 188 | <ClInclude Include="arm\interpreter\skyeye_defs.h" /> | 200 | <ClInclude Include="arm\interpreter\skyeye_defs.h" /> |
| 189 | <ClInclude Include="arm\interpreter\vfp\asm_vfp.h" /> | 201 | <ClInclude Include="arm\interpreter\vfp\asm_vfp.h" /> |
| 190 | <ClInclude Include="arm\interpreter\vfp\vfp.h" /> | 202 | <ClInclude Include="arm\interpreter\vfp\vfp.h" /> |
| 191 | <ClInclude Include="arm\interpreter\vfp\vfp_helper.h" /> | 203 | <ClInclude Include="arm\interpreter\vfp\vfp_helper.h" /> |
| 192 | <ClInclude Include="arm\mmu\arm1176jzf_s_mmu.h" /> | ||
| 193 | <ClInclude Include="arm\mmu\cache.h" /> | ||
| 194 | <ClInclude Include="arm\mmu\rb.h" /> | ||
| 195 | <ClInclude Include="arm\mmu\tlb.h" /> | ||
| 196 | <ClInclude Include="arm\mmu\wb.h" /> | ||
| 197 | <ClInclude Include="core.h" /> | 204 | <ClInclude Include="core.h" /> |
| 198 | <ClInclude Include="core_timing.h" /> | 205 | <ClInclude Include="core_timing.h" /> |
| 199 | <ClInclude Include="elf\elf_reader.h" /> | 206 | <ClInclude Include="elf\elf_reader.h" /> |
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 7436b9ed0..dba6b6f67 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters | |||
| @@ -7,9 +7,6 @@ | |||
| 7 | <Filter Include="arm\disassembler"> | 7 | <Filter Include="arm\disassembler"> |
| 8 | <UniqueIdentifier>{61100188-a726-4024-ab16-95ee242b446e}</UniqueIdentifier> | 8 | <UniqueIdentifier>{61100188-a726-4024-ab16-95ee242b446e}</UniqueIdentifier> |
| 9 | </Filter> | 9 | </Filter> |
| 10 | <Filter Include="arm\mmu"> | ||
| 11 | <UniqueIdentifier>{a64d3c8a-747a-491b-b782-6e2622bedf24}</UniqueIdentifier> | ||
| 12 | </Filter> | ||
| 13 | <Filter Include="file_sys"> | 10 | <Filter Include="file_sys"> |
| 14 | <UniqueIdentifier>{7f618562-73d1-4f55-9628-887497c27654}</UniqueIdentifier> | 11 | <UniqueIdentifier>{7f618562-73d1-4f55-9628-887497c27654}</UniqueIdentifier> |
| 15 | </Filter> | 12 | </Filter> |
| @@ -31,6 +28,9 @@ | |||
| 31 | <Filter Include="arm\interpreter\vfp"> | 28 | <Filter Include="arm\interpreter\vfp"> |
| 32 | <UniqueIdentifier>{de62238f-a28e-4a33-8495-23fed6784588}</UniqueIdentifier> | 29 | <UniqueIdentifier>{de62238f-a28e-4a33-8495-23fed6784588}</UniqueIdentifier> |
| 33 | </Filter> | 30 | </Filter> |
| 31 | <Filter Include="arm\interpreter\mmu"> | ||
| 32 | <UniqueIdentifier>{13ef9860-2ba0-47e9-a93d-b4052adab269}</UniqueIdentifier> | ||
| 33 | </Filter> | ||
| 34 | </ItemGroup> | 34 | </ItemGroup> |
| 35 | <ItemGroup> | 35 | <ItemGroup> |
| 36 | <ClCompile Include="arm\disassembler\arm_disasm.cpp"> | 36 | <ClCompile Include="arm\disassembler\arm_disasm.cpp"> |
| @@ -60,9 +60,6 @@ | |||
| 60 | <ClCompile Include="arm\interpreter\thumbemu.cpp"> | 60 | <ClCompile Include="arm\interpreter\thumbemu.cpp"> |
| 61 | <Filter>arm\interpreter</Filter> | 61 | <Filter>arm\interpreter</Filter> |
| 62 | </ClCompile> | 62 | </ClCompile> |
| 63 | <ClCompile Include="arm\mmu\arm1176jzf_s_mmu.cpp"> | ||
| 64 | <Filter>arm\mmu</Filter> | ||
| 65 | </ClCompile> | ||
| 66 | <ClCompile Include="file_sys\directory_file_system.cpp"> | 63 | <ClCompile Include="file_sys\directory_file_system.cpp"> |
| 67 | <Filter>file_sys</Filter> | 64 | <Filter>file_sys</Filter> |
| 68 | </ClCompile> | 65 | </ClCompile> |
| @@ -129,6 +126,27 @@ | |||
| 129 | <ClCompile Include="arm\interpreter\vfp\vfpsingle.cpp"> | 126 | <ClCompile Include="arm\interpreter\vfp\vfpsingle.cpp"> |
| 130 | <Filter>arm\interpreter\vfp</Filter> | 127 | <Filter>arm\interpreter\vfp</Filter> |
| 131 | </ClCompile> | 128 | </ClCompile> |
| 129 | <ClCompile Include="arm\interpreter\mmu\arm1176jzf_s_mmu.cpp"> | ||
| 130 | <Filter>arm\interpreter\mmu</Filter> | ||
| 131 | </ClCompile> | ||
| 132 | <ClCompile Include="arm\interpreter\mmu\xscale_copro.cpp"> | ||
| 133 | <Filter>arm\interpreter\mmu</Filter> | ||
| 134 | </ClCompile> | ||
| 135 | <ClCompile Include="arm\interpreter\mmu\sa_mmu.cpp"> | ||
| 136 | <Filter>arm\interpreter\mmu</Filter> | ||
| 137 | </ClCompile> | ||
| 138 | <ClCompile Include="arm\interpreter\mmu\cache.cpp"> | ||
| 139 | <Filter>arm\interpreter\mmu</Filter> | ||
| 140 | </ClCompile> | ||
| 141 | <ClCompile Include="arm\interpreter\mmu\rb.cpp"> | ||
| 142 | <Filter>arm\interpreter\mmu</Filter> | ||
| 143 | </ClCompile> | ||
| 144 | <ClCompile Include="arm\interpreter\mmu\tlb.cpp"> | ||
| 145 | <Filter>arm\interpreter\mmu</Filter> | ||
| 146 | </ClCompile> | ||
| 147 | <ClCompile Include="arm\interpreter\mmu\wb.cpp"> | ||
| 148 | <Filter>arm\interpreter\mmu</Filter> | ||
| 149 | </ClCompile> | ||
| 132 | </ItemGroup> | 150 | </ItemGroup> |
| 133 | <ItemGroup> | 151 | <ItemGroup> |
| 134 | <ClInclude Include="arm\disassembler\arm_disasm.h"> | 152 | <ClInclude Include="arm\disassembler\arm_disasm.h"> |
| @@ -158,21 +176,6 @@ | |||
| 158 | <ClInclude Include="arm\interpreter\skyeye_defs.h"> | 176 | <ClInclude Include="arm\interpreter\skyeye_defs.h"> |
| 159 | <Filter>arm\interpreter</Filter> | 177 | <Filter>arm\interpreter</Filter> |
| 160 | </ClInclude> | 178 | </ClInclude> |
| 161 | <ClInclude Include="arm\mmu\arm1176jzf_s_mmu.h"> | ||
| 162 | <Filter>arm\mmu</Filter> | ||
| 163 | </ClInclude> | ||
| 164 | <ClInclude Include="arm\mmu\cache.h"> | ||
| 165 | <Filter>arm\mmu</Filter> | ||
| 166 | </ClInclude> | ||
| 167 | <ClInclude Include="arm\mmu\rb.h"> | ||
| 168 | <Filter>arm\mmu</Filter> | ||
| 169 | </ClInclude> | ||
| 170 | <ClInclude Include="arm\mmu\tlb.h"> | ||
| 171 | <Filter>arm\mmu</Filter> | ||
| 172 | </ClInclude> | ||
| 173 | <ClInclude Include="arm\mmu\wb.h"> | ||
| 174 | <Filter>arm\mmu</Filter> | ||
| 175 | </ClInclude> | ||
| 176 | <ClInclude Include="file_sys\directory_file_system.h"> | 179 | <ClInclude Include="file_sys\directory_file_system.h"> |
| 177 | <Filter>file_sys</Filter> | 180 | <Filter>file_sys</Filter> |
| 178 | </ClInclude> | 181 | </ClInclude> |
| @@ -247,6 +250,24 @@ | |||
| 247 | <ClInclude Include="arm\interpreter\vfp\vfp_helper.h"> | 250 | <ClInclude Include="arm\interpreter\vfp\vfp_helper.h"> |
| 248 | <Filter>arm\interpreter\vfp</Filter> | 251 | <Filter>arm\interpreter\vfp</Filter> |
| 249 | </ClInclude> | 252 | </ClInclude> |
| 253 | <ClInclude Include="arm\interpreter\mmu\arm1176jzf_s_mmu.h"> | ||
| 254 | <Filter>arm\interpreter\mmu</Filter> | ||
| 255 | </ClInclude> | ||
| 256 | <ClInclude Include="arm\interpreter\mmu\cache.h"> | ||
| 257 | <Filter>arm\interpreter\mmu</Filter> | ||
| 258 | </ClInclude> | ||
| 259 | <ClInclude Include="arm\interpreter\mmu\rb.h"> | ||
| 260 | <Filter>arm\interpreter\mmu</Filter> | ||
| 261 | </ClInclude> | ||
| 262 | <ClInclude Include="arm\interpreter\mmu\tlb.h"> | ||
| 263 | <Filter>arm\interpreter\mmu</Filter> | ||
| 264 | </ClInclude> | ||
| 265 | <ClInclude Include="arm\interpreter\mmu\wb.h"> | ||
| 266 | <Filter>arm\interpreter\mmu</Filter> | ||
| 267 | </ClInclude> | ||
| 268 | <ClInclude Include="arm\interpreter\mmu\sa_mmu.h"> | ||
| 269 | <Filter>arm\interpreter\mmu</Filter> | ||
| 270 | </ClInclude> | ||
| 250 | </ItemGroup> | 271 | </ItemGroup> |
| 251 | <ItemGroup> | 272 | <ItemGroup> |
| 252 | <Text Include="CMakeLists.txt" /> | 273 | <Text Include="CMakeLists.txt" /> |