Commit ae2285314189c0ea32fc73d38c1e9b8051d213ab
1 parent
d418c81e
Sparc update (David S. Miller)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@161 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
187 additions
and
78 deletions
Makefile
@@ -29,6 +29,18 @@ OP_CFLAGS=$(CFLAGS) | @@ -29,6 +29,18 @@ OP_CFLAGS=$(CFLAGS) | ||
29 | LDFLAGS+=-Wl,-T,s390.ld | 29 | LDFLAGS+=-Wl,-T,s390.ld |
30 | endif | 30 | endif |
31 | 31 | ||
32 | +ifeq ($(ARCH),sparc) | ||
33 | +CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 | ||
34 | +LDFLAGS+=-m32 | ||
35 | +OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 | ||
36 | +endif | ||
37 | + | ||
38 | +ifeq ($(ARCH),sparc64) | ||
39 | +CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 | ||
40 | +LDFLAGS+=-m64 | ||
41 | +OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 | ||
42 | +endif | ||
43 | + | ||
32 | ifeq ($(ARCH),alpha) | 44 | ifeq ($(ARCH),alpha) |
33 | # -msmall-data is not used because we want two-instruction relocations | 45 | # -msmall-data is not used because we want two-instruction relocations |
34 | # for the constant constructions | 46 | # for the constant constructions |
configure
@@ -47,6 +47,12 @@ case "$cpu" in | @@ -47,6 +47,12 @@ case "$cpu" in | ||
47 | s390) | 47 | s390) |
48 | cpu="s390" | 48 | cpu="s390" |
49 | ;; | 49 | ;; |
50 | + sparc) | ||
51 | + cpu="sparc" | ||
52 | + ;; | ||
53 | + sparc64) | ||
54 | + cpu="sparc64" | ||
55 | + ;; | ||
50 | ia64) | 56 | ia64) |
51 | cpu="ia64" | 57 | cpu="ia64" |
52 | ;; | 58 | ;; |
@@ -131,7 +137,7 @@ fi | @@ -131,7 +137,7 @@ fi | ||
131 | else | 137 | else |
132 | 138 | ||
133 | # if cross compiling, cannot launch a program, so make a static guess | 139 | # if cross compiling, cannot launch a program, so make a static guess |
134 | -if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" ; then | 140 | +if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64"; then |
135 | bigendian="yes" | 141 | bigendian="yes" |
136 | fi | 142 | fi |
137 | 143 | ||
@@ -217,6 +223,12 @@ elif test "$cpu" = "s390" ; then | @@ -217,6 +223,12 @@ elif test "$cpu" = "s390" ; then | ||
217 | elif test "$cpu" = "alpha" ; then | 223 | elif test "$cpu" = "alpha" ; then |
218 | echo "ARCH=alpha" >> config.mak | 224 | echo "ARCH=alpha" >> config.mak |
219 | echo "#define HOST_ALPHA 1" >> $TMPH | 225 | echo "#define HOST_ALPHA 1" >> $TMPH |
226 | +elif test "$cpu" = "sparc" ; then | ||
227 | + echo "ARCH=sparc" >> config.mak | ||
228 | + echo "#define HOST_SPARC 1" >> $TMPH | ||
229 | +elif test "$cpu" = "sparc64" ; then | ||
230 | + echo "ARCH=sparc64" >> config.mak | ||
231 | + echo "#define HOST_SPARC64 1" >> $TMPH | ||
220 | elif test "$cpu" = "ia64" ; then | 232 | elif test "$cpu" = "ia64" ; then |
221 | echo "ARCH=ia64" >> config.mak | 233 | echo "ARCH=ia64" >> config.mak |
222 | echo "#define HOST_IA64 1" >> $TMPH | 234 | echo "#define HOST_IA64 1" >> $TMPH |
dyngen.c
@@ -274,14 +274,20 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -274,14 +274,20 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
274 | { | 274 | { |
275 | int copy_size = 0; | 275 | int copy_size = 0; |
276 | uint8_t *p_start, *p_end; | 276 | uint8_t *p_start, *p_end; |
277 | + host_ulong start_offset; | ||
277 | int nb_args, i, n; | 278 | int nb_args, i, n; |
278 | uint8_t args_present[MAX_ARGS]; | 279 | uint8_t args_present[MAX_ARGS]; |
279 | const char *sym_name, *p; | 280 | const char *sym_name, *p; |
280 | ELF_RELOC *rel; | 281 | ELF_RELOC *rel; |
281 | 282 | ||
282 | - /* compute exact size excluding return instruction */ | 283 | + /* Compute exact size excluding prologue and epilogue instructions. |
284 | + * Increment start_offset to skip epilogue instructions, then compute | ||
285 | + * copy_size the indicate the size of the remaining instructions (in | ||
286 | + * bytes). | ||
287 | + */ | ||
283 | p_start = text + offset; | 288 | p_start = text + offset; |
284 | p_end = p_start + size; | 289 | p_end = p_start + size; |
290 | + start_offset = offset; | ||
285 | switch(ELF_ARCH) { | 291 | switch(ELF_ARCH) { |
286 | case EM_386: | 292 | case EM_386: |
287 | { | 293 | { |
@@ -343,41 +349,63 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -343,41 +349,63 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
343 | case EM_SPARC: | 349 | case EM_SPARC: |
344 | case EM_SPARC32PLUS: | 350 | case EM_SPARC32PLUS: |
345 | { | 351 | { |
352 | + uint32_t start_insn, end_insn1, end_insn2, skip_insn; | ||
346 | uint8_t *p; | 353 | uint8_t *p; |
347 | p = (void *)(p_end - 8); | 354 | p = (void *)(p_end - 8); |
348 | if (p <= p_start) | 355 | if (p <= p_start) |
349 | error("empty code for %s", name); | 356 | error("empty code for %s", name); |
350 | - if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf98) | ||
351 | - error("save %%sp,-104,%%sp expected at the start of %s " | ||
352 | - "found [%08x]", | ||
353 | - name, get32((uint32_t *)(p_start + 0x0))); | ||
354 | - if (get32((uint32_t *)(p + 0x0)) != 0x81c7e008 || | ||
355 | - get32((uint32_t *)(p + 0x4)) != 0x81e80000) | ||
356 | - error("ret; restore; expected at the end of %s found [%08x:%08x]", | ||
357 | - name, | ||
358 | - get32((uint32_t *)(p + 0x0)), | ||
359 | - get32((uint32_t *)(p + 0x4))); | 357 | + start_insn = get32((uint32_t *)(p_start + 0x0)); |
358 | + end_insn1 = get32((uint32_t *)(p + 0x0)); | ||
359 | + end_insn2 = get32((uint32_t *)(p + 0x4)); | ||
360 | + if ((start_insn & ~0x1fff) == 0x9de3a000) { | ||
361 | + p_start += 0x4; | ||
362 | + start_offset += 0x4; | ||
363 | + if ((int)(start_insn | ~0x1fff) < -128) | ||
364 | + error("Found bogus save at the start of %s", name); | ||
365 | + if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000) | ||
366 | + error("ret; restore; not found at end of %s", name); | ||
367 | + } else { | ||
368 | + error("No save at the beginning of %s", name); | ||
369 | + } | ||
370 | + | ||
371 | + /* Skip a preceeding nop, if present. */ | ||
372 | + if (p > p_start) { | ||
373 | + skip_insn = get32((uint32_t *)(p - 0x4)); | ||
374 | + if (skip_insn == 0x01000000) | ||
375 | + p -= 4; | ||
376 | + } | ||
360 | 377 | ||
361 | copy_size = p - p_start; | 378 | copy_size = p - p_start; |
362 | } | 379 | } |
363 | break; | 380 | break; |
364 | case EM_SPARCV9: | 381 | case EM_SPARCV9: |
365 | { | 382 | { |
383 | + uint32_t start_insn, end_insn1, end_insn2, skip_insn; | ||
366 | uint8_t *p; | 384 | uint8_t *p; |
367 | p = (void *)(p_end - 8); | 385 | p = (void *)(p_end - 8); |
368 | if (p <= p_start) | 386 | if (p <= p_start) |
369 | error("empty code for %s", name); | 387 | error("empty code for %s", name); |
370 | - if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf40) | ||
371 | - error("save %%sp,-192,%%sp expected at the start of %s " | ||
372 | - "found [%08x]", | ||
373 | - name, get32((uint32_t *)(p_start + 0x0))); | ||
374 | - if (get32((uint32_t *)(p + 0x0)) != 0x81cfe008 || | ||
375 | - get32((uint32_t *)(p + 0x4)) != 0x01000000) | ||
376 | - error("rett %%i7+8; nop; expected at the end of %s " | ||
377 | - "found [%08x:%08x]", | ||
378 | - name, | ||
379 | - get32((uint32_t *)(p + 0x0)), | ||
380 | - get32((uint32_t *)(p + 0x4))); | 388 | + start_insn = get32((uint32_t *)(p_start + 0x0)); |
389 | + end_insn1 = get32((uint32_t *)(p + 0x0)); | ||
390 | + end_insn2 = get32((uint32_t *)(p + 0x4)); | ||
391 | + if ((start_insn & ~0x1fff) == 0x9de3a000) { | ||
392 | + p_start += 0x4; | ||
393 | + start_offset += 0x4; | ||
394 | + if ((int)(start_insn | ~0x1fff) < -256) | ||
395 | + error("Found bogus save at the start of %s", name); | ||
396 | + if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000) | ||
397 | + error("ret; restore; not found at end of %s", name); | ||
398 | + } else { | ||
399 | + error("No save at the beginning of %s", name); | ||
400 | + } | ||
401 | + | ||
402 | + /* Skip a preceeding nop, if present. */ | ||
403 | + if (p > p_start) { | ||
404 | + skip_insn = get32((uint32_t *)(p - 0x4)); | ||
405 | + if (skip_insn == 0x01000000) | ||
406 | + p -= 4; | ||
407 | + } | ||
408 | + | ||
381 | copy_size = p - p_start; | 409 | copy_size = p - p_start; |
382 | } | 410 | } |
383 | break; | 411 | break; |
@@ -390,7 +418,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -390,7 +418,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
390 | args_present[i] = 0; | 418 | args_present[i] = 0; |
391 | 419 | ||
392 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 420 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
393 | - if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 421 | + if (rel->r_offset >= start_offset && |
422 | + rel->r_offset < start_offset + copy_size) { | ||
394 | sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; | 423 | sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
395 | if (strstart(sym_name, "__op_param", &p)) { | 424 | if (strstart(sym_name, "__op_param", &p)) { |
396 | n = strtoul(p, NULL, 10); | 425 | n = strtoul(p, NULL, 10); |
@@ -427,7 +456,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -427,7 +456,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
427 | fprintf(outfile, " extern void %s();\n", name); | 456 | fprintf(outfile, " extern void %s();\n", name); |
428 | 457 | ||
429 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 458 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
430 | - if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 459 | + if (rel->r_offset >= start_offset && |
460 | + rel->r_offset < start_offset + copy_size) { | ||
431 | sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; | 461 | sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
432 | if (*sym_name && !strstart(sym_name, "__op_param", &p)) { | 462 | if (*sym_name && !strstart(sym_name, "__op_param", &p)) { |
433 | #if defined(HOST_SPARC) | 463 | #if defined(HOST_SPARC) |
@@ -443,7 +473,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -443,7 +473,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
443 | } | 473 | } |
444 | } | 474 | } |
445 | 475 | ||
446 | - fprintf(outfile, " memcpy(gen_code_ptr, &%s, %d);\n", name, copy_size); | 476 | + fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n", name, start_offset - offset, copy_size); |
447 | for(i = 0; i < nb_args; i++) { | 477 | for(i = 0; i < nb_args; i++) { |
448 | fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1); | 478 | fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1); |
449 | } | 479 | } |
@@ -455,7 +485,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -455,7 +485,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
455 | int type; | 485 | int type; |
456 | int addend; | 486 | int addend; |
457 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 487 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
458 | - if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 488 | + if (rel->r_offset >= start_offset && |
489 | + rel->r_offset < start_offset + copy_size) { | ||
459 | sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; | 490 | sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
460 | if (strstart(sym_name, "__op_param", &p)) { | 491 | if (strstart(sym_name, "__op_param", &p)) { |
461 | snprintf(name, sizeof(name), "param%s", p); | 492 | snprintf(name, sizeof(name), "param%s", p); |
@@ -467,11 +498,11 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -467,11 +498,11 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
467 | switch(type) { | 498 | switch(type) { |
468 | case R_386_32: | 499 | case R_386_32: |
469 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", | 500 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
470 | - rel->r_offset - offset, name, addend); | 501 | + rel->r_offset - start_offset, name, addend); |
471 | break; | 502 | break; |
472 | case R_386_PC32: | 503 | case R_386_PC32: |
473 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", | 504 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", |
474 | - rel->r_offset - offset, name, rel->r_offset - offset, addend); | 505 | + rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend); |
475 | break; | 506 | break; |
476 | default: | 507 | default: |
477 | error("unsupported i386 relocation (%d)", type); | 508 | error("unsupported i386 relocation (%d)", type); |
@@ -485,7 +516,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -485,7 +516,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
485 | int type; | 516 | int type; |
486 | int addend; | 517 | int addend; |
487 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 518 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
488 | - if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 519 | + if (rel->r_offset >= start_offset && |
520 | + rel->r_offset < start_offset + copy_size) { | ||
489 | sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; | 521 | sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
490 | if (strstart(sym_name, "__op_param", &p)) { | 522 | if (strstart(sym_name, "__op_param", &p)) { |
491 | snprintf(name, sizeof(name), "param%s", p); | 523 | snprintf(name, sizeof(name), "param%s", p); |
@@ -497,24 +529,24 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -497,24 +529,24 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
497 | switch(type) { | 529 | switch(type) { |
498 | case R_PPC_ADDR32: | 530 | case R_PPC_ADDR32: |
499 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", | 531 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
500 | - rel->r_offset - offset, name, addend); | 532 | + rel->r_offset - start_offset, name, addend); |
501 | break; | 533 | break; |
502 | case R_PPC_ADDR16_LO: | 534 | case R_PPC_ADDR16_LO: |
503 | fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n", | 535 | fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n", |
504 | - rel->r_offset - offset, name, addend); | 536 | + rel->r_offset - start_offset, name, addend); |
505 | break; | 537 | break; |
506 | case R_PPC_ADDR16_HI: | 538 | case R_PPC_ADDR16_HI: |
507 | fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n", | 539 | fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n", |
508 | - rel->r_offset - offset, name, addend); | 540 | + rel->r_offset - start_offset, name, addend); |
509 | break; | 541 | break; |
510 | case R_PPC_ADDR16_HA: | 542 | case R_PPC_ADDR16_HA: |
511 | fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n", | 543 | fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n", |
512 | - rel->r_offset - offset, name, addend); | 544 | + rel->r_offset - start_offset, name, addend); |
513 | break; | 545 | break; |
514 | case R_PPC_REL24: | 546 | case R_PPC_REL24: |
515 | /* warning: must be at 32 MB distancy */ | 547 | /* warning: must be at 32 MB distancy */ |
516 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n", | 548 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n", |
517 | - rel->r_offset - offset, rel->r_offset - offset, name, rel->r_offset - offset, addend); | 549 | + rel->r_offset - start_offset, rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend); |
518 | break; | 550 | break; |
519 | default: | 551 | default: |
520 | error("unsupported powerpc relocation (%d)", type); | 552 | error("unsupported powerpc relocation (%d)", type); |
@@ -528,7 +560,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -528,7 +560,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
528 | int type; | 560 | int type; |
529 | int addend; | 561 | int addend; |
530 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 562 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
531 | - if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 563 | + if (rel->r_offset >= start_offset && |
564 | + rel->r_offset < start_offset + copy_size) { | ||
532 | sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; | 565 | sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
533 | if (strstart(sym_name, "__op_param", &p)) { | 566 | if (strstart(sym_name, "__op_param", &p)) { |
534 | snprintf(name, sizeof(name), "param%s", p); | 567 | snprintf(name, sizeof(name), "param%s", p); |
@@ -540,15 +573,15 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -540,15 +573,15 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
540 | switch(type) { | 573 | switch(type) { |
541 | case R_390_32: | 574 | case R_390_32: |
542 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", | 575 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
543 | - rel->r_offset - offset, name, addend); | 576 | + rel->r_offset - start_offset, name, addend); |
544 | break; | 577 | break; |
545 | case R_390_16: | 578 | case R_390_16: |
546 | fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n", | 579 | fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n", |
547 | - rel->r_offset - offset, name, addend); | 580 | + rel->r_offset - start_offset, name, addend); |
548 | break; | 581 | break; |
549 | case R_390_8: | 582 | case R_390_8: |
550 | fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n", | 583 | fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n", |
551 | - rel->r_offset - offset, name, addend); | 584 | + rel->r_offset - start_offset, name, addend); |
552 | break; | 585 | break; |
553 | default: | 586 | default: |
554 | error("unsupported s390 relocation (%d)", type); | 587 | error("unsupported s390 relocation (%d)", type); |
@@ -559,7 +592,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -559,7 +592,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
559 | #elif defined(HOST_ALPHA) | 592 | #elif defined(HOST_ALPHA) |
560 | { | 593 | { |
561 | for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { | 594 | for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { |
562 | - if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 595 | + if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { |
563 | int type; | 596 | int type; |
564 | 597 | ||
565 | type = ELF64_R_TYPE(rel->r_info); | 598 | type = ELF64_R_TYPE(rel->r_info); |
@@ -569,9 +602,9 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -569,9 +602,9 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
569 | /* The gp is just 32 bit, and never changes, so it's easiest to emit it | 602 | /* The gp is just 32 bit, and never changes, so it's easiest to emit it |
570 | as an immediate instead of constructing it from the pv or ra. */ | 603 | as an immediate instead of constructing it from the pv or ra. */ |
571 | fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n", | 604 | fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n", |
572 | - rel->r_offset - offset); | 605 | + rel->r_offset - start_offset); |
573 | fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n", | 606 | fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n", |
574 | - rel->r_offset - offset + rel->r_addend); | 607 | + rel->r_offset - start_offset + rel->r_addend); |
575 | break; | 608 | break; |
576 | case R_ALPHA_LITUSE: | 609 | case R_ALPHA_LITUSE: |
577 | /* jsr to literal hint. Could be used to optimize to bsr. Ignore for | 610 | /* jsr to literal hint. Could be used to optimize to bsr. Ignore for |
@@ -591,18 +624,18 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -591,18 +624,18 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
591 | special treatment. */ | 624 | special treatment. */ |
592 | if (strstart(sym_name, "__op_param", &p)) | 625 | if (strstart(sym_name, "__op_param", &p)) |
593 | fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n", | 626 | fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n", |
594 | - rel->r_offset - offset, p); | 627 | + rel->r_offset - start_offset, p); |
595 | break; | 628 | break; |
596 | case R_ALPHA_GPRELLOW: | 629 | case R_ALPHA_GPRELLOW: |
597 | if (strstart(sym_name, "__op_param", &p)) | 630 | if (strstart(sym_name, "__op_param", &p)) |
598 | fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n", | 631 | fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n", |
599 | - rel->r_offset - offset, p); | 632 | + rel->r_offset - start_offset, p); |
600 | break; | 633 | break; |
601 | case R_ALPHA_BRSGP: | 634 | case R_ALPHA_BRSGP: |
602 | /* PC-relative jump. Tweak offset to skip the two instructions that try to | 635 | /* PC-relative jump. Tweak offset to skip the two instructions that try to |
603 | set up the gp from the pv. */ | 636 | set up the gp from the pv. */ |
604 | fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld) + 4);\n", | 637 | fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld) + 4);\n", |
605 | - rel->r_offset - offset, sym_name, rel->r_offset - offset); | 638 | + rel->r_offset - start_offset, sym_name, rel->r_offset - start_offset); |
606 | break; | 639 | break; |
607 | default: | 640 | default: |
608 | error("unsupported Alpha relocation (%d)", type); | 641 | error("unsupported Alpha relocation (%d)", type); |
@@ -616,7 +649,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -616,7 +649,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
616 | int type; | 649 | int type; |
617 | int addend; | 650 | int addend; |
618 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 651 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
619 | - if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 652 | + if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { |
620 | sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; | 653 | sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; |
621 | if (strstart(sym_name, "__op_param", &p)) { | 654 | if (strstart(sym_name, "__op_param", &p)) { |
622 | snprintf(name, sizeof(name), "param%s", p); | 655 | snprintf(name, sizeof(name), "param%s", p); |
@@ -642,7 +675,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -642,7 +675,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
642 | int type; | 675 | int type; |
643 | int addend; | 676 | int addend; |
644 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 677 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
645 | - if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 678 | + if (rel->r_offset >= start_offset && |
679 | + rel->r_offset < start_offset + copy_size) { | ||
646 | sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | 680 | sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; |
647 | if (strstart(sym_name, "__op_param", &p)) { | 681 | if (strstart(sym_name, "__op_param", &p)) { |
648 | snprintf(name, sizeof(name), "param%s", p); | 682 | snprintf(name, sizeof(name), "param%s", p); |
@@ -660,16 +694,16 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -660,16 +694,16 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
660 | switch(type) { | 694 | switch(type) { |
661 | case R_SPARC_32: | 695 | case R_SPARC_32: |
662 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", | 696 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
663 | - rel->r_offset - offset, name, addend); | 697 | + rel->r_offset - start_offset, name, addend); |
664 | break; | 698 | break; |
665 | case R_SPARC_HI22: | 699 | case R_SPARC_HI22: |
666 | fprintf(outfile, | 700 | fprintf(outfile, |
667 | " *(uint32_t *)(gen_code_ptr + %d) = " | 701 | " *(uint32_t *)(gen_code_ptr + %d) = " |
668 | "((*(uint32_t *)(gen_code_ptr + %d)) " | 702 | "((*(uint32_t *)(gen_code_ptr + %d)) " |
669 | " & ~0x3fffff) " | 703 | " & ~0x3fffff) " |
670 | - " | ((%s + %d) & 0x3fffff);\n", | ||
671 | - rel->r_offset - offset, | ||
672 | - rel->r_offset - offset, | 704 | + " | (((%s + %d) >> 10) & 0x3fffff);\n", |
705 | + rel->r_offset - start_offset, | ||
706 | + rel->r_offset - start_offset, | ||
673 | name, addend); | 707 | name, addend); |
674 | break; | 708 | break; |
675 | case R_SPARC_LO10: | 709 | case R_SPARC_LO10: |
@@ -678,8 +712,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -678,8 +712,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
678 | "((*(uint32_t *)(gen_code_ptr + %d)) " | 712 | "((*(uint32_t *)(gen_code_ptr + %d)) " |
679 | " & ~0x3ff) " | 713 | " & ~0x3ff) " |
680 | " | ((%s + %d) & 0x3ff);\n", | 714 | " | ((%s + %d) & 0x3ff);\n", |
681 | - rel->r_offset - offset, | ||
682 | - rel->r_offset - offset, | 715 | + rel->r_offset - start_offset, |
716 | + rel->r_offset - start_offset, | ||
683 | name, addend); | 717 | name, addend); |
684 | break; | 718 | break; |
685 | case R_SPARC_WDISP30: | 719 | case R_SPARC_WDISP30: |
@@ -687,11 +721,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -687,11 +721,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
687 | " *(uint32_t *)(gen_code_ptr + %d) = " | 721 | " *(uint32_t *)(gen_code_ptr + %d) = " |
688 | "((*(uint32_t *)(gen_code_ptr + %d)) " | 722 | "((*(uint32_t *)(gen_code_ptr + %d)) " |
689 | " & ~0x3fffffff) " | 723 | " & ~0x3fffffff) " |
690 | - " | ((((%s + %d) - (long)gen_code_ptr)>>2) " | 724 | + " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) " |
691 | " & 0x3fffffff);\n", | 725 | " & 0x3fffffff);\n", |
692 | - rel->r_offset - offset, | ||
693 | - rel->r_offset - offset, | ||
694 | - name, addend); | 726 | + rel->r_offset - start_offset, |
727 | + rel->r_offset - start_offset, | ||
728 | + name, addend, | ||
729 | + rel->r_offset - start_offset); | ||
695 | break; | 730 | break; |
696 | default: | 731 | default: |
697 | error("unsupported sparc relocation (%d)", type); | 732 | error("unsupported sparc relocation (%d)", type); |
@@ -705,7 +740,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -705,7 +740,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
705 | int type; | 740 | int type; |
706 | int addend; | 741 | int addend; |
707 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 742 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
708 | - if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 743 | + if (rel->r_offset >= start_offset && |
744 | + rel->r_offset < start_offset + copy_size) { | ||
709 | sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; | 745 | sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; |
710 | if (strstart(sym_name, "__op_param", &p)) { | 746 | if (strstart(sym_name, "__op_param", &p)) { |
711 | snprintf(name, sizeof(name), "param%s", p); | 747 | snprintf(name, sizeof(name), "param%s", p); |
@@ -717,16 +753,16 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -717,16 +753,16 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
717 | switch(type) { | 753 | switch(type) { |
718 | case R_SPARC_32: | 754 | case R_SPARC_32: |
719 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", | 755 | fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", |
720 | - rel->r_offset - offset, name, addend); | 756 | + rel->r_offset - start_offset, name, addend); |
721 | break; | 757 | break; |
722 | case R_SPARC_HI22: | 758 | case R_SPARC_HI22: |
723 | fprintf(outfile, | 759 | fprintf(outfile, |
724 | " *(uint32_t *)(gen_code_ptr + %d) = " | 760 | " *(uint32_t *)(gen_code_ptr + %d) = " |
725 | "((*(uint32_t *)(gen_code_ptr + %d)) " | 761 | "((*(uint32_t *)(gen_code_ptr + %d)) " |
726 | " & ~0x3fffff) " | 762 | " & ~0x3fffff) " |
727 | - " | ((%s + %d) & 0x3fffff);\n", | ||
728 | - rel->r_offset - offset, | ||
729 | - rel->r_offset - offset, | 763 | + " | (((%s + %d) >> 10) & 0x3fffff);\n", |
764 | + rel->r_offset - start_offset, | ||
765 | + rel->r_offset - start_offset, | ||
730 | name, addend); | 766 | name, addend); |
731 | break; | 767 | break; |
732 | case R_SPARC_LO10: | 768 | case R_SPARC_LO10: |
@@ -735,8 +771,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -735,8 +771,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
735 | "((*(uint32_t *)(gen_code_ptr + %d)) " | 771 | "((*(uint32_t *)(gen_code_ptr + %d)) " |
736 | " & ~0x3ff) " | 772 | " & ~0x3ff) " |
737 | " | ((%s + %d) & 0x3ff);\n", | 773 | " | ((%s + %d) & 0x3ff);\n", |
738 | - rel->r_offset - offset, | ||
739 | - rel->r_offset - offset, | 774 | + rel->r_offset - start_offset, |
775 | + rel->r_offset - start_offset, | ||
740 | name, addend); | 776 | name, addend); |
741 | break; | 777 | break; |
742 | case R_SPARC_WDISP30: | 778 | case R_SPARC_WDISP30: |
@@ -744,11 +780,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -744,11 +780,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
744 | " *(uint32_t *)(gen_code_ptr + %d) = " | 780 | " *(uint32_t *)(gen_code_ptr + %d) = " |
745 | "((*(uint32_t *)(gen_code_ptr + %d)) " | 781 | "((*(uint32_t *)(gen_code_ptr + %d)) " |
746 | " & ~0x3fffffff) " | 782 | " & ~0x3fffffff) " |
747 | - " | ((((%s + %d) - (long)gen_code_ptr)>>2) " | 783 | + " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) " |
748 | " & 0x3fffffff);\n", | 784 | " & 0x3fffffff);\n", |
749 | - rel->r_offset - offset, | ||
750 | - rel->r_offset - offset, | ||
751 | - name, addend); | 785 | + rel->r_offset - start_offset, |
786 | + rel->r_offset - start_offset, | ||
787 | + name, addend, | ||
788 | + rel->r_offset - start_offset); | ||
752 | break; | 789 | break; |
753 | default: | 790 | default: |
754 | error("unsupported sparc64 relocation (%d)", type); | 791 | error("unsupported sparc64 relocation (%d)", type); |
@@ -933,7 +970,22 @@ fprintf(outfile, | @@ -933,7 +970,22 @@ fprintf(outfile, | ||
933 | " const uint32_t *opparam_ptr;\n" | 970 | " const uint32_t *opparam_ptr;\n" |
934 | " gen_code_ptr = gen_code_buf;\n" | 971 | " gen_code_ptr = gen_code_buf;\n" |
935 | " opc_ptr = opc_buf;\n" | 972 | " opc_ptr = opc_buf;\n" |
936 | -" opparam_ptr = opparam_buf;\n" | 973 | +" opparam_ptr = opparam_buf;\n"); |
974 | + | ||
975 | + /* Generate prologue, if needed. */ | ||
976 | + switch(ELF_ARCH) { | ||
977 | + case EM_SPARC: | ||
978 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x9c23a080; /* sub %%sp, 128, %%sp */\n"); | ||
979 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0xbc27a080; /* sub %%fp, 128, %%fp */\n"); | ||
980 | + break; | ||
981 | + | ||
982 | + case EM_SPARCV9: | ||
983 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x9c23a100; /* sub %%sp, 256, %%sp */\n"); | ||
984 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0xbc27a100; /* sub %%fp, 256, %%fp */\n"); | ||
985 | + break; | ||
986 | + }; | ||
987 | + | ||
988 | +fprintf(outfile, | ||
937 | " for(;;) {\n" | 989 | " for(;;) {\n" |
938 | " switch(*opc_ptr++) {\n" | 990 | " switch(*opc_ptr++) {\n" |
939 | ); | 991 | ); |
@@ -961,7 +1013,7 @@ fprintf(outfile, | @@ -961,7 +1013,7 @@ fprintf(outfile, | ||
961 | " the_end:\n" | 1013 | " the_end:\n" |
962 | ); | 1014 | ); |
963 | 1015 | ||
964 | -/* generate a return */ | 1016 | +/* generate epilogue */ |
965 | switch(ELF_ARCH) { | 1017 | switch(ELF_ARCH) { |
966 | case EM_386: | 1018 | case EM_386: |
967 | fprintf(outfile, "*gen_code_ptr++ = 0xc3; /* ret */\n"); | 1019 | fprintf(outfile, "*gen_code_ptr++ = 0xc3; /* ret */\n"); |
@@ -980,11 +1032,13 @@ fprintf(outfile, | @@ -980,11 +1032,13 @@ fprintf(outfile, | ||
980 | break; | 1032 | break; |
981 | case EM_SPARC: | 1033 | case EM_SPARC: |
982 | case EM_SPARC32PLUS: | 1034 | case EM_SPARC32PLUS: |
1035 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0xbc07a080; /* add %%fp, 256, %%fp */\n"); | ||
1036 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81c62008; /* jmpl %%i0 + 8, %%g0 */\n"); | ||
1037 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x9c03a080; /* add %%sp, 256, %%sp */\n"); | ||
1038 | + break; | ||
983 | case EM_SPARCV9: | 1039 | case EM_SPARCV9: |
984 | - /* Fill the delay slot. */ | ||
985 | - fprintf(outfile, "*((uint32_t *)gen_code_ptr) = *((uint32_t *)gen_code_ptr - 1); /* delay slot */\n"); | ||
986 | - fprintf(outfile, "*((uint32_t *)gen_code_ptr - 1) = 0x81c3e008; /* retl */\n"); | ||
987 | - fprintf(outfile, "gen_code_ptr++;\n"); | 1040 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81c7e008; /* ret */\n"); |
1041 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81e80000; /* restore */\n"); | ||
988 | break; | 1042 | break; |
989 | default: | 1043 | default: |
990 | error("unknown ELF architecture"); | 1044 | error("unknown ELF architecture"); |
exec-i386.c
@@ -153,6 +153,13 @@ void raise_exception_err(int exception_index, int error_code) | @@ -153,6 +153,13 @@ void raise_exception_err(int exception_index, int error_code) | ||
153 | { | 153 | { |
154 | /* NOTE: the register at this point must be saved by hand because | 154 | /* NOTE: the register at this point must be saved by hand because |
155 | longjmp restore them */ | 155 | longjmp restore them */ |
156 | +#ifdef __sparc__ | ||
157 | + /* We have to stay in the same register window as our caller, | ||
158 | + * thus this trick. | ||
159 | + */ | ||
160 | + __asm__ __volatile__("restore\n\t" | ||
161 | + "mov\t%o0, %i0"); | ||
162 | +#endif | ||
156 | #ifdef reg_EAX | 163 | #ifdef reg_EAX |
157 | env->regs[R_EAX] = EAX; | 164 | env->regs[R_EAX] = EAX; |
158 | #endif | 165 | #endif |
@@ -409,7 +416,15 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -409,7 +416,15 @@ int cpu_x86_exec(CPUX86State *env1) | ||
409 | /* execute the generated code */ | 416 | /* execute the generated code */ |
410 | tc_ptr = tb->tc_ptr; | 417 | tc_ptr = tb->tc_ptr; |
411 | gen_func = (void *)tc_ptr; | 418 | gen_func = (void *)tc_ptr; |
419 | +#ifdef __sparc__ | ||
420 | + __asm__ __volatile__("call %0\n\t" | ||
421 | + " mov %%o7,%%i0" | ||
422 | + : /* no outputs */ | ||
423 | + : "r" (gen_func) | ||
424 | + : "i0", "i1", "i2", "i3", "i4", "i5"); | ||
425 | +#else | ||
412 | gen_func(); | 426 | gen_func(); |
427 | +#endif | ||
413 | } | 428 | } |
414 | } | 429 | } |
415 | ret = env->exception_index; | 430 | ret = env->exception_index; |
exec-i386.h
@@ -89,11 +89,27 @@ register unsigned int A0 asm("s2"); | @@ -89,11 +89,27 @@ register unsigned int A0 asm("s2"); | ||
89 | register struct CPUX86State *env asm("s3"); | 89 | register struct CPUX86State *env asm("s3"); |
90 | #endif | 90 | #endif |
91 | #ifdef __sparc__ | 91 | #ifdef __sparc__ |
92 | -register unsigned int T0 asm("l0"); | ||
93 | -register unsigned int T1 asm("l1"); | ||
94 | -register unsigned int A0 asm("l2"); | ||
95 | -register struct CPUX86State *env asm("l3"); | 92 | +register unsigned int EAX asm("l0"); |
93 | +register unsigned int ECX asm("l1"); | ||
94 | +register unsigned int EDX asm("l2"); | ||
95 | +register unsigned int EBX asm("l3"); | ||
96 | +register unsigned int ESP asm("l4"); | ||
97 | +register unsigned int EBP asm("l5"); | ||
98 | +register unsigned int ESI asm("l6"); | ||
99 | +register unsigned int EDI asm("l7"); | ||
100 | +register unsigned int T0 asm("g1"); | ||
101 | +register unsigned int T1 asm("g2"); | ||
102 | +register unsigned int A0 asm("g3"); | ||
103 | +register struct CPUX86State *env asm("g6"); | ||
96 | #define USE_FP_CONVERT | 104 | #define USE_FP_CONVERT |
105 | +#define reg_EAX | ||
106 | +#define reg_ECX | ||
107 | +#define reg_EDX | ||
108 | +#define reg_EBX | ||
109 | +#define reg_ESP | ||
110 | +#define reg_EBP | ||
111 | +#define reg_ESI | ||
112 | +#define reg_EDI | ||
97 | #endif | 113 | #endif |
98 | #ifdef __s390__ | 114 | #ifdef __s390__ |
99 | register unsigned int T0 asm("r7"); | 115 | register unsigned int T0 asm("r7"); |