Commit ae2285314189c0ea32fc73d38c1e9b8051d213ab

Authored by bellard
1 parent d418c81e

Sparc update (David S. Miller)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@161 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile
... ... @@ -29,6 +29,18 @@ OP_CFLAGS=$(CFLAGS)
29 29 LDFLAGS+=-Wl,-T,s390.ld
30 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 44 ifeq ($(ARCH),alpha)
33 45 # -msmall-data is not used because we want two-instruction relocations
34 46 # for the constant constructions
... ...
configure
... ... @@ -47,6 +47,12 @@ case "$cpu" in
47 47 s390)
48 48 cpu="s390"
49 49 ;;
  50 + sparc)
  51 + cpu="sparc"
  52 + ;;
  53 + sparc64)
  54 + cpu="sparc64"
  55 + ;;
50 56 ia64)
51 57 cpu="ia64"
52 58 ;;
... ... @@ -131,7 +137,7 @@ fi
131 137 else
132 138  
133 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 141 bigendian="yes"
136 142 fi
137 143  
... ... @@ -217,6 +223,12 @@ elif test "$cpu" = "s390" ; then
217 223 elif test "$cpu" = "alpha" ; then
218 224 echo "ARCH=alpha" >> config.mak
219 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 232 elif test "$cpu" = "ia64" ; then
221 233 echo "ARCH=ia64" >> config.mak
222 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 274 {
275 275 int copy_size = 0;
276 276 uint8_t *p_start, *p_end;
  277 + host_ulong start_offset;
277 278 int nb_args, i, n;
278 279 uint8_t args_present[MAX_ARGS];
279 280 const char *sym_name, *p;
280 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 288 p_start = text + offset;
284 289 p_end = p_start + size;
  290 + start_offset = offset;
285 291 switch(ELF_ARCH) {
286 292 case EM_386:
287 293 {
... ... @@ -343,41 +349,63 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
343 349 case EM_SPARC:
344 350 case EM_SPARC32PLUS:
345 351 {
  352 + uint32_t start_insn, end_insn1, end_insn2, skip_insn;
346 353 uint8_t *p;
347 354 p = (void *)(p_end - 8);
348 355 if (p <= p_start)
349 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 378 copy_size = p - p_start;
362 379 }
363 380 break;
364 381 case EM_SPARCV9:
365 382 {
  383 + uint32_t start_insn, end_insn1, end_insn2, skip_insn;
366 384 uint8_t *p;
367 385 p = (void *)(p_end - 8);
368 386 if (p <= p_start)
369 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 409 copy_size = p - p_start;
382 410 }
383 411 break;
... ... @@ -390,7 +418,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
390 418 args_present[i] = 0;
391 419  
392 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 423 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
395 424 if (strstart(sym_name, "__op_param", &p)) {
396 425 n = strtoul(p, NULL, 10);
... ... @@ -427,7 +456,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
427 456 fprintf(outfile, " extern void %s();\n", name);
428 457  
429 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 461 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
432 462 if (*sym_name && !strstart(sym_name, "__op_param", &p)) {
433 463 #if defined(HOST_SPARC)
... ... @@ -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 477 for(i = 0; i < nb_args; i++) {
448 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 485 int type;
456 486 int addend;
457 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 490 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
460 491 if (strstart(sym_name, "__op_param", &p)) {
461 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 498 switch(type) {
468 499 case R_386_32:
469 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 502 break;
472 503 case R_386_PC32:
473 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 506 break;
476 507 default:
477 508 error("unsupported i386 relocation (%d)", type);
... ... @@ -485,7 +516,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
485 516 int type;
486 517 int addend;
487 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 521 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
490 522 if (strstart(sym_name, "__op_param", &p)) {
491 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 529 switch(type) {
498 530 case R_PPC_ADDR32:
499 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 533 break;
502 534 case R_PPC_ADDR16_LO:
503 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 537 break;
506 538 case R_PPC_ADDR16_HI:
507 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 541 break;
510 542 case R_PPC_ADDR16_HA:
511 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 545 break;
514 546 case R_PPC_REL24:
515 547 /* warning: must be at 32 MB distancy */
516 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 550 break;
519 551 default:
520 552 error("unsupported powerpc relocation (%d)", type);
... ... @@ -528,7 +560,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
528 560 int type;
529 561 int addend;
530 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 565 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
533 566 if (strstart(sym_name, "__op_param", &p)) {
534 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 573 switch(type) {
541 574 case R_390_32:
542 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 577 break;
545 578 case R_390_16:
546 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 581 break;
549 582 case R_390_8:
550 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 585 break;
553 586 default:
554 587 error("unsupported s390 relocation (%d)", type);
... ... @@ -559,7 +592,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
559 592 #elif defined(HOST_ALPHA)
560 593 {
561 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 596 int type;
564 597  
565 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 602 /* The gp is just 32 bit, and never changes, so it's easiest to emit it
570 603 as an immediate instead of constructing it from the pv or ra. */
571 604 fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
572   - rel->r_offset - offset);
  605 + rel->r_offset - start_offset);
573 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 608 break;
576 609 case R_ALPHA_LITUSE:
577 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 624 special treatment. */
592 625 if (strstart(sym_name, "__op_param", &p))
593 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 628 break;
596 629 case R_ALPHA_GPRELLOW:
597 630 if (strstart(sym_name, "__op_param", &p))
598 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 633 break;
601 634 case R_ALPHA_BRSGP:
602 635 /* PC-relative jump. Tweak offset to skip the two instructions that try to
603 636 set up the gp from the pv. */
604 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 639 break;
607 640 default:
608 641 error("unsupported Alpha relocation (%d)", type);
... ... @@ -616,7 +649,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
616 649 int type;
617 650 int addend;
618 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 653 sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
621 654 if (strstart(sym_name, "__op_param", &p)) {
622 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 675 int type;
643 676 int addend;
644 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 680 sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
647 681 if (strstart(sym_name, "__op_param", &p)) {
648 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 694 switch(type) {
661 695 case R_SPARC_32:
662 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 698 break;
665 699 case R_SPARC_HI22:
666 700 fprintf(outfile,
667 701 " *(uint32_t *)(gen_code_ptr + %d) = "
668 702 "((*(uint32_t *)(gen_code_ptr + %d)) "
669 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 707 name, addend);
674 708 break;
675 709 case R_SPARC_LO10:
... ... @@ -678,8 +712,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
678 712 "((*(uint32_t *)(gen_code_ptr + %d)) "
679 713 " & ~0x3ff) "
680 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 717 name, addend);
684 718 break;
685 719 case R_SPARC_WDISP30:
... ... @@ -687,11 +721,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
687 721 " *(uint32_t *)(gen_code_ptr + %d) = "
688 722 "((*(uint32_t *)(gen_code_ptr + %d)) "
689 723 " & ~0x3fffffff) "
690   - " | ((((%s + %d) - (long)gen_code_ptr)>>2) "
  724 + " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
691 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 730 break;
696 731 default:
697 732 error("unsupported sparc relocation (%d)", type);
... ... @@ -705,7 +740,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
705 740 int type;
706 741 int addend;
707 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 745 sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
710 746 if (strstart(sym_name, "__op_param", &p)) {
711 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 753 switch(type) {
718 754 case R_SPARC_32:
719 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 757 break;
722 758 case R_SPARC_HI22:
723 759 fprintf(outfile,
724 760 " *(uint32_t *)(gen_code_ptr + %d) = "
725 761 "((*(uint32_t *)(gen_code_ptr + %d)) "
726 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 766 name, addend);
731 767 break;
732 768 case R_SPARC_LO10:
... ... @@ -735,8 +771,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
735 771 "((*(uint32_t *)(gen_code_ptr + %d)) "
736 772 " & ~0x3ff) "
737 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 776 name, addend);
741 777 break;
742 778 case R_SPARC_WDISP30:
... ... @@ -744,11 +780,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
744 780 " *(uint32_t *)(gen_code_ptr + %d) = "
745 781 "((*(uint32_t *)(gen_code_ptr + %d)) "
746 782 " & ~0x3fffffff) "
747   - " | ((((%s + %d) - (long)gen_code_ptr)>>2) "
  783 + " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
748 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 789 break;
753 790 default:
754 791 error("unsupported sparc64 relocation (%d)", type);
... ... @@ -933,7 +970,22 @@ fprintf(outfile,
933 970 " const uint32_t *opparam_ptr;\n"
934 971 " gen_code_ptr = gen_code_buf;\n"
935 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 989 " for(;;) {\n"
938 990 " switch(*opc_ptr++) {\n"
939 991 );
... ... @@ -961,7 +1013,7 @@ fprintf(outfile,
961 1013 " the_end:\n"
962 1014 );
963 1015  
964   -/* generate a return */
  1016 +/* generate epilogue */
965 1017 switch(ELF_ARCH) {
966 1018 case EM_386:
967 1019 fprintf(outfile, "*gen_code_ptr++ = 0xc3; /* ret */\n");
... ... @@ -980,11 +1032,13 @@ fprintf(outfile,
980 1032 break;
981 1033 case EM_SPARC:
982 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 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 1042 break;
989 1043 default:
990 1044 error("unknown ELF architecture");
... ...
exec-i386.c
... ... @@ -153,6 +153,13 @@ void raise_exception_err(int exception_index, int error_code)
153 153 {
154 154 /* NOTE: the register at this point must be saved by hand because
155 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 163 #ifdef reg_EAX
157 164 env->regs[R_EAX] = EAX;
158 165 #endif
... ... @@ -409,7 +416,15 @@ int cpu_x86_exec(CPUX86State *env1)
409 416 /* execute the generated code */
410 417 tc_ptr = tb->tc_ptr;
411 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 426 gen_func();
  427 +#endif
413 428 }
414 429 }
415 430 ret = env->exception_index;
... ...
exec-i386.h
... ... @@ -89,11 +89,27 @@ register unsigned int A0 asm(&quot;s2&quot;);
89 89 register struct CPUX86State *env asm("s3");
90 90 #endif
91 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 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 113 #endif
98 114 #ifdef __s390__
99 115 register unsigned int T0 asm("r7");
... ...