2 |
#include <fenv.h> |
#include <fenv.h> |
3 |
#include "exec.h" |
#include "exec.h" |
4 |
|
|
5 |
|
//#define DEBUG_MMU |
6 |
|
|
7 |
#ifdef USE_INT_TO_FLOAT_HELPERS |
#ifdef USE_INT_TO_FLOAT_HELPERS |
8 |
void do_fitos(void) |
void do_fitos(void) |
9 |
{ |
{ |
35 |
{ |
{ |
36 |
if (isnan(FT0) || isnan(FT1)) { |
if (isnan(FT0) || isnan(FT1)) { |
37 |
T0 = FSR_FCC1 | FSR_FCC0; |
T0 = FSR_FCC1 | FSR_FCC0; |
38 |
|
env->fsr &= ~(FSR_FCC1 | FSR_FCC0); |
39 |
|
env->fsr |= T0; |
40 |
|
if (env->fsr & FSR_NVM) { |
41 |
|
raise_exception(TT_FP_EXCP); |
42 |
|
} else { |
43 |
|
env->fsr |= FSR_NVA; |
44 |
|
} |
45 |
} else if (FT0 < FT1) { |
} else if (FT0 < FT1) { |
46 |
T0 = FSR_FCC0; |
T0 = FSR_FCC0; |
47 |
} else if (FT0 > FT1) { |
} else if (FT0 > FT1) { |
56 |
{ |
{ |
57 |
if (isnan(DT0) || isnan(DT1)) { |
if (isnan(DT0) || isnan(DT1)) { |
58 |
T0 = FSR_FCC1 | FSR_FCC0; |
T0 = FSR_FCC1 | FSR_FCC0; |
59 |
|
env->fsr &= ~(FSR_FCC1 | FSR_FCC0); |
60 |
|
env->fsr |= T0; |
61 |
|
if (env->fsr & FSR_NVM) { |
62 |
|
raise_exception(TT_FP_EXCP); |
63 |
|
} else { |
64 |
|
env->fsr |= FSR_NVA; |
65 |
|
} |
66 |
} else if (DT0 < DT1) { |
} else if (DT0 < DT1) { |
67 |
T0 = FSR_FCC0; |
T0 = FSR_FCC0; |
68 |
} else if (DT0 > DT1) { |
} else if (DT0 > DT1) { |
75 |
|
|
76 |
void helper_ld_asi(int asi, int size, int sign) |
void helper_ld_asi(int asi, int size, int sign) |
77 |
{ |
{ |
78 |
switch(asi) { |
uint32_t ret; |
79 |
|
|
80 |
|
switch (asi) { |
81 |
case 3: /* MMU probe */ |
case 3: /* MMU probe */ |
82 |
T1 = 0; |
{ |
83 |
return; |
int mmulev; |
84 |
|
|
85 |
|
mmulev = (T0 >> 8) & 15; |
86 |
|
if (mmulev > 4) |
87 |
|
ret = 0; |
88 |
|
else { |
89 |
|
ret = mmu_probe(T0, mmulev); |
90 |
|
//bswap32s(&ret); |
91 |
|
} |
92 |
|
#ifdef DEBUG_MMU |
93 |
|
printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret); |
94 |
|
#endif |
95 |
|
} |
96 |
|
break; |
97 |
case 4: /* read MMU regs */ |
case 4: /* read MMU regs */ |
98 |
{ |
{ |
99 |
int temp, reg = (T0 >> 8) & 0xf; |
int reg = (T0 >> 8) & 0xf; |
100 |
|
|
101 |
temp = env->mmuregs[reg]; |
ret = env->mmuregs[reg]; |
102 |
if (reg == 3 || reg == 4) /* Fault status, addr cleared on read*/ |
if (reg == 3 || reg == 4) /* Fault status, addr cleared on read*/ |
103 |
env->mmuregs[reg] = 0; |
env->mmuregs[4] = 0; |
|
T1 = temp; |
|
104 |
} |
} |
105 |
return; |
break; |
106 |
case 0x20 ... 0x2f: /* MMU passthrough */ |
case 0x20 ... 0x2f: /* MMU passthrough */ |
107 |
{ |
cpu_physical_memory_read(T0, (void *) &ret, size); |
108 |
int temp; |
if (size == 4) |
109 |
|
bswap32s(&ret); |
110 |
cpu_physical_memory_read(T0, (void *) &temp, size); |
else if (size == 2) |
111 |
bswap32s(&temp); |
bswap16s(&ret); |
112 |
T1 = temp; |
break; |
|
} |
|
|
return; |
|
113 |
default: |
default: |
114 |
T1 = 0; |
ret = 0; |
115 |
return; |
break; |
116 |
} |
} |
117 |
|
T1 = ret; |
118 |
} |
} |
119 |
|
|
120 |
void helper_st_asi(int asi, int size, int sign) |
void helper_st_asi(int asi, int size, int sign) |
121 |
{ |
{ |
122 |
switch(asi) { |
switch(asi) { |
123 |
case 3: /* MMU flush */ |
case 3: /* MMU flush */ |
124 |
return; |
{ |
125 |
|
int mmulev; |
126 |
|
|
127 |
|
mmulev = (T0 >> 8) & 15; |
128 |
|
switch (mmulev) { |
129 |
|
case 0: // flush page |
130 |
|
tlb_flush_page(cpu_single_env, T0 & 0xfffff000); |
131 |
|
break; |
132 |
|
case 1: // flush segment (256k) |
133 |
|
case 2: // flush region (16M) |
134 |
|
case 3: // flush context (4G) |
135 |
|
case 4: // flush entire |
136 |
|
tlb_flush(cpu_single_env, 1); |
137 |
|
break; |
138 |
|
default: |
139 |
|
break; |
140 |
|
} |
141 |
|
dump_mmu(); |
142 |
|
return; |
143 |
|
} |
144 |
case 4: /* write MMU regs */ |
case 4: /* write MMU regs */ |
145 |
{ |
{ |
146 |
int reg = (T0 >> 8) & 0xf; |
int reg = (T0 >> 8) & 0xf, oldreg; |
147 |
|
|
148 |
|
oldreg = env->mmuregs[reg]; |
149 |
if (reg == 0) { |
if (reg == 0) { |
150 |
env->mmuregs[reg] &= ~(MMU_E | MMU_NF); |
env->mmuregs[reg] &= ~(MMU_E | MMU_NF); |
151 |
env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF); |
env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF); |
152 |
} else |
} else |
153 |
env->mmuregs[reg] = T1; |
env->mmuregs[reg] = T1; |
154 |
|
if (oldreg != env->mmuregs[reg]) { |
155 |
|
#if 0 |
156 |
|
// XXX: Only if MMU mapping change, we may need to flush? |
157 |
|
tlb_flush(cpu_single_env, 1); |
158 |
|
cpu_loop_exit(); |
159 |
|
FORCE_RET(); |
160 |
|
#endif |
161 |
|
} |
162 |
|
dump_mmu(); |
163 |
return; |
return; |
164 |
} |
} |
165 |
|
case 0x17: /* Block copy, sta access */ |
166 |
|
{ |
167 |
|
// value (T1) = src |
168 |
|
// address (T0) = dst |
169 |
|
// copy 32 bytes |
170 |
|
int src = T1, dst = T0; |
171 |
|
uint8_t temp[32]; |
172 |
|
|
173 |
|
bswap32s(&src); |
174 |
|
|
175 |
|
cpu_physical_memory_read(src, (void *) &temp, 32); |
176 |
|
cpu_physical_memory_write(dst, (void *) &temp, 32); |
177 |
|
} |
178 |
|
return; |
179 |
|
case 0x1f: /* Block fill, stda access */ |
180 |
|
{ |
181 |
|
// value (T1, T2) |
182 |
|
// address (T0) = dst |
183 |
|
// fill 32 bytes |
184 |
|
int i, dst = T0; |
185 |
|
uint64_t val; |
186 |
|
|
187 |
|
val = (((uint64_t)T1) << 32) | T2; |
188 |
|
bswap64s(&val); |
189 |
|
|
190 |
|
for (i = 0; i < 32; i += 8, dst += 8) { |
191 |
|
cpu_physical_memory_write(dst, (void *) &val, 8); |
192 |
|
} |
193 |
|
} |
194 |
|
return; |
195 |
case 0x20 ... 0x2f: /* MMU passthrough */ |
case 0x20 ... 0x2f: /* MMU passthrough */ |
196 |
{ |
{ |
197 |
int temp = T1; |
int temp = T1; |
198 |
|
if (size == 4) |
199 |
bswap32s(&temp); |
bswap32s(&temp); |
200 |
|
else if (size == 2) |
201 |
|
bswap16s(&temp); |
202 |
|
|
203 |
cpu_physical_memory_write(T0, (void *) &temp, size); |
cpu_physical_memory_write(T0, (void *) &temp, size); |
204 |
} |
} |
205 |
return; |
return; |
208 |
} |
} |
209 |
} |
} |
210 |
|
|
|
#if 0 |
|
|
void do_ldd_raw(uint32_t addr) |
|
|
{ |
|
|
T1 = ldl_raw((void *) addr); |
|
|
T0 = ldl_raw((void *) (addr + 4)); |
|
|
} |
|
|
|
|
|
#if !defined(CONFIG_USER_ONLY) |
|
|
void do_ldd_user(uint32_t addr) |
|
|
{ |
|
|
T1 = ldl_user((void *) addr); |
|
|
T0 = ldl_user((void *) (addr + 4)); |
|
|
} |
|
|
void do_ldd_kernel(uint32_t addr) |
|
|
{ |
|
|
T1 = ldl_kernel((void *) addr); |
|
|
T0 = ldl_kernel((void *) (addr + 4)); |
|
|
} |
|
|
#endif |
|
|
#endif |
|
|
|
|
211 |
void helper_rett() |
void helper_rett() |
212 |
{ |
{ |
213 |
int cwp; |
int cwp; |
237 |
break; |
break; |
238 |
} |
} |
239 |
} |
} |
240 |
|
|
241 |
|
void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f) |
242 |
|
{ |
243 |
|
int exptemp; |
244 |
|
|
245 |
|
*pmant = ldexp(frexp(f, &exptemp), 53); |
246 |
|
*pexp = exptemp; |
247 |
|
} |
248 |
|
|
249 |
|
double cpu_put_fp64(uint64_t mant, uint16_t exp) |
250 |
|
{ |
251 |
|
return ldexp((double) mant, exp - 53); |
252 |
|
} |
253 |
|
|
254 |
|
void helper_debug() |
255 |
|
{ |
256 |
|
env->exception_index = EXCP_DEBUG; |
257 |
|
cpu_loop_exit(); |
258 |
|
} |