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