Commit 04369ff2f525ea510b6ddeaa2e3ed6aedde8bbb4
1 parent
68decc7c
ppc port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@36 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
14 changed files
with
486 additions
and
35 deletions
Makefile
... | ... | @@ -90,7 +90,7 @@ i386.ld ppc.ld exec-i386.h exec-i386.c configure VERSION \ |
90 | 90 | tests/Makefile\ |
91 | 91 | tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\ |
92 | 92 | tests/test-i386-muldiv.h\ |
93 | -tests/test2.c tests/hello.c tests/sha1.c | |
93 | +tests/test2.c tests/hello.c tests/hello tests/sha1.c | |
94 | 94 | |
95 | 95 | FILE=gemu-$(VERSION) |
96 | 96 | ... | ... |
configure
... | ... | @@ -11,11 +11,11 @@ else |
11 | 11 | TMPDIR1="/tmp" |
12 | 12 | fi |
13 | 13 | |
14 | -TMPC="${TMPDIR1}/qemacs-conf-${RANDOM}-$$-${RANDOM}.c" | |
15 | -TMPO="${TMPDIR1}/qemacs-conf-${RANDOM}-$$-${RANDOM}.o" | |
16 | -TMPE="${TMPDIR1}/qemacs-conf-${RANDOM}-$$-${RANDOM}" | |
17 | -TMPS="${TMPDIR1}/qemacs-conf-${RANDOM}-$$-${RANDOM}.S" | |
18 | -TMPH="${TMPDIR1}/qemacs-conf-${RANDOM}-$$-${RANDOM}.h" | |
14 | +TMPC="${TMPDIR1}/gemu-conf-${RANDOM}-$$-${RANDOM}.c" | |
15 | +TMPO="${TMPDIR1}/gemu-conf-${RANDOM}-$$-${RANDOM}.o" | |
16 | +TMPE="${TMPDIR1}/gemu-conf-${RANDOM}-$$-${RANDOM}" | |
17 | +TMPS="${TMPDIR1}/gemu-conf-${RANDOM}-$$-${RANDOM}.S" | |
18 | +TMPH="${TMPDIR1}/gemu-conf-${RANDOM}-$$-${RANDOM}.h" | |
19 | 19 | |
20 | 20 | # default parameters |
21 | 21 | prefix="/usr/local" |
... | ... | @@ -144,12 +144,20 @@ fi |
144 | 144 | fi |
145 | 145 | |
146 | 146 | # check gcc version |
147 | +cat > $TMPC <<EOF | |
148 | +int main(void) { | |
149 | +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2) | |
150 | +return 0; | |
151 | +#else | |
152 | +#error gcc < 3.2 | |
153 | +#endif | |
154 | +} | |
155 | +EOF | |
156 | + | |
147 | 157 | gcc_major="2" |
148 | -gcc_version="$($cc -v 2>&1 | grep version | cut -d ' ' -f3-)" | |
149 | -case "$gcc_version" in | |
150 | -3.*) gcc_major="3"; | |
151 | -;; | |
152 | -esac | |
158 | +if $cc -o $TMPO $TMPC 2> /dev/null ; then | |
159 | + gcc_major="3" | |
160 | +fi | |
153 | 161 | |
154 | 162 | if test x"$1" = x"-h" -o x"$1" = x"--help" ; then |
155 | 163 | cat << EOF |
... | ... | @@ -201,9 +209,9 @@ if test "$cpu" = "x86" ; then |
201 | 209 | elif test "$cpu" = "armv4l" ; then |
202 | 210 | echo "ARCH=arm" >> config.mak |
203 | 211 | elif test "$cpu" = "powerpc" ; then |
204 | - echo "ARCH=ppc" > config.mak | |
212 | + echo "ARCH=ppc" >> config.mak | |
205 | 213 | elif test "$cpu" = "mips" ; then |
206 | - echo "ARCH=mips" > config.mak | |
214 | + echo "ARCH=mips" >> config.mak | |
207 | 215 | else |
208 | 216 | echo "Unsupported CPU" |
209 | 217 | exit 1 | ... | ... |
cpu-i386.h
... | ... | @@ -4,6 +4,7 @@ |
4 | 4 | #ifndef CPU_I386_H |
5 | 5 | #define CPU_I386_H |
6 | 6 | |
7 | +#include "config.h" | |
7 | 8 | #include <setjmp.h> |
8 | 9 | |
9 | 10 | #define R_EAX 0 |
... | ... | @@ -174,6 +175,7 @@ typedef struct CPUX86State { |
174 | 175 | int exception_index; |
175 | 176 | } CPUX86State; |
176 | 177 | |
178 | +/* all CPU memory access use these macros */ | |
177 | 179 | static inline int ldub(void *ptr) |
178 | 180 | { |
179 | 181 | return *(uint8_t *)ptr; |
... | ... | @@ -184,6 +186,134 @@ static inline int ldsb(void *ptr) |
184 | 186 | return *(int8_t *)ptr; |
185 | 187 | } |
186 | 188 | |
189 | +static inline void stb(void *ptr, int v) | |
190 | +{ | |
191 | + *(uint8_t *)ptr = v; | |
192 | +} | |
193 | + | |
194 | +#ifdef WORDS_BIGENDIAN | |
195 | + | |
196 | +/* conservative code for little endian unaligned accesses */ | |
197 | +static inline int lduw(void *ptr) | |
198 | +{ | |
199 | +#ifdef __powerpc__ | |
200 | + int val; | |
201 | + __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr)); | |
202 | + return val; | |
203 | +#else | |
204 | + uint8_t *p = ptr; | |
205 | + return p[0] | (p[1] << 8); | |
206 | +#endif | |
207 | +} | |
208 | + | |
209 | +static inline int ldsw(void *ptr) | |
210 | +{ | |
211 | +#ifdef __powerpc__ | |
212 | + int val; | |
213 | + __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr)); | |
214 | + return (int16_t)val; | |
215 | +#else | |
216 | + uint8_t *p = ptr; | |
217 | + return (int16_t)(p[0] | (p[1] << 8)); | |
218 | +#endif | |
219 | +} | |
220 | + | |
221 | +static inline int ldl(void *ptr) | |
222 | +{ | |
223 | +#ifdef __powerpc__ | |
224 | + int val; | |
225 | + __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr)); | |
226 | + return val; | |
227 | +#else | |
228 | + uint8_t *p = ptr; | |
229 | + return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); | |
230 | +#endif | |
231 | +} | |
232 | + | |
233 | +static inline uint64_t ldq(void *ptr) | |
234 | +{ | |
235 | + uint8_t *p = ptr; | |
236 | + uint32_t v1, v2; | |
237 | + v1 = ldl(p); | |
238 | + v2 = ldl(p + 4); | |
239 | + return v1 | ((uint64_t)v2 << 32); | |
240 | +} | |
241 | + | |
242 | +static inline void stw(void *ptr, int v) | |
243 | +{ | |
244 | +#ifdef __powerpc__ | |
245 | + __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr)); | |
246 | +#else | |
247 | + uint8_t *p = ptr; | |
248 | + p[0] = v; | |
249 | + p[1] = v >> 8; | |
250 | +#endif | |
251 | +} | |
252 | + | |
253 | +static inline void stl(void *ptr, int v) | |
254 | +{ | |
255 | +#ifdef __powerpc__ | |
256 | + __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr)); | |
257 | +#else | |
258 | + uint8_t *p = ptr; | |
259 | + p[0] = v; | |
260 | + p[1] = v >> 8; | |
261 | + p[2] = v >> 16; | |
262 | + p[3] = v >> 24; | |
263 | +#endif | |
264 | +} | |
265 | + | |
266 | +static inline void stq(void *ptr, uint64_t v) | |
267 | +{ | |
268 | + uint8_t *p = ptr; | |
269 | + stl(p, (uint32_t)v); | |
270 | + stl(p + 4, v >> 32); | |
271 | +} | |
272 | + | |
273 | +/* float access */ | |
274 | + | |
275 | +static inline float ldfl(void *ptr) | |
276 | +{ | |
277 | + union { | |
278 | + float f; | |
279 | + uint32_t i; | |
280 | + } u; | |
281 | + u.i = ldl(ptr); | |
282 | + return u.f; | |
283 | +} | |
284 | + | |
285 | +static inline double ldfq(void *ptr) | |
286 | +{ | |
287 | + union { | |
288 | + double d; | |
289 | + uint64_t i; | |
290 | + } u; | |
291 | + u.i = ldq(ptr); | |
292 | + return u.d; | |
293 | +} | |
294 | + | |
295 | +static inline void stfl(void *ptr, float v) | |
296 | +{ | |
297 | + union { | |
298 | + float f; | |
299 | + uint32_t i; | |
300 | + } u; | |
301 | + u.f = v; | |
302 | + stl(ptr, u.i); | |
303 | +} | |
304 | + | |
305 | +static inline void stfq(void *ptr, double v) | |
306 | +{ | |
307 | + union { | |
308 | + double d; | |
309 | + uint64_t i; | |
310 | + } u; | |
311 | + u.d = v; | |
312 | + stq(ptr, u.i); | |
313 | +} | |
314 | + | |
315 | +#else | |
316 | + | |
187 | 317 | static inline int lduw(void *ptr) |
188 | 318 | { |
189 | 319 | return *(uint16_t *)ptr; |
... | ... | @@ -204,11 +334,6 @@ static inline uint64_t ldq(void *ptr) |
204 | 334 | return *(uint64_t *)ptr; |
205 | 335 | } |
206 | 336 | |
207 | -static inline void stb(void *ptr, int v) | |
208 | -{ | |
209 | - *(uint8_t *)ptr = v; | |
210 | -} | |
211 | - | |
212 | 337 | static inline void stw(void *ptr, int v) |
213 | 338 | { |
214 | 339 | *(uint16_t *)ptr = v; |
... | ... | @@ -245,6 +370,7 @@ static inline void stfq(void *ptr, double v) |
245 | 370 | { |
246 | 371 | *(double *)ptr = v; |
247 | 372 | } |
373 | +#endif | |
248 | 374 | |
249 | 375 | #ifndef IN_OP_I386 |
250 | 376 | void cpu_x86_outb(int addr, int val); | ... | ... |
dis-asm.h
dyngen.c
... | ... | @@ -19,6 +19,7 @@ |
19 | 19 | */ |
20 | 20 | #include <stdlib.h> |
21 | 21 | #include <stdio.h> |
22 | +#include <string.h> | |
22 | 23 | #include <stdarg.h> |
23 | 24 | #include <inttypes.h> |
24 | 25 | #include <elf.h> |
... | ... | @@ -228,14 +229,10 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, |
228 | 229 | { |
229 | 230 | uint8_t *p; |
230 | 231 | p = (void *)(p_end - 4); |
231 | - /* find ret */ | |
232 | - while (p > p_start && get32((uint32_t *)p) != 0x4e800020) | |
233 | - p -= 4; | |
234 | - /* skip double ret */ | |
235 | - if (p > p_start && get32((uint32_t *)(p - 4)) == 0x4e800020) | |
236 | - p -= 4; | |
237 | 232 | if (p == p_start) |
238 | 233 | error("empty code for %s", name); |
234 | + if (get32((uint32_t *)p) != 0x4e800020) | |
235 | + error("blr expected at the end of %s", name); | |
239 | 236 | copy_size = p - p_start; |
240 | 237 | } |
241 | 238 | break; |
... | ... | @@ -361,6 +358,51 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, |
361 | 358 | } |
362 | 359 | } |
363 | 360 | break; |
361 | + case EM_PPC: | |
362 | + { | |
363 | + Elf32_Rela *rel; | |
364 | + char name[256]; | |
365 | + int type; | |
366 | + long addend; | |
367 | + for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | |
368 | + if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | |
369 | + sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | |
370 | + if (strstart(sym_name, "__op_param", &p)) { | |
371 | + snprintf(name, sizeof(name), "param%s", p); | |
372 | + } else { | |
373 | + snprintf(name, sizeof(name), "(long)(&%s)", sym_name); | |
374 | + } | |
375 | + type = ELF32_R_TYPE(rel->r_info); | |
376 | + addend = rel->r_addend; | |
377 | + switch(type) { | |
378 | + case R_PPC_ADDR32: | |
379 | + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %ld) = %s + %ld;\n", | |
380 | + rel->r_offset - offset, name, addend); | |
381 | + break; | |
382 | + case R_PPC_ADDR16_LO: | |
383 | + fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %ld) = (%s + %ld);\n", | |
384 | + rel->r_offset - offset, name, addend); | |
385 | + break; | |
386 | + case R_PPC_ADDR16_HI: | |
387 | + fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %ld) = (%s + %ld) >> 16;\n", | |
388 | + rel->r_offset - offset, name, addend); | |
389 | + break; | |
390 | + case R_PPC_ADDR16_HA: | |
391 | + fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %ld) = (%s + %ld + 0x8000) >> 16;\n", | |
392 | + rel->r_offset - offset, name, addend); | |
393 | + break; | |
394 | + case R_PPC_REL24: | |
395 | + /* warning: must be at 32 MB distancy */ | |
396 | + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %ld) = (*(uint32_t *)(gen_code_ptr + %ld) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %ld) + %ld) & 0x03fffffc);\n", | |
397 | + rel->r_offset - offset, rel->r_offset - offset, name, rel->r_offset - offset, addend); | |
398 | + break; | |
399 | + default: | |
400 | + error("unsupported powerpc relocation (%d)", type); | |
401 | + } | |
402 | + } | |
403 | + } | |
404 | + } | |
405 | + break; | |
364 | 406 | default: |
365 | 407 | error("unsupported CPU for relocations (%d)", e_machine); |
366 | 408 | } |
... | ... | @@ -569,6 +611,9 @@ fprintf(outfile, |
569 | 611 | case EM_386: |
570 | 612 | fprintf(outfile, "*gen_code_ptr++ = 0xc3; /* ret */\n"); |
571 | 613 | break; |
614 | + case EM_PPC: | |
615 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x4e800020; /* blr */\n"); | |
616 | + break; | |
572 | 617 | default: |
573 | 618 | error("no return generation for cpu '%s'", cpu_name); |
574 | 619 | } | ... | ... |
exec-i386.c
... | ... | @@ -171,6 +171,30 @@ int cpu_x86_exec(CPUX86State *env1) |
171 | 171 | { |
172 | 172 | int saved_T0, saved_T1, saved_A0; |
173 | 173 | CPUX86State *saved_env; |
174 | +#ifdef reg_EAX | |
175 | + int saved_EAX; | |
176 | +#endif | |
177 | +#ifdef reg_ECX | |
178 | + int saved_ECX; | |
179 | +#endif | |
180 | +#ifdef reg_EDX | |
181 | + int saved_EDX; | |
182 | +#endif | |
183 | +#ifdef reg_EBX | |
184 | + int saved_EBX; | |
185 | +#endif | |
186 | +#ifdef reg_ESP | |
187 | + int saved_ESP; | |
188 | +#endif | |
189 | +#ifdef reg_EBP | |
190 | + int saved_EBP; | |
191 | +#endif | |
192 | +#ifdef reg_ESI | |
193 | + int saved_ESI; | |
194 | +#endif | |
195 | +#ifdef reg_EDI | |
196 | + int saved_EDI; | |
197 | +#endif | |
174 | 198 | int code_gen_size, ret; |
175 | 199 | void (*gen_func)(void); |
176 | 200 | TranslationBlock *tb; |
... | ... | @@ -183,6 +207,38 @@ int cpu_x86_exec(CPUX86State *env1) |
183 | 207 | saved_A0 = A0; |
184 | 208 | saved_env = env; |
185 | 209 | env = env1; |
210 | +#ifdef reg_EAX | |
211 | + saved_EAX = EAX; | |
212 | + EAX = env->regs[R_EAX]; | |
213 | +#endif | |
214 | +#ifdef reg_ECX | |
215 | + saved_ECX = ECX; | |
216 | + ECX = env->regs[R_ECX]; | |
217 | +#endif | |
218 | +#ifdef reg_EDX | |
219 | + saved_EDX = EDX; | |
220 | + EDX = env->regs[R_EDX]; | |
221 | +#endif | |
222 | +#ifdef reg_EBX | |
223 | + saved_EBX = EBX; | |
224 | + EBX = env->regs[R_EBX]; | |
225 | +#endif | |
226 | +#ifdef reg_ESP | |
227 | + saved_ESP = ESP; | |
228 | + ESP = env->regs[R_ESP]; | |
229 | +#endif | |
230 | +#ifdef reg_EBP | |
231 | + saved_EBP = EBP; | |
232 | + EBP = env->regs[R_EBP]; | |
233 | +#endif | |
234 | +#ifdef reg_ESI | |
235 | + saved_ESI = ESI; | |
236 | + ESI = env->regs[R_ESI]; | |
237 | +#endif | |
238 | +#ifdef reg_EDI | |
239 | + saved_EDI = EDI; | |
240 | + EDI = env->regs[R_EDI]; | |
241 | +#endif | |
186 | 242 | |
187 | 243 | /* prepare setjmp context for exception handling */ |
188 | 244 | if (setjmp(env->jmp_env) == 0) { |
... | ... | @@ -217,6 +273,30 @@ int cpu_x86_exec(CPUX86State *env1) |
217 | 273 | ret = env->exception_index; |
218 | 274 | |
219 | 275 | /* restore global registers */ |
276 | +#ifdef reg_EAX | |
277 | + EAX = saved_EAX; | |
278 | +#endif | |
279 | +#ifdef reg_ECX | |
280 | + ECX = saved_ECX; | |
281 | +#endif | |
282 | +#ifdef reg_EDX | |
283 | + EDX = saved_EDX; | |
284 | +#endif | |
285 | +#ifdef reg_EBX | |
286 | + EBX = saved_EBX; | |
287 | +#endif | |
288 | +#ifdef reg_ESP | |
289 | + ESP = saved_ESP; | |
290 | +#endif | |
291 | +#ifdef reg_EBP | |
292 | + EBP = saved_EBP; | |
293 | +#endif | |
294 | +#ifdef reg_ESI | |
295 | + ESI = saved_ESI; | |
296 | +#endif | |
297 | +#ifdef reg_EDI | |
298 | + EDI = saved_EDI; | |
299 | +#endif | |
220 | 300 | T0 = saved_T0; |
221 | 301 | T1 = saved_T1; |
222 | 302 | A0 = saved_A0; | ... | ... |
exec-i386.h
... | ... | @@ -36,10 +36,27 @@ register unsigned int A0 asm("edi"); |
36 | 36 | register struct CPUX86State *env asm("ebp"); |
37 | 37 | #endif |
38 | 38 | #ifdef __powerpc__ |
39 | +register unsigned int EAX asm("r16"); | |
40 | +register unsigned int ECX asm("r17"); | |
41 | +register unsigned int EDX asm("r18"); | |
42 | +register unsigned int EBX asm("r19"); | |
43 | +register unsigned int ESP asm("r20"); | |
44 | +register unsigned int EBP asm("r21"); | |
45 | +register unsigned int ESI asm("r22"); | |
46 | +register unsigned int EDI asm("r23"); | |
39 | 47 | register unsigned int T0 asm("r24"); |
40 | 48 | register unsigned int T1 asm("r25"); |
41 | 49 | register unsigned int A0 asm("r26"); |
42 | 50 | register struct CPUX86State *env asm("r27"); |
51 | +#define USE_INT_TO_FLOAT_HELPERS | |
52 | +#define reg_EAX | |
53 | +#define reg_ECX | |
54 | +#define reg_EDX | |
55 | +#define reg_EBX | |
56 | +#define reg_ESP | |
57 | +#define reg_EBP | |
58 | +#define reg_ESI | |
59 | +#define reg_EDI | |
43 | 60 | #endif |
44 | 61 | #ifdef __arm__ |
45 | 62 | register unsigned int T0 asm("r4"); |
... | ... | @@ -70,14 +87,30 @@ register struct CPUX86State *env asm("l3"); |
70 | 87 | #define xglue(x, y) x ## y |
71 | 88 | #define glue(x, y) xglue(x, y) |
72 | 89 | |
90 | +#ifndef reg_EAX | |
73 | 91 | #define EAX (env->regs[R_EAX]) |
92 | +#endif | |
93 | +#ifndef reg_ECX | |
74 | 94 | #define ECX (env->regs[R_ECX]) |
95 | +#endif | |
96 | +#ifndef reg_EDX | |
75 | 97 | #define EDX (env->regs[R_EDX]) |
98 | +#endif | |
99 | +#ifndef reg_EBX | |
76 | 100 | #define EBX (env->regs[R_EBX]) |
101 | +#endif | |
102 | +#ifndef reg_ESP | |
77 | 103 | #define ESP (env->regs[R_ESP]) |
104 | +#endif | |
105 | +#ifndef reg_EBP | |
78 | 106 | #define EBP (env->regs[R_EBP]) |
107 | +#endif | |
108 | +#ifndef reg_ESI | |
79 | 109 | #define ESI (env->regs[R_ESI]) |
110 | +#endif | |
111 | +#ifndef reg_EDI | |
80 | 112 | #define EDI (env->regs[R_EDI]) |
113 | +#endif | |
81 | 114 | #define PC (env->pc) |
82 | 115 | #define DF (env->df) |
83 | 116 | ... | ... |
linux-user/main.c
linux-user/syscall.c
... | ... | @@ -20,6 +20,7 @@ |
20 | 20 | #include <stdlib.h> |
21 | 21 | #include <stdio.h> |
22 | 22 | #include <stdarg.h> |
23 | +#include <string.h> | |
23 | 24 | #include <elf.h> |
24 | 25 | #include <endian.h> |
25 | 26 | #include <errno.h> |
... | ... | @@ -42,6 +43,9 @@ |
42 | 43 | #define termios host_termios |
43 | 44 | #define winsize host_winsize |
44 | 45 | #define termio host_termio |
46 | +#define sgttyb host_sgttyb /* same as target */ | |
47 | +#define tchars host_tchars /* same as target */ | |
48 | +#define ltchars host_ltchars /* same as target */ | |
45 | 49 | |
46 | 50 | #include <linux/termios.h> |
47 | 51 | #include <linux/unistd.h> |
... | ... | @@ -904,7 +908,8 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
904 | 908 | case TARGET_NR_ftime: |
905 | 909 | goto unimplemented; |
906 | 910 | case TARGET_NR_sync: |
907 | - ret = get_errno(sync()); | |
911 | + sync(); | |
912 | + ret = 0; | |
908 | 913 | break; |
909 | 914 | case TARGET_NR_kill: |
910 | 915 | ret = get_errno(kill(arg1, arg2)); | ... | ... |
op-i386.c
... | ... | @@ -123,6 +123,32 @@ static inline int lshift(int x, int n) |
123 | 123 | /* NOTE: not static to force relocation generation by GCC */ |
124 | 124 | void raise_exception(int exception_index) |
125 | 125 | { |
126 | + /* NOTE: the register at this point must be saved by hand because | |
127 | + longjmp restore them */ | |
128 | +#ifdef reg_EAX | |
129 | + env->regs[R_EAX] = EAX; | |
130 | +#endif | |
131 | +#ifdef reg_ECX | |
132 | + env->regs[R_ECX] = ECX; | |
133 | +#endif | |
134 | +#ifdef reg_EDX | |
135 | + env->regs[R_EDX] = EDX; | |
136 | +#endif | |
137 | +#ifdef reg_EBX | |
138 | + env->regs[R_EBX] = EBX; | |
139 | +#endif | |
140 | +#ifdef reg_ESP | |
141 | + env->regs[R_ESP] = ESP; | |
142 | +#endif | |
143 | +#ifdef reg_EBP | |
144 | + env->regs[R_EBP] = EBP; | |
145 | +#endif | |
146 | +#ifdef reg_ESI | |
147 | + env->regs[R_ESI] = ESI; | |
148 | +#endif | |
149 | +#ifdef reg_EDI | |
150 | + env->regs[R_EDI] = EDI; | |
151 | +#endif | |
126 | 152 | env->exception_index = exception_index; |
127 | 153 | longjmp(env->jmp_env, 1); |
128 | 154 | } |
... | ... | @@ -1341,6 +1367,41 @@ void OPPROTO op_fldl_FT0_A0(void) |
1341 | 1367 | FT0 = ldfq((void *)A0); |
1342 | 1368 | } |
1343 | 1369 | |
1370 | +/* helpers are needed to avoid static constant reference. XXX: find a better way */ | |
1371 | +#ifdef USE_INT_TO_FLOAT_HELPERS | |
1372 | + | |
1373 | +void helper_fild_FT0_A0(void) | |
1374 | +{ | |
1375 | + FT0 = (CPU86_LDouble)ldsw((void *)A0); | |
1376 | +} | |
1377 | + | |
1378 | +void helper_fildl_FT0_A0(void) | |
1379 | +{ | |
1380 | + FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0)); | |
1381 | +} | |
1382 | + | |
1383 | +void helper_fildll_FT0_A0(void) | |
1384 | +{ | |
1385 | + FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0)); | |
1386 | +} | |
1387 | + | |
1388 | +void OPPROTO op_fild_FT0_A0(void) | |
1389 | +{ | |
1390 | + helper_fild_FT0_A0(); | |
1391 | +} | |
1392 | + | |
1393 | +void OPPROTO op_fildl_FT0_A0(void) | |
1394 | +{ | |
1395 | + helper_fildl_FT0_A0(); | |
1396 | +} | |
1397 | + | |
1398 | +void OPPROTO op_fildll_FT0_A0(void) | |
1399 | +{ | |
1400 | + helper_fildll_FT0_A0(); | |
1401 | +} | |
1402 | + | |
1403 | +#else | |
1404 | + | |
1344 | 1405 | void OPPROTO op_fild_FT0_A0(void) |
1345 | 1406 | { |
1346 | 1407 | FT0 = (CPU86_LDouble)ldsw((void *)A0); |
... | ... | @@ -1355,6 +1416,7 @@ void OPPROTO op_fildll_FT0_A0(void) |
1355 | 1416 | { |
1356 | 1417 | FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0)); |
1357 | 1418 | } |
1419 | +#endif | |
1358 | 1420 | |
1359 | 1421 | /* fp load ST0 */ |
1360 | 1422 | |
... | ... | @@ -1393,6 +1455,41 @@ void OPPROTO op_fldt_ST0_A0(void) |
1393 | 1455 | } |
1394 | 1456 | #endif |
1395 | 1457 | |
1458 | +/* helpers are needed to avoid static constant reference. XXX: find a better way */ | |
1459 | +#ifdef USE_INT_TO_FLOAT_HELPERS | |
1460 | + | |
1461 | +void helper_fild_ST0_A0(void) | |
1462 | +{ | |
1463 | + ST0 = (CPU86_LDouble)ldsw((void *)A0); | |
1464 | +} | |
1465 | + | |
1466 | +void helper_fildl_ST0_A0(void) | |
1467 | +{ | |
1468 | + ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0)); | |
1469 | +} | |
1470 | + | |
1471 | +void helper_fildll_ST0_A0(void) | |
1472 | +{ | |
1473 | + ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0)); | |
1474 | +} | |
1475 | + | |
1476 | +void OPPROTO op_fild_ST0_A0(void) | |
1477 | +{ | |
1478 | + helper_fild_ST0_A0(); | |
1479 | +} | |
1480 | + | |
1481 | +void OPPROTO op_fildl_ST0_A0(void) | |
1482 | +{ | |
1483 | + helper_fildl_ST0_A0(); | |
1484 | +} | |
1485 | + | |
1486 | +void OPPROTO op_fildll_ST0_A0(void) | |
1487 | +{ | |
1488 | + helper_fildll_ST0_A0(); | |
1489 | +} | |
1490 | + | |
1491 | +#else | |
1492 | + | |
1396 | 1493 | void OPPROTO op_fild_ST0_A0(void) |
1397 | 1494 | { |
1398 | 1495 | ST0 = (CPU86_LDouble)ldsw((void *)A0); |
... | ... | @@ -1408,6 +1505,8 @@ void OPPROTO op_fildll_ST0_A0(void) |
1408 | 1505 | ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0)); |
1409 | 1506 | } |
1410 | 1507 | |
1508 | +#endif | |
1509 | + | |
1411 | 1510 | /* fp store */ |
1412 | 1511 | |
1413 | 1512 | void OPPROTO op_fsts_ST0_A0(void) | ... | ... |
ops_template.h
... | ... | @@ -809,6 +809,7 @@ void OPPROTO glue(op_rep_movs, SUFFIX)(void) |
809 | 809 | EDI += inc; |
810 | 810 | ECX--; |
811 | 811 | } |
812 | + FORCE_RET(); | |
812 | 813 | } |
813 | 814 | |
814 | 815 | void OPPROTO glue(op_stos, SUFFIX)(void) |
... | ... | @@ -826,6 +827,7 @@ void OPPROTO glue(op_rep_stos, SUFFIX)(void) |
826 | 827 | EDI += inc; |
827 | 828 | ECX--; |
828 | 829 | } |
830 | + FORCE_RET(); | |
829 | 831 | } |
830 | 832 | |
831 | 833 | void OPPROTO glue(op_lods, SUFFIX)(void) |
... | ... | @@ -859,6 +861,7 @@ void OPPROTO glue(op_rep_lods, SUFFIX)(void) |
859 | 861 | ESI += inc; |
860 | 862 | ECX--; |
861 | 863 | } |
864 | + FORCE_RET(); | |
862 | 865 | } |
863 | 866 | |
864 | 867 | void OPPROTO glue(op_scas, SUFFIX)(void) |
... | ... | @@ -890,6 +893,7 @@ void OPPROTO glue(op_repz_scas, SUFFIX)(void) |
890 | 893 | CC_DST = v1 - v2; |
891 | 894 | CC_OP = CC_OP_SUBB + SHIFT; |
892 | 895 | } |
896 | + FORCE_RET(); | |
893 | 897 | } |
894 | 898 | |
895 | 899 | void OPPROTO glue(op_repnz_scas, SUFFIX)(void) |
... | ... | @@ -911,6 +915,7 @@ void OPPROTO glue(op_repnz_scas, SUFFIX)(void) |
911 | 915 | CC_DST = v1 - v2; |
912 | 916 | CC_OP = CC_OP_SUBB + SHIFT; |
913 | 917 | } |
918 | + FORCE_RET(); | |
914 | 919 | } |
915 | 920 | |
916 | 921 | void OPPROTO glue(op_cmps, SUFFIX)(void) |
... | ... | @@ -942,6 +947,7 @@ void OPPROTO glue(op_repz_cmps, SUFFIX)(void) |
942 | 947 | CC_DST = v1 - v2; |
943 | 948 | CC_OP = CC_OP_SUBB + SHIFT; |
944 | 949 | } |
950 | + FORCE_RET(); | |
945 | 951 | } |
946 | 952 | |
947 | 953 | void OPPROTO glue(op_repnz_cmps, SUFFIX)(void) |
... | ... | @@ -962,6 +968,7 @@ void OPPROTO glue(op_repnz_cmps, SUFFIX)(void) |
962 | 968 | CC_DST = v1 - v2; |
963 | 969 | CC_OP = CC_OP_SUBB + SHIFT; |
964 | 970 | } |
971 | + FORCE_RET(); | |
965 | 972 | } |
966 | 973 | |
967 | 974 | /* port I/O */ |
... | ... | @@ -986,6 +993,7 @@ void OPPROTO glue(op_rep_outs, SUFFIX)(void) |
986 | 993 | ESI += inc; |
987 | 994 | ECX--; |
988 | 995 | } |
996 | + FORCE_RET(); | |
989 | 997 | } |
990 | 998 | |
991 | 999 | void OPPROTO glue(op_ins, SUFFIX)(void) |
... | ... | @@ -1008,6 +1016,7 @@ void OPPROTO glue(op_rep_ins, SUFFIX)(void) |
1008 | 1016 | EDI += (DF << SHIFT); |
1009 | 1017 | ECX--; |
1010 | 1018 | } |
1019 | + FORCE_RET(); | |
1011 | 1020 | } |
1012 | 1021 | |
1013 | 1022 | void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void) | ... | ... |
tests/Makefile
... | ... | @@ -4,8 +4,9 @@ CFLAGS=-Wall -O2 -g |
4 | 4 | LDFLAGS= |
5 | 5 | |
6 | 6 | ifeq ($(ARCH),i386) |
7 | -TESTS=hello test2 sha1 test-i386 | |
7 | +TESTS=test2 sha1-i386 test-i386 | |
8 | 8 | endif |
9 | +TESTS+=sha1 | |
9 | 10 | |
10 | 11 | GEMU=../gemu |
11 | 12 | |
... | ... | @@ -13,26 +14,32 @@ all: $(TESTS) |
13 | 14 | |
14 | 15 | hello: hello.c |
15 | 16 | $(CC) -nostdlib $(CFLAGS) -static $(LDFLAGS) -o $@ $< |
17 | + strip hello | |
16 | 18 | |
17 | 19 | test2: test2.c |
18 | 20 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< |
19 | 21 | |
20 | -# i386 emulation test (dump various opcodes) */ | |
22 | +# i386 emulation test (test various opcodes) */ | |
21 | 23 | test-i386: test-i386.c test-i386.h test-i386-shift.h test-i386-muldiv.h |
22 | 24 | $(CC) $(CFLAGS) $(LDFLAGS) -static -o $@ $< -lm |
23 | 25 | |
24 | 26 | test: test-i386 |
27 | +ifeq ($(ARCH),i386) | |
25 | 28 | ./test-i386 > test-i386.ref |
29 | +endif | |
26 | 30 | $(GEMU) test-i386 > test-i386.out |
27 | 31 | @if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi |
28 | 32 | |
29 | 33 | # speed test |
30 | -sha1: sha1.c | |
34 | +sha1-i386: sha1.c | |
31 | 35 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< |
32 | 36 | |
33 | -speed: sha1 | |
37 | +sha1: sha1.c | |
38 | + $(HOST_CC) $(CFLAGS) $(LDFLAGS) -o $@ $< | |
39 | + | |
40 | +speed: sha1 sha1-i386 | |
34 | 41 | time ./sha1 |
35 | - time $(GEMU) sha1 | |
42 | + time $(GEMU) ./sha1-i386 | |
36 | 43 | |
37 | 44 | clean: |
38 | 45 | rm -f *~ *.o $(TESTS) | ... | ... |
tests/test-i386.c
... | ... | @@ -653,7 +653,7 @@ void test_segs(void) |
653 | 653 | { |
654 | 654 | struct modify_ldt_ldt_s ldt; |
655 | 655 | long long ldt_table[3]; |
656 | - int i, res, res2; | |
656 | + int res, res2; | |
657 | 657 | char tmp; |
658 | 658 | |
659 | 659 | ldt.entry_number = 1; |
... | ... | @@ -679,9 +679,13 @@ void test_segs(void) |
679 | 679 | modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ |
680 | 680 | |
681 | 681 | modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */ |
682 | - for(i=0;i<3;i++) | |
683 | - printf("%d: %016Lx\n", i, ldt_table[i]); | |
684 | - | |
682 | +#if 0 | |
683 | + { | |
684 | + int i; | |
685 | + for(i=0;i<3;i++) | |
686 | + printf("%d: %016Lx\n", i, ldt_table[i]); | |
687 | + } | |
688 | +#endif | |
685 | 689 | /* do some tests with fs or gs */ |
686 | 690 | asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1))); |
687 | 691 | asm volatile ("movl %0, %%gs" : : "r" (MK_SEL(2))); | ... | ... |
translate-i386.c
... | ... | @@ -38,10 +38,40 @@ |
38 | 38 | #define offsetof(type, field) ((size_t) &((type *)0)->field) |
39 | 39 | #endif |
40 | 40 | |
41 | +/* XXX: move that elsewhere */ | |
41 | 42 | static uint16_t *gen_opc_ptr; |
42 | 43 | static uint32_t *gen_opparam_ptr; |
43 | 44 | int __op_param1, __op_param2, __op_param3; |
44 | 45 | |
46 | +#ifdef __i386__ | |
47 | +static inline void flush_icache_range(unsigned long start, unsigned long stop) | |
48 | +{ | |
49 | +} | |
50 | +#endif | |
51 | + | |
52 | +#ifdef __powerpc__ | |
53 | + | |
54 | +#define MIN_CACHE_LINE_SIZE 8 /* conservative value */ | |
55 | + | |
56 | +static void inline flush_icache_range(unsigned long start, unsigned long stop) | |
57 | +{ | |
58 | + unsigned long p; | |
59 | + | |
60 | + p = start & ~(MIN_CACHE_LINE_SIZE - 1); | |
61 | + stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1); | |
62 | + | |
63 | + for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { | |
64 | + asm ("dcbst 0,%0;" : : "r"(p) : "memory"); | |
65 | + } | |
66 | + asm ("sync"); | |
67 | + for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { | |
68 | + asm ("icbi 0,%0; sync;" : : "r"(p) : "memory"); | |
69 | + } | |
70 | + asm ("sync"); | |
71 | + asm ("isync"); | |
72 | +} | |
73 | +#endif | |
74 | + | |
45 | 75 | extern FILE *logfile; |
46 | 76 | extern int loglevel; |
47 | 77 | |
... | ... | @@ -3179,6 +3209,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, |
3179 | 3209 | DisasContext dc1, *dc = &dc1; |
3180 | 3210 | uint8_t *pc_ptr; |
3181 | 3211 | uint16_t *gen_opc_end; |
3212 | + int gen_code_size; | |
3182 | 3213 | long ret; |
3183 | 3214 | #ifdef DEBUG_DISAS |
3184 | 3215 | struct disassemble_info disasm_info; |
... | ... | @@ -3264,7 +3295,9 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, |
3264 | 3295 | #endif |
3265 | 3296 | |
3266 | 3297 | /* generate machine code */ |
3267 | - *gen_code_size_ptr = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf); | |
3298 | + gen_code_size = dyngen_code(gen_code_buf, gen_opc_buf, gen_opparam_buf); | |
3299 | + flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size)); | |
3300 | + *gen_code_size_ptr = gen_code_size; | |
3268 | 3301 | |
3269 | 3302 | #ifdef DEBUG_DISAS |
3270 | 3303 | if (loglevel) { | ... | ... |