]>
Commit | Line | Data |
---|---|---|
e8af50a3 FB |
1 | #include <math.h> |
2 | #include <fenv.h> | |
3 | #include "exec.h" | |
4 | ||
e80cfcfc FB |
5 | //#define DEBUG_MMU |
6 | ||
9d893301 FB |
7 | void raise_exception(int tt) |
8 | { | |
9 | env->exception_index = tt; | |
10 | cpu_loop_exit(); | |
11 | } | |
12 | ||
a0c4cb4a FB |
13 | #ifdef USE_INT_TO_FLOAT_HELPERS |
14 | void do_fitos(void) | |
15 | { | |
16 | FT0 = (float) *((int32_t *)&FT1); | |
17 | } | |
18 | ||
19 | void do_fitod(void) | |
20 | { | |
21 | DT0 = (double) *((int32_t *)&FT1); | |
22 | } | |
23 | #endif | |
24 | ||
25 | void do_fabss(void) | |
e8af50a3 FB |
26 | { |
27 | FT0 = fabsf(FT1); | |
28 | } | |
29 | ||
a0c4cb4a | 30 | void do_fsqrts(void) |
e8af50a3 FB |
31 | { |
32 | FT0 = sqrtf(FT1); | |
33 | } | |
34 | ||
a0c4cb4a | 35 | void do_fsqrtd(void) |
e8af50a3 FB |
36 | { |
37 | DT0 = sqrt(DT1); | |
38 | } | |
39 | ||
a0c4cb4a | 40 | void do_fcmps (void) |
e8af50a3 FB |
41 | { |
42 | if (isnan(FT0) || isnan(FT1)) { | |
43 | T0 = FSR_FCC1 | FSR_FCC0; | |
e80cfcfc FB |
44 | env->fsr &= ~(FSR_FCC1 | FSR_FCC0); |
45 | env->fsr |= T0; | |
46 | if (env->fsr & FSR_NVM) { | |
47 | raise_exception(TT_FP_EXCP); | |
48 | } else { | |
49 | env->fsr |= FSR_NVA; | |
50 | } | |
e8af50a3 FB |
51 | } else if (FT0 < FT1) { |
52 | T0 = FSR_FCC0; | |
53 | } else if (FT0 > FT1) { | |
54 | T0 = FSR_FCC1; | |
55 | } else { | |
56 | T0 = 0; | |
57 | } | |
58 | env->fsr = T0; | |
59 | } | |
60 | ||
a0c4cb4a | 61 | void do_fcmpd (void) |
e8af50a3 FB |
62 | { |
63 | if (isnan(DT0) || isnan(DT1)) { | |
64 | T0 = FSR_FCC1 | FSR_FCC0; | |
e80cfcfc FB |
65 | env->fsr &= ~(FSR_FCC1 | FSR_FCC0); |
66 | env->fsr |= T0; | |
67 | if (env->fsr & FSR_NVM) { | |
68 | raise_exception(TT_FP_EXCP); | |
69 | } else { | |
70 | env->fsr |= FSR_NVA; | |
71 | } | |
e8af50a3 FB |
72 | } else if (DT0 < DT1) { |
73 | T0 = FSR_FCC0; | |
74 | } else if (DT0 > DT1) { | |
75 | T0 = FSR_FCC1; | |
76 | } else { | |
77 | T0 = 0; | |
78 | } | |
79 | env->fsr = T0; | |
80 | } | |
81 | ||
a0c4cb4a | 82 | void helper_ld_asi(int asi, int size, int sign) |
e8af50a3 | 83 | { |
e80cfcfc FB |
84 | uint32_t ret; |
85 | ||
86 | switch (asi) { | |
e8af50a3 | 87 | case 3: /* MMU probe */ |
e80cfcfc FB |
88 | { |
89 | int mmulev; | |
90 | ||
91 | mmulev = (T0 >> 8) & 15; | |
92 | if (mmulev > 4) | |
93 | ret = 0; | |
94 | else { | |
95 | ret = mmu_probe(T0, mmulev); | |
96 | //bswap32s(&ret); | |
97 | } | |
98 | #ifdef DEBUG_MMU | |
99 | printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret); | |
100 | #endif | |
101 | } | |
102 | break; | |
e8af50a3 FB |
103 | case 4: /* read MMU regs */ |
104 | { | |
e80cfcfc | 105 | int reg = (T0 >> 8) & 0xf; |
e8af50a3 | 106 | |
e80cfcfc | 107 | ret = env->mmuregs[reg]; |
55754d9e FB |
108 | if (reg == 3) /* Fault status cleared on read */ |
109 | env->mmuregs[reg] = 0; | |
110 | #ifdef DEBUG_MMU | |
111 | printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret); | |
112 | #endif | |
e8af50a3 | 113 | } |
e80cfcfc | 114 | break; |
e8af50a3 | 115 | case 0x20 ... 0x2f: /* MMU passthrough */ |
e80cfcfc FB |
116 | cpu_physical_memory_read(T0, (void *) &ret, size); |
117 | if (size == 4) | |
49be8030 FB |
118 | tswap32s(&ret); |
119 | else if (size == 2) | |
120 | tswap16s((uint16_t *)&ret); | |
e80cfcfc | 121 | break; |
e8af50a3 | 122 | default: |
e80cfcfc FB |
123 | ret = 0; |
124 | break; | |
e8af50a3 | 125 | } |
e80cfcfc | 126 | T1 = ret; |
e8af50a3 FB |
127 | } |
128 | ||
a0c4cb4a | 129 | void helper_st_asi(int asi, int size, int sign) |
e8af50a3 FB |
130 | { |
131 | switch(asi) { | |
132 | case 3: /* MMU flush */ | |
e80cfcfc FB |
133 | { |
134 | int mmulev; | |
135 | ||
136 | mmulev = (T0 >> 8) & 15; | |
55754d9e FB |
137 | #ifdef DEBUG_MMU |
138 | printf("mmu flush level %d\n", mmulev); | |
139 | #endif | |
e80cfcfc FB |
140 | switch (mmulev) { |
141 | case 0: // flush page | |
55754d9e | 142 | tlb_flush_page(env, T0 & 0xfffff000); |
e80cfcfc FB |
143 | break; |
144 | case 1: // flush segment (256k) | |
145 | case 2: // flush region (16M) | |
146 | case 3: // flush context (4G) | |
147 | case 4: // flush entire | |
55754d9e | 148 | tlb_flush(env, 1); |
e80cfcfc FB |
149 | break; |
150 | default: | |
151 | break; | |
152 | } | |
55754d9e | 153 | #ifdef DEBUG_MMU |
e80cfcfc | 154 | dump_mmu(); |
55754d9e | 155 | #endif |
e80cfcfc FB |
156 | return; |
157 | } | |
e8af50a3 FB |
158 | case 4: /* write MMU regs */ |
159 | { | |
e80cfcfc FB |
160 | int reg = (T0 >> 8) & 0xf, oldreg; |
161 | ||
162 | oldreg = env->mmuregs[reg]; | |
55754d9e FB |
163 | switch(reg) { |
164 | case 0: | |
e8af50a3 FB |
165 | env->mmuregs[reg] &= ~(MMU_E | MMU_NF); |
166 | env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF); | |
55754d9e FB |
167 | if ((oldreg & MMU_E) != (env->mmuregs[reg] & MMU_E)) |
168 | tlb_flush(env, 1); | |
169 | break; | |
170 | case 2: | |
e8af50a3 | 171 | env->mmuregs[reg] = T1; |
55754d9e FB |
172 | if (oldreg != env->mmuregs[reg]) { |
173 | /* we flush when the MMU context changes because | |
174 | QEMU has no MMU context support */ | |
175 | tlb_flush(env, 1); | |
176 | } | |
177 | break; | |
178 | case 3: | |
179 | case 4: | |
180 | break; | |
181 | default: | |
182 | env->mmuregs[reg] = T1; | |
183 | break; | |
184 | } | |
185 | #ifdef DEBUG_MMU | |
186 | if (oldreg != env->mmuregs[reg]) { | |
187 | printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]); | |
188 | } | |
e80cfcfc | 189 | dump_mmu(); |
55754d9e | 190 | #endif |
e8af50a3 FB |
191 | return; |
192 | } | |
e80cfcfc FB |
193 | case 0x17: /* Block copy, sta access */ |
194 | { | |
195 | // value (T1) = src | |
196 | // address (T0) = dst | |
197 | // copy 32 bytes | |
198 | int src = T1, dst = T0; | |
199 | uint8_t temp[32]; | |
200 | ||
49be8030 | 201 | tswap32s(&src); |
e80cfcfc FB |
202 | |
203 | cpu_physical_memory_read(src, (void *) &temp, 32); | |
204 | cpu_physical_memory_write(dst, (void *) &temp, 32); | |
205 | } | |
206 | return; | |
207 | case 0x1f: /* Block fill, stda access */ | |
208 | { | |
209 | // value (T1, T2) | |
210 | // address (T0) = dst | |
211 | // fill 32 bytes | |
212 | int i, dst = T0; | |
213 | uint64_t val; | |
214 | ||
215 | val = (((uint64_t)T1) << 32) | T2; | |
49be8030 | 216 | tswap64s(&val); |
e80cfcfc FB |
217 | |
218 | for (i = 0; i < 32; i += 8, dst += 8) { | |
219 | cpu_physical_memory_write(dst, (void *) &val, 8); | |
220 | } | |
221 | } | |
222 | return; | |
e8af50a3 FB |
223 | case 0x20 ... 0x2f: /* MMU passthrough */ |
224 | { | |
225 | int temp = T1; | |
e80cfcfc | 226 | if (size == 4) |
49be8030 | 227 | tswap32s(&temp); |
e80cfcfc | 228 | else if (size == 2) |
49be8030 | 229 | tswap16s((uint16_t *)&temp); |
e8af50a3 FB |
230 | cpu_physical_memory_write(T0, (void *) &temp, size); |
231 | } | |
232 | return; | |
233 | default: | |
234 | return; | |
235 | } | |
236 | } | |
237 | ||
a0c4cb4a | 238 | void helper_rett() |
e8af50a3 | 239 | { |
af7bf89b FB |
240 | unsigned int cwp; |
241 | ||
e8af50a3 FB |
242 | env->psret = 1; |
243 | cwp = (env->cwp + 1) & (NWINDOWS - 1); | |
244 | if (env->wim & (1 << cwp)) { | |
245 | raise_exception(TT_WIN_UNF); | |
246 | } | |
247 | set_cwp(cwp); | |
248 | env->psrs = env->psrps; | |
249 | } | |
250 | ||
8d5f07fa | 251 | void helper_ldfsr(void) |
e8af50a3 FB |
252 | { |
253 | switch (env->fsr & FSR_RD_MASK) { | |
254 | case FSR_RD_NEAREST: | |
255 | fesetround(FE_TONEAREST); | |
256 | break; | |
257 | case FSR_RD_ZERO: | |
258 | fesetround(FE_TOWARDZERO); | |
259 | break; | |
260 | case FSR_RD_POS: | |
261 | fesetround(FE_UPWARD); | |
262 | break; | |
263 | case FSR_RD_NEG: | |
264 | fesetround(FE_DOWNWARD); | |
265 | break; | |
266 | } | |
267 | } | |
e80cfcfc FB |
268 | |
269 | void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f) | |
270 | { | |
271 | int exptemp; | |
272 | ||
273 | *pmant = ldexp(frexp(f, &exptemp), 53); | |
274 | *pexp = exptemp; | |
275 | } | |
276 | ||
277 | double cpu_put_fp64(uint64_t mant, uint16_t exp) | |
278 | { | |
279 | return ldexp((double) mant, exp - 53); | |
280 | } | |
281 | ||
282 | void helper_debug() | |
283 | { | |
284 | env->exception_index = EXCP_DEBUG; | |
285 | cpu_loop_exit(); | |
286 | } | |
af7bf89b FB |
287 | |
288 | void do_wrpsr() | |
289 | { | |
290 | PUT_PSR(env, T0); | |
291 | } | |
292 | ||
293 | void do_rdpsr() | |
294 | { | |
295 | T0 = GET_PSR(env); | |
296 | } |