]>
Commit | Line | Data |
---|---|---|
2328826b MF |
1 | /* |
2 | * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab. | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions are met: | |
7 | * * Redistributions of source code must retain the above copyright | |
8 | * notice, this list of conditions and the following disclaimer. | |
9 | * * Redistributions in binary form must reproduce the above copyright | |
10 | * notice, this list of conditions and the following disclaimer in the | |
11 | * documentation and/or other materials provided with the distribution. | |
12 | * * Neither the name of the Open Source and Linux Lab nor the | |
13 | * names of its contributors may be used to endorse or promote products | |
14 | * derived from this software without specific prior written permission. | |
15 | * | |
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 | */ | |
27 | ||
09aae23d | 28 | #include "qemu/osdep.h" |
47e20887 | 29 | #include "qemu/main-loop.h" |
2328826b | 30 | #include "cpu.h" |
2ef6175a | 31 | #include "exec/helper-proto.h" |
1de7afc9 | 32 | #include "qemu/host-utils.h" |
63c91552 | 33 | #include "exec/exec-all.h" |
f08b6170 | 34 | #include "exec/cpu_ldst.h" |
29d8ec7b | 35 | #include "exec/address-spaces.h" |
0f590e74 | 36 | #include "qemu/timer.h" |
2328826b | 37 | |
ba7651fb MF |
38 | #ifndef CONFIG_USER_ONLY |
39 | ||
59a71f75 MF |
40 | void HELPER(update_ccount)(CPUXtensaState *env) |
41 | { | |
42 | uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); | |
43 | ||
44 | env->ccount_time = now; | |
45 | env->sregs[CCOUNT] = env->ccount_base + | |
46 | (uint32_t)((now - env->time_base) * | |
47 | env->config->clock_freq_khz / 1000000); | |
48 | } | |
49 | ||
50 | void HELPER(wsr_ccount)(CPUXtensaState *env, uint32_t v) | |
b994e91b | 51 | { |
59a71f75 MF |
52 | int i; |
53 | ||
54 | HELPER(update_ccount)(env); | |
55 | env->ccount_base += v - env->sregs[CCOUNT]; | |
56 | for (i = 0; i < env->config->nccompare; ++i) { | |
57 | HELPER(update_ccompare)(env, i); | |
58 | } | |
b994e91b MF |
59 | } |
60 | ||
59a71f75 | 61 | void HELPER(update_ccompare)(CPUXtensaState *env, uint32_t i) |
b994e91b | 62 | { |
59a71f75 MF |
63 | uint64_t dcc; |
64 | ||
65 | HELPER(update_ccount)(env); | |
66 | dcc = (uint64_t)(env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] - 1) + 1; | |
67 | timer_mod(env->ccompare[i].timer, | |
68 | env->ccount_time + (dcc * 1000000) / env->config->clock_freq_khz); | |
d2132510 | 69 | env->yield_needed = 1; |
b994e91b MF |
70 | } |
71 | ||
fcc803d1 MF |
72 | /*! |
73 | * Check vaddr accessibility/cache attributes and raise an exception if | |
74 | * specified by the ATOMCTL SR. | |
75 | * | |
76 | * Note: local memory exclusion is not implemented | |
77 | */ | |
78 | void HELPER(check_atomctl)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr) | |
79 | { | |
80 | uint32_t paddr, page_size, access; | |
81 | uint32_t atomctl = env->sregs[ATOMCTL]; | |
82 | int rc = xtensa_get_physical_addr(env, true, vaddr, 1, | |
83 | xtensa_get_cring(env), &paddr, &page_size, &access); | |
84 | ||
85 | /* | |
86 | * s32c1i never causes LOAD_PROHIBITED_CAUSE exceptions, | |
87 | * see opcode description in the ISA | |
88 | */ | |
89 | if (rc == 0 && | |
90 | (access & (PAGE_READ | PAGE_WRITE)) != (PAGE_READ | PAGE_WRITE)) { | |
91 | rc = STORE_PROHIBITED_CAUSE; | |
92 | } | |
93 | ||
94 | if (rc) { | |
95 | HELPER(exception_cause_vaddr)(env, pc, rc, vaddr); | |
96 | } | |
97 | ||
98 | /* | |
99 | * When data cache is not configured use ATOMCTL bypass field. | |
100 | * See ISA, 4.3.12.4 The Atomic Operation Control Register (ATOMCTL) | |
101 | * under the Conditional Store Option. | |
102 | */ | |
103 | if (!xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) { | |
104 | access = PAGE_CACHE_BYPASS; | |
105 | } | |
106 | ||
107 | switch (access & PAGE_CACHE_MASK) { | |
108 | case PAGE_CACHE_WB: | |
109 | atomctl >>= 2; | |
5739006b | 110 | /* fall through */ |
fcc803d1 MF |
111 | case PAGE_CACHE_WT: |
112 | atomctl >>= 2; | |
5739006b | 113 | /* fall through */ |
fcc803d1 MF |
114 | case PAGE_CACHE_BYPASS: |
115 | if ((atomctl & 0x3) == 0) { | |
116 | HELPER(exception_cause_vaddr)(env, pc, | |
117 | LOAD_STORE_ERROR_CAUSE, vaddr); | |
118 | } | |
119 | break; | |
120 | ||
121 | case PAGE_CACHE_ISOLATE: | |
122 | HELPER(exception_cause_vaddr)(env, pc, | |
123 | LOAD_STORE_ERROR_CAUSE, vaddr); | |
124 | break; | |
125 | ||
126 | default: | |
127 | break; | |
128 | } | |
129 | } | |
130 | ||
9e03ade4 MF |
131 | void HELPER(wsr_memctl)(CPUXtensaState *env, uint32_t v) |
132 | { | |
133 | if (xtensa_option_enabled(env->config, XTENSA_OPTION_ICACHE)) { | |
134 | if (extract32(v, MEMCTL_IUSEWAYS_SHIFT, MEMCTL_IUSEWAYS_LEN) > | |
135 | env->config->icache_ways) { | |
136 | deposit32(v, MEMCTL_IUSEWAYS_SHIFT, MEMCTL_IUSEWAYS_LEN, | |
137 | env->config->icache_ways); | |
138 | } | |
139 | } | |
140 | if (xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) { | |
141 | if (extract32(v, MEMCTL_DUSEWAYS_SHIFT, MEMCTL_DUSEWAYS_LEN) > | |
142 | env->config->dcache_ways) { | |
143 | deposit32(v, MEMCTL_DUSEWAYS_SHIFT, MEMCTL_DUSEWAYS_LEN, | |
144 | env->config->dcache_ways); | |
145 | } | |
146 | if (extract32(v, MEMCTL_DALLOCWAYS_SHIFT, MEMCTL_DALLOCWAYS_LEN) > | |
147 | env->config->dcache_ways) { | |
148 | deposit32(v, MEMCTL_DALLOCWAYS_SHIFT, MEMCTL_DALLOCWAYS_LEN, | |
149 | env->config->dcache_ways); | |
150 | } | |
151 | } | |
152 | env->sregs[MEMCTL] = v & env->config->memctl_mask; | |
153 | } | |
154 | ||
ba7651fb | 155 | #endif |
dd519cbe | 156 | |
3a3c9dc4 MF |
157 | uint32_t HELPER(rer)(CPUXtensaState *env, uint32_t addr) |
158 | { | |
ba7651fb | 159 | #ifndef CONFIG_USER_ONLY |
3a3c9dc4 | 160 | return address_space_ldl(env->address_space_er, addr, |
2c5b1d2a | 161 | MEMTXATTRS_UNSPECIFIED, NULL); |
ba7651fb MF |
162 | #else |
163 | return 0; | |
164 | #endif | |
3a3c9dc4 MF |
165 | } |
166 | ||
167 | void HELPER(wer)(CPUXtensaState *env, uint32_t data, uint32_t addr) | |
168 | { | |
ba7651fb | 169 | #ifndef CONFIG_USER_ONLY |
3a3c9dc4 | 170 | address_space_stl(env->address_space_er, addr, data, |
2c5b1d2a | 171 | MEMTXATTRS_UNSPECIFIED, NULL); |
ba7651fb | 172 | #endif |
3a3c9dc4 | 173 | } |