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) { | ... | ... |