]>
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]; |
e8af50a3 | 108 | if (reg == 3 || reg == 4) /* Fault status, addr cleared on read*/ |
e80cfcfc | 109 | env->mmuregs[4] = 0; |
e8af50a3 | 110 | } |
e80cfcfc | 111 | break; |
e8af50a3 | 112 | case 0x20 ... 0x2f: /* MMU passthrough */ |
e80cfcfc FB |
113 | cpu_physical_memory_read(T0, (void *) &ret, size); |
114 | if (size == 4) | |
49be8030 FB |
115 | tswap32s(&ret); |
116 | else if (size == 2) | |
117 | tswap16s((uint16_t *)&ret); | |
e80cfcfc | 118 | break; |
e8af50a3 | 119 | default: |
e80cfcfc FB |
120 | ret = 0; |
121 | break; | |
e8af50a3 | 122 | } |
e80cfcfc | 123 | T1 = ret; |
e8af50a3 FB |
124 | } |
125 | ||
a0c4cb4a | 126 | void helper_st_asi(int asi, int size, int sign) |
e8af50a3 FB |
127 | { |
128 | switch(asi) { | |
129 | case 3: /* MMU flush */ | |
e80cfcfc FB |
130 | { |
131 | int mmulev; | |
132 | ||
133 | mmulev = (T0 >> 8) & 15; | |
134 | switch (mmulev) { | |
135 | case 0: // flush page | |
136 | tlb_flush_page(cpu_single_env, T0 & 0xfffff000); | |
137 | break; | |
138 | case 1: // flush segment (256k) | |
139 | case 2: // flush region (16M) | |
140 | case 3: // flush context (4G) | |
141 | case 4: // flush entire | |
142 | tlb_flush(cpu_single_env, 1); | |
143 | break; | |
144 | default: | |
145 | break; | |
146 | } | |
147 | dump_mmu(); | |
148 | return; | |
149 | } | |
e8af50a3 FB |
150 | case 4: /* write MMU regs */ |
151 | { | |
e80cfcfc FB |
152 | int reg = (T0 >> 8) & 0xf, oldreg; |
153 | ||
154 | oldreg = env->mmuregs[reg]; | |
e8af50a3 FB |
155 | if (reg == 0) { |
156 | env->mmuregs[reg] &= ~(MMU_E | MMU_NF); | |
157 | env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF); | |
158 | } else | |
159 | env->mmuregs[reg] = T1; | |
e80cfcfc FB |
160 | if (oldreg != env->mmuregs[reg]) { |
161 | #if 0 | |
162 | // XXX: Only if MMU mapping change, we may need to flush? | |
163 | tlb_flush(cpu_single_env, 1); | |
164 | cpu_loop_exit(); | |
165 | FORCE_RET(); | |
166 | #endif | |
167 | } | |
168 | dump_mmu(); | |
e8af50a3 FB |
169 | return; |
170 | } | |
e80cfcfc FB |
171 | case 0x17: /* Block copy, sta access */ |
172 | { | |
173 | // value (T1) = src | |
174 | // address (T0) = dst | |
175 | // copy 32 bytes | |
176 | int src = T1, dst = T0; | |
177 | uint8_t temp[32]; | |
178 | ||
49be8030 | 179 | tswap32s(&src); |
e80cfcfc FB |
180 | |
181 | cpu_physical_memory_read(src, (void *) &temp, 32); | |
182 | cpu_physical_memory_write(dst, (void *) &temp, 32); | |
183 | } | |
184 | return; | |
185 | case 0x1f: /* Block fill, stda access */ | |
186 | { | |
187 | // value (T1, T2) | |
188 | // address (T0) = dst | |
189 | // fill 32 bytes | |
190 | int i, dst = T0; | |
191 | uint64_t val; | |
192 | ||
193 | val = (((uint64_t)T1) << 32) | T2; | |
49be8030 | 194 | tswap64s(&val); |
e80cfcfc FB |
195 | |
196 | for (i = 0; i < 32; i += 8, dst += 8) { | |
197 | cpu_physical_memory_write(dst, (void *) &val, 8); | |
198 | } | |
199 | } | |
200 | return; | |
e8af50a3 FB |
201 | case 0x20 ... 0x2f: /* MMU passthrough */ |
202 | { | |
203 | int temp = T1; | |
e80cfcfc | 204 | if (size == 4) |
49be8030 | 205 | tswap32s(&temp); |
e80cfcfc | 206 | else if (size == 2) |
49be8030 | 207 | tswap16s((uint16_t *)&temp); |
e8af50a3 FB |
208 | cpu_physical_memory_write(T0, (void *) &temp, size); |
209 | } | |
210 | return; | |
211 | default: | |
212 | return; | |
213 | } | |
214 | } | |
215 | ||
a0c4cb4a | 216 | void helper_rett() |
e8af50a3 | 217 | { |
af7bf89b FB |
218 | unsigned int cwp; |
219 | ||
e8af50a3 FB |
220 | env->psret = 1; |
221 | cwp = (env->cwp + 1) & (NWINDOWS - 1); | |
222 | if (env->wim & (1 << cwp)) { | |
223 | raise_exception(TT_WIN_UNF); | |
224 | } | |
225 | set_cwp(cwp); | |
226 | env->psrs = env->psrps; | |
227 | } | |
228 | ||
8d5f07fa | 229 | void helper_ldfsr(void) |
e8af50a3 FB |
230 | { |
231 | switch (env->fsr & FSR_RD_MASK) { | |
232 | case FSR_RD_NEAREST: | |
233 | fesetround(FE_TONEAREST); | |
234 | break; | |
235 | case FSR_RD_ZERO: | |
236 | fesetround(FE_TOWARDZERO); | |
237 | break; | |
238 | case FSR_RD_POS: | |
239 | fesetround(FE_UPWARD); | |
240 | break; | |
241 | case FSR_RD_NEG: | |
242 | fesetround(FE_DOWNWARD); | |
243 | break; | |
244 | } | |
245 | } | |
e80cfcfc FB |
246 | |
247 | void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f) | |
248 | { | |
249 | int exptemp; | |
250 | ||
251 | *pmant = ldexp(frexp(f, &exptemp), 53); | |
252 | *pexp = exptemp; | |
253 | } | |
254 | ||
255 | double cpu_put_fp64(uint64_t mant, uint16_t exp) | |
256 | { | |
257 | return ldexp((double) mant, exp - 53); | |
258 | } | |
259 | ||
260 | void helper_debug() | |
261 | { | |
262 | env->exception_index = EXCP_DEBUG; | |
263 | cpu_loop_exit(); | |
264 | } | |
af7bf89b FB |
265 | |
266 | void do_wrpsr() | |
267 | { | |
268 | PUT_PSR(env, T0); | |
269 | } | |
270 | ||
271 | void do_rdpsr() | |
272 | { | |
273 | T0 = GET_PSR(env); | |
274 | } |