1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include "qemu/osdep.h"
29#include "qemu/main-loop.h"
30#include "cpu.h"
31#include "exec/helper-proto.h"
32#include "qemu/host-utils.h"
33#include "exec/exec-all.h"
34#include "exec/cpu_ldst.h"
35#include "exec/address-spaces.h"
36#include "qemu/timer.h"
37
38#ifndef CONFIG_USER_ONLY
39
40void 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
50void HELPER(wsr_ccount)(CPUXtensaState *env, uint32_t v)
51{
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 }
59}
60
61void HELPER(update_ccompare)(CPUXtensaState *env, uint32_t i)
62{
63 uint64_t dcc;
64
65 atomic_and(&env->sregs[INTSET],
66 ~(1u << env->config->timerint[i]));
67 HELPER(update_ccount)(env);
68 dcc = (uint64_t)(env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] - 1) + 1;
69 timer_mod(env->ccompare[i].timer,
70 env->ccount_time + (dcc * 1000000) / env->config->clock_freq_khz);
71 env->yield_needed = 1;
72}
73
74
75
76
77
78
79
80void HELPER(check_atomctl)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr)
81{
82 uint32_t paddr, page_size, access;
83 uint32_t atomctl = env->sregs[ATOMCTL];
84 int rc = xtensa_get_physical_addr(env, true, vaddr, 1,
85 xtensa_get_cring(env), &paddr, &page_size, &access);
86
87
88
89
90
91 if (rc == 0 &&
92 (access & (PAGE_READ | PAGE_WRITE)) != (PAGE_READ | PAGE_WRITE)) {
93 rc = STORE_PROHIBITED_CAUSE;
94 }
95
96 if (rc) {
97 HELPER(exception_cause_vaddr)(env, pc, rc, vaddr);
98 }
99
100
101
102
103
104
105 if (!xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) {
106 access = PAGE_CACHE_BYPASS;
107 }
108
109 switch (access & PAGE_CACHE_MASK) {
110 case PAGE_CACHE_WB:
111 atomctl >>= 2;
112
113 case PAGE_CACHE_WT:
114 atomctl >>= 2;
115
116 case PAGE_CACHE_BYPASS:
117 if ((atomctl & 0x3) == 0) {
118 HELPER(exception_cause_vaddr)(env, pc,
119 LOAD_STORE_ERROR_CAUSE, vaddr);
120 }
121 break;
122
123 case PAGE_CACHE_ISOLATE:
124 HELPER(exception_cause_vaddr)(env, pc,
125 LOAD_STORE_ERROR_CAUSE, vaddr);
126 break;
127
128 default:
129 break;
130 }
131}
132
133void HELPER(wsr_memctl)(CPUXtensaState *env, uint32_t v)
134{
135 if (xtensa_option_enabled(env->config, XTENSA_OPTION_ICACHE)) {
136 if (extract32(v, MEMCTL_IUSEWAYS_SHIFT, MEMCTL_IUSEWAYS_LEN) >
137 env->config->icache_ways) {
138 deposit32(v, MEMCTL_IUSEWAYS_SHIFT, MEMCTL_IUSEWAYS_LEN,
139 env->config->icache_ways);
140 }
141 }
142 if (xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) {
143 if (extract32(v, MEMCTL_DUSEWAYS_SHIFT, MEMCTL_DUSEWAYS_LEN) >
144 env->config->dcache_ways) {
145 deposit32(v, MEMCTL_DUSEWAYS_SHIFT, MEMCTL_DUSEWAYS_LEN,
146 env->config->dcache_ways);
147 }
148 if (extract32(v, MEMCTL_DALLOCWAYS_SHIFT, MEMCTL_DALLOCWAYS_LEN) >
149 env->config->dcache_ways) {
150 deposit32(v, MEMCTL_DALLOCWAYS_SHIFT, MEMCTL_DALLOCWAYS_LEN,
151 env->config->dcache_ways);
152 }
153 }
154 env->sregs[MEMCTL] = v & env->config->memctl_mask;
155}
156
157#endif
158
159uint32_t HELPER(rer)(CPUXtensaState *env, uint32_t addr)
160{
161#ifndef CONFIG_USER_ONLY
162 return address_space_ldl(env->address_space_er, addr,
163 MEMTXATTRS_UNSPECIFIED, NULL);
164#else
165 return 0;
166#endif
167}
168
169void HELPER(wer)(CPUXtensaState *env, uint32_t data, uint32_t addr)
170{
171#ifndef CONFIG_USER_ONLY
172 address_space_stl(env->address_space_er, addr, data,
173 MEMTXATTRS_UNSPECIFIED, NULL);
174#endif
175}
176