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,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(&quot;s2&quot;); @@ -89,11 +89,27 @@ register unsigned int A0 asm(&quot;s2&quot;);
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");