Revision ec6338ba target-i386/helper2.c
b/target-i386/helper2.c | ||
---|---|---|
31 | 31 |
|
32 | 32 |
//#define DEBUG_MMU |
33 | 33 |
|
34 |
#ifdef USE_CODE_COPY |
|
35 |
#include <unistd.h> |
|
36 |
#include <asm/ldt.h> |
|
37 |
#include <linux/unistd.h> |
|
38 |
#include <linux/version.h> |
|
39 |
|
|
40 |
int modify_ldt(int func, void *ptr, unsigned long bytecount) |
|
41 |
{ |
|
42 |
return syscall(__NR_modify_ldt, func, ptr, bytecount); |
|
43 |
} |
|
44 |
|
|
45 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66) |
|
46 |
#define modify_ldt_ldt_s user_desc |
|
47 |
#endif |
|
48 |
#endif /* USE_CODE_COPY */ |
|
49 |
|
|
50 | 34 |
static struct x86_def_t *x86_cpu_def; |
51 | 35 |
typedef struct x86_def_t x86_def_t; |
52 | 36 |
static int cpu_x86_register (CPUX86State *env, const x86_def_t *def); |
... | ... | |
123 | 107 |
inited = 1; |
124 | 108 |
optimize_flags_init(); |
125 | 109 |
} |
126 |
#ifdef USE_CODE_COPY |
|
127 |
/* testing code for code copy case */ |
|
128 |
{ |
|
129 |
struct modify_ldt_ldt_s ldt; |
|
130 |
|
|
131 |
ldt.entry_number = 1; |
|
132 |
ldt.base_addr = (unsigned long)env; |
|
133 |
ldt.limit = (sizeof(CPUState) + 0xfff) >> 12; |
|
134 |
ldt.seg_32bit = 1; |
|
135 |
ldt.contents = MODIFY_LDT_CONTENTS_DATA; |
|
136 |
ldt.read_exec_only = 0; |
|
137 |
ldt.limit_in_pages = 1; |
|
138 |
ldt.seg_not_present = 0; |
|
139 |
ldt.useable = 1; |
|
140 |
modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ |
|
141 |
|
|
142 |
asm volatile ("movl %0, %%fs" : : "r" ((1 << 3) | 7)); |
|
143 |
} |
|
144 |
#endif |
|
145 | 110 |
cpu_x86_register(env, x86_cpu_def); |
146 | 111 |
cpu_reset(env); |
147 | 112 |
#ifdef USE_KQEMU |
... | ... | |
1186 | 1151 |
return paddr; |
1187 | 1152 |
} |
1188 | 1153 |
#endif /* !CONFIG_USER_ONLY */ |
1189 |
|
|
1190 |
#if defined(USE_CODE_COPY) |
|
1191 |
struct fpstate { |
|
1192 |
uint16_t fpuc; |
|
1193 |
uint16_t dummy1; |
|
1194 |
uint16_t fpus; |
|
1195 |
uint16_t dummy2; |
|
1196 |
uint16_t fptag; |
|
1197 |
uint16_t dummy3; |
|
1198 |
|
|
1199 |
uint32_t fpip; |
|
1200 |
uint32_t fpcs; |
|
1201 |
uint32_t fpoo; |
|
1202 |
uint32_t fpos; |
|
1203 |
uint8_t fpregs1[8 * 10]; |
|
1204 |
}; |
|
1205 |
|
|
1206 |
void restore_native_fp_state(CPUState *env) |
|
1207 |
{ |
|
1208 |
int fptag, i, j; |
|
1209 |
struct fpstate fp1, *fp = &fp1; |
|
1210 |
|
|
1211 |
fp->fpuc = env->fpuc; |
|
1212 |
fp->fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; |
|
1213 |
fptag = 0; |
|
1214 |
for (i=7; i>=0; i--) { |
|
1215 |
fptag <<= 2; |
|
1216 |
if (env->fptags[i]) { |
|
1217 |
fptag |= 3; |
|
1218 |
} else { |
|
1219 |
/* the FPU automatically computes it */ |
|
1220 |
} |
|
1221 |
} |
|
1222 |
fp->fptag = fptag; |
|
1223 |
j = env->fpstt; |
|
1224 |
for(i = 0;i < 8; i++) { |
|
1225 |
memcpy(&fp->fpregs1[i * 10], &env->fpregs[j].d, 10); |
|
1226 |
j = (j + 1) & 7; |
|
1227 |
} |
|
1228 |
asm volatile ("frstor %0" : "=m" (*fp)); |
|
1229 |
env->native_fp_regs = 1; |
|
1230 |
} |
|
1231 |
|
|
1232 |
void save_native_fp_state(CPUState *env) |
|
1233 |
{ |
|
1234 |
int fptag, i, j; |
|
1235 |
uint16_t fpuc; |
|
1236 |
struct fpstate fp1, *fp = &fp1; |
|
1237 |
|
|
1238 |
asm volatile ("fsave %0" : : "m" (*fp)); |
|
1239 |
env->fpuc = fp->fpuc; |
|
1240 |
env->fpstt = (fp->fpus >> 11) & 7; |
|
1241 |
env->fpus = fp->fpus & ~0x3800; |
|
1242 |
fptag = fp->fptag; |
|
1243 |
for(i = 0;i < 8; i++) { |
|
1244 |
env->fptags[i] = ((fptag & 3) == 3); |
|
1245 |
fptag >>= 2; |
|
1246 |
} |
|
1247 |
j = env->fpstt; |
|
1248 |
for(i = 0;i < 8; i++) { |
|
1249 |
memcpy(&env->fpregs[j].d, &fp->fpregs1[i * 10], 10); |
|
1250 |
j = (j + 1) & 7; |
|
1251 |
} |
|
1252 |
/* we must restore the default rounding state */ |
|
1253 |
/* XXX: we do not restore the exception state */ |
|
1254 |
fpuc = 0x037f | (env->fpuc & (3 << 10)); |
|
1255 |
asm volatile("fldcw %0" : : "m" (fpuc)); |
|
1256 |
env->native_fp_regs = 0; |
|
1257 |
} |
|
1258 |
#endif |
Also available in: Unified diff