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 | 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("s2"); |
| 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"); | ... | ... |