Commit efdea7bf193bb5f00737022f8a6efeab3e4d5ff4
1 parent
0d330196
ia64 support - alpha support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@116 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
136 additions
and
22 deletions
dyngen.c
| @@ -58,20 +58,29 @@ | @@ -58,20 +58,29 @@ | ||
| 58 | #define elf_check_arch(x) ((x) == EM_ALPHA) | 58 | #define elf_check_arch(x) ((x) == EM_ALPHA) |
| 59 | #define ELF_USES_RELOCA | 59 | #define ELF_USES_RELOCA |
| 60 | 60 | ||
| 61 | +#elif defined(HOST_IA64) | ||
| 62 | + | ||
| 63 | +#define ELF_CLASS ELFCLASS64 | ||
| 64 | +#define ELF_ARCH EM_IA_64 | ||
| 65 | +#define elf_check_arch(x) ((x) == EM_IA_64) | ||
| 66 | +#define ELF_USES_RELOCA | ||
| 67 | + | ||
| 61 | #else | 68 | #else |
| 62 | #error unsupported CPU - please update the code | 69 | #error unsupported CPU - please update the code |
| 63 | #endif | 70 | #endif |
| 64 | 71 | ||
| 72 | +#include "elf.h" | ||
| 73 | + | ||
| 65 | #if ELF_CLASS == ELFCLASS32 | 74 | #if ELF_CLASS == ELFCLASS32 |
| 66 | typedef int32_t host_long; | 75 | typedef int32_t host_long; |
| 67 | typedef uint32_t host_ulong; | 76 | typedef uint32_t host_ulong; |
| 77 | +#define swabls(x) swab32s(x) | ||
| 68 | #else | 78 | #else |
| 69 | typedef int64_t host_long; | 79 | typedef int64_t host_long; |
| 70 | typedef uint64_t host_ulong; | 80 | typedef uint64_t host_ulong; |
| 81 | +#define swabls(x) swab64s(x) | ||
| 71 | #endif | 82 | #endif |
| 72 | 83 | ||
| 73 | -#include "elf.h" | ||
| 74 | - | ||
| 75 | #include "thunk.h" | 84 | #include "thunk.h" |
| 76 | 85 | ||
| 77 | /* all dynamically generated functions begin with this code */ | 86 | /* all dynamically generated functions begin with this code */ |
| @@ -104,12 +113,6 @@ void swab64s(uint64_t *p) | @@ -104,12 +113,6 @@ void swab64s(uint64_t *p) | ||
| 104 | *p = bswap64(*p); | 113 | *p = bswap64(*p); |
| 105 | } | 114 | } |
| 106 | 115 | ||
| 107 | -#if ELF_CLASS == ELFCLASS32 | ||
| 108 | -#define swabls(x) swab32s(x) | ||
| 109 | -#else | ||
| 110 | -#define swabls(x) swab64s(x) | ||
| 111 | -#endif | ||
| 112 | - | ||
| 113 | void elf_swap_ehdr(struct elfhdr *h) | 116 | void elf_swap_ehdr(struct elfhdr *h) |
| 114 | { | 117 | { |
| 115 | swab16s(&h->e_type); /* Object file type */ | 118 | swab16s(&h->e_type); /* Object file type */ |
| @@ -187,7 +190,7 @@ void put32(uint32_t *p, uint32_t val) | @@ -187,7 +190,7 @@ void put32(uint32_t *p, uint32_t val) | ||
| 187 | *p = val; | 190 | *p = val; |
| 188 | } | 191 | } |
| 189 | 192 | ||
| 190 | -void __attribute__((noreturn)) error(const char *fmt, ...) | 193 | +void __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) error(const char *fmt, ...) |
| 191 | { | 194 | { |
| 192 | va_list ap; | 195 | va_list ap; |
| 193 | va_start(ap, fmt); | 196 | va_start(ap, fmt); |
| @@ -295,10 +298,36 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -295,10 +298,36 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 295 | if (p == p_start) | 298 | if (p == p_start) |
| 296 | error("empty code for %s", name); | 299 | error("empty code for %s", name); |
| 297 | if (get16((uint16_t *)p) != 0x07fe && get16((uint16_t *)p) != 0x07f4) | 300 | if (get16((uint16_t *)p) != 0x07fe && get16((uint16_t *)p) != 0x07f4) |
| 298 | - error("br %r14 expected at the end of %s", name); | 301 | + error("br %%r14 expected at the end of %s", name); |
| 299 | copy_size = p - p_start; | 302 | copy_size = p - p_start; |
| 300 | } | 303 | } |
| 301 | break; | 304 | break; |
| 305 | + case EM_ALPHA: | ||
| 306 | + { | ||
| 307 | + uint8_t *p; | ||
| 308 | + p = p_end - 4; | ||
| 309 | + if (p == p_start) | ||
| 310 | + error("empty code for %s", name); | ||
| 311 | + if (get32((uint32_t *)p) != 0x6bfa8001) | ||
| 312 | + error("ret expected at the end of %s", name); | ||
| 313 | + copy_size = p - p_start; | ||
| 314 | + } | ||
| 315 | + break; | ||
| 316 | + case EM_IA_64: | ||
| 317 | + { | ||
| 318 | + uint8_t *p; | ||
| 319 | + p = (void *)(p_end - 4); | ||
| 320 | + if (p == p_start) | ||
| 321 | + error("empty code for %s", name); | ||
| 322 | + /* br.ret.sptk.many b0;; */ | ||
| 323 | + /* 08 00 84 00 */ | ||
| 324 | + if (get32((uint32_t *)p) != 0x00840008) | ||
| 325 | + error("br.ret.sptk.many b0;; expected at the end of %s", name); | ||
| 326 | + copy_size = p - p_start; | ||
| 327 | + } | ||
| 328 | + break; | ||
| 329 | + default: | ||
| 330 | + error("unknown ELF architecture"); | ||
| 302 | } | 331 | } |
| 303 | 332 | ||
| 304 | /* compute the number of arguments by looking at the relocations */ | 333 | /* compute the number of arguments by looking at the relocations */ |
| @@ -344,7 +373,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -344,7 +373,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 344 | 373 | ||
| 345 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 374 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 346 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 375 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
| 347 | - sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | 376 | + sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
| 348 | if (!strstart(sym_name, "__op_param", &p)) { | 377 | if (!strstart(sym_name, "__op_param", &p)) { |
| 349 | fprintf(outfile, "extern char %s;\n", sym_name); | 378 | fprintf(outfile, "extern char %s;\n", sym_name); |
| 350 | } | 379 | } |
| @@ -364,7 +393,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -364,7 +393,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 364 | int addend; | 393 | int addend; |
| 365 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 394 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 366 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 395 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
| 367 | - sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | 396 | + sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
| 368 | if (strstart(sym_name, "__op_param", &p)) { | 397 | if (strstart(sym_name, "__op_param", &p)) { |
| 369 | snprintf(name, sizeof(name), "param%s", p); | 398 | snprintf(name, sizeof(name), "param%s", p); |
| 370 | } else { | 399 | } else { |
| @@ -394,7 +423,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -394,7 +423,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 394 | int addend; | 423 | int addend; |
| 395 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 424 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 396 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 425 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
| 397 | - sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | 426 | + sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
| 398 | if (strstart(sym_name, "__op_param", &p)) { | 427 | if (strstart(sym_name, "__op_param", &p)) { |
| 399 | snprintf(name, sizeof(name), "param%s", p); | 428 | snprintf(name, sizeof(name), "param%s", p); |
| 400 | } else { | 429 | } else { |
| @@ -437,7 +466,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -437,7 +466,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 437 | int addend; | 466 | int addend; |
| 438 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 467 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 439 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 468 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
| 440 | - sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | 469 | + sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
| 441 | if (strstart(sym_name, "__op_param", &p)) { | 470 | if (strstart(sym_name, "__op_param", &p)) { |
| 442 | snprintf(name, sizeof(name), "param%s", p); | 471 | snprintf(name, sizeof(name), "param%s", p); |
| 443 | } else { | 472 | } else { |
| @@ -464,6 +493,67 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -464,6 +493,67 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 464 | } | 493 | } |
| 465 | } | 494 | } |
| 466 | } | 495 | } |
| 496 | +#elif defined(HOST_ALPHA) | ||
| 497 | + { | ||
| 498 | + for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { | ||
| 499 | + if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | ||
| 500 | + int type; | ||
| 501 | + sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; | ||
| 502 | + | ||
| 503 | + type = ELF64_R_TYPE(rel->r_info); | ||
| 504 | + switch (type) { | ||
| 505 | + case R_ALPHA_GPDISP: | ||
| 506 | + /* Instructions to set up the gp can be nopped, since we keep it current | ||
| 507 | + all the time. FIXME assert that target is really gp */ | ||
| 508 | + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = 0x2ffe0000; /* unop */\n", | ||
| 509 | + rel->r_offset - offset); | ||
| 510 | + break; | ||
| 511 | + case R_ALPHA_LITUSE: | ||
| 512 | + /* jsr to literal hint. Could be used to optimize to bsr. Ignore for | ||
| 513 | + now, since some called functions (libc) need pv to be set up. */ | ||
| 514 | + break; | ||
| 515 | + case R_ALPHA_HINT: | ||
| 516 | + /* Branch target prediction hint. Ignore for now. Should be already | ||
| 517 | + correct for in-function jumps. */ | ||
| 518 | + break; | ||
| 519 | + case R_ALPHA_LITERAL: | ||
| 520 | + /* Load a literal from the GOT relative to the gp. Need to patch the | ||
| 521 | + 16-bit immediate offset. */ | ||
| 522 | + fprintf(outfile, " *(int16_t *)(gen_code_ptr + %d) = gp - (long)(&%s);\n", | ||
| 523 | + rel->r_offset - offset, name); | ||
| 524 | + break; | ||
| 525 | + default: | ||
| 526 | + error("unsupported Alpha relocation (%d)", type); | ||
| 527 | + } | ||
| 528 | + } | ||
| 529 | + } | ||
| 530 | + } | ||
| 531 | +#elif defined(HOST_IA64) | ||
| 532 | + { | ||
| 533 | + char name[256]; | ||
| 534 | + int type; | ||
| 535 | + int addend; | ||
| 536 | + for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | ||
| 537 | + if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | ||
| 538 | + sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; | ||
| 539 | + if (strstart(sym_name, "__op_param", &p)) { | ||
| 540 | + snprintf(name, sizeof(name), "param%s", p); | ||
| 541 | + } else { | ||
| 542 | + snprintf(name, sizeof(name), "(long)(&%s)", sym_name); | ||
| 543 | + } | ||
| 544 | + type = ELF64_R_TYPE(rel->r_info); | ||
| 545 | + addend = rel->r_addend; | ||
| 546 | + switch(type) { | ||
| 547 | + case R_IA64_LTOFF22: | ||
| 548 | + error("must implemnt R_IA64_LTOFF22 relocation"); | ||
| 549 | + case R_IA64_PCREL21B: | ||
| 550 | + error("must implemnt R_IA64_PCREL21B relocation"); | ||
| 551 | + default: | ||
| 552 | + error("unsupported ia64 relocation (%d)", type); | ||
| 553 | + } | ||
| 554 | + } | ||
| 555 | + } | ||
| 556 | + } | ||
| 467 | #else | 557 | #else |
| 468 | #error unsupported CPU | 558 | #error unsupported CPU |
| 469 | #endif | 559 | #endif |
| @@ -564,17 +654,17 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | @@ -564,17 +654,17 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | ||
| 564 | nb_relocs = sec->sh_size / sec->sh_entsize; | 654 | nb_relocs = sec->sh_size / sec->sh_entsize; |
| 565 | if (do_swap) { | 655 | if (do_swap) { |
| 566 | if (sec->sh_type == SHT_REL) { | 656 | if (sec->sh_type == SHT_REL) { |
| 567 | - Elf32_Rel *rel = relocs; | 657 | + ElfW(Rel) *rel = relocs; |
| 568 | for(j = 0, rel = relocs; j < nb_relocs; j++, rel++) { | 658 | for(j = 0, rel = relocs; j < nb_relocs; j++, rel++) { |
| 569 | - swab32s(&rel->r_offset); | ||
| 570 | - swab32s(&rel->r_info); | 659 | + swabls(&rel->r_offset); |
| 660 | + swabls(&rel->r_info); | ||
| 571 | } | 661 | } |
| 572 | } else { | 662 | } else { |
| 573 | - Elf32_Rela *rel = relocs; | 663 | + ElfW(Rela) *rel = relocs; |
| 574 | for(j = 0, rel = relocs; j < nb_relocs; j++, rel++) { | 664 | for(j = 0, rel = relocs; j < nb_relocs; j++, rel++) { |
| 575 | - swab32s(&rel->r_offset); | ||
| 576 | - swab32s(&rel->r_info); | ||
| 577 | - swab32s(&rel->r_addend); | 665 | + swabls(&rel->r_offset); |
| 666 | + swabls(&rel->r_info); | ||
| 667 | + swabls(&rel->r_addend); | ||
| 578 | } | 668 | } |
| 579 | } | 669 | } |
| 580 | } | 670 | } |
| @@ -590,7 +680,7 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | @@ -590,7 +680,7 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | ||
| 590 | symtab = load_data(fd, symtab_sec->sh_offset, symtab_sec->sh_size); | 680 | symtab = load_data(fd, symtab_sec->sh_offset, symtab_sec->sh_size); |
| 591 | strtab = load_data(fd, strtab_sec->sh_offset, strtab_sec->sh_size); | 681 | strtab = load_data(fd, strtab_sec->sh_offset, strtab_sec->sh_size); |
| 592 | 682 | ||
| 593 | - nb_syms = symtab_sec->sh_size / sizeof(Elf32_Sym); | 683 | + nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym)); |
| 594 | if (do_swap) { | 684 | if (do_swap) { |
| 595 | for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { | 685 | for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { |
| 596 | swab32s(&sym->st_name); | 686 | swab32s(&sym->st_name); |
| @@ -612,6 +702,9 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | @@ -612,6 +702,9 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | ||
| 612 | } | 702 | } |
| 613 | } else { | 703 | } else { |
| 614 | /* generate big code generation switch */ | 704 | /* generate big code generation switch */ |
| 705 | +#ifdef HOST_ALPHA | ||
| 706 | + fprintf(outfile, "register long gp asm(\"%%$29\");\n"); | ||
| 707 | +#endif | ||
| 615 | fprintf(outfile, | 708 | fprintf(outfile, |
| 616 | "int dyngen_code(uint8_t *gen_code_buf,\n" | 709 | "int dyngen_code(uint8_t *gen_code_buf,\n" |
| 617 | " const uint16_t *opc_buf, const uint32_t *opparam_buf)\n" | 710 | " const uint16_t *opc_buf, const uint32_t *opparam_buf)\n" |
| @@ -660,6 +753,14 @@ fprintf(outfile, | @@ -660,6 +753,14 @@ fprintf(outfile, | ||
| 660 | case EM_S390: | 753 | case EM_S390: |
| 661 | fprintf(outfile, "*((uint16_t *)gen_code_ptr)++ = 0x07fe; /* br %%r14 */\n"); | 754 | fprintf(outfile, "*((uint16_t *)gen_code_ptr)++ = 0x07fe; /* br %%r14 */\n"); |
| 662 | break; | 755 | break; |
| 756 | + case EM_ALPHA: | ||
| 757 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x6bfa8001; /* ret */\n"); | ||
| 758 | + break; | ||
| 759 | + case EM_IA_64: | ||
| 760 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x00840008; /* br.ret.sptk.many b0;; */\n"); | ||
| 761 | + break; | ||
| 762 | + default: | ||
| 763 | + error("unknown ELF architecture"); | ||
| 663 | } | 764 | } |
| 664 | 765 | ||
| 665 | fprintf(outfile, "return gen_code_ptr - gen_code_buf;\n"); | 766 | fprintf(outfile, "return gen_code_ptr - gen_code_buf;\n"); |
translate-i386.c
| @@ -53,6 +53,12 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop) | @@ -53,6 +53,12 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop) | ||
| 53 | } | 53 | } |
| 54 | #endif | 54 | #endif |
| 55 | 55 | ||
| 56 | +#ifdef __ia64__ | ||
| 57 | +static inline void flush_icache_range(unsigned long start, unsigned long stop) | ||
| 58 | +{ | ||
| 59 | +} | ||
| 60 | +#endif | ||
| 61 | + | ||
| 56 | #ifdef __powerpc__ | 62 | #ifdef __powerpc__ |
| 57 | 63 | ||
| 58 | #define MIN_CACHE_LINE_SIZE 8 /* conservative value */ | 64 | #define MIN_CACHE_LINE_SIZE 8 /* conservative value */ |
| @@ -76,6 +82,13 @@ static void inline flush_icache_range(unsigned long start, unsigned long stop) | @@ -76,6 +82,13 @@ static void inline flush_icache_range(unsigned long start, unsigned long stop) | ||
| 76 | } | 82 | } |
| 77 | #endif | 83 | #endif |
| 78 | 84 | ||
| 85 | +#ifdef __alpha__ | ||
| 86 | +static inline void flush_icache_range(unsigned long start, unsigned long stop) | ||
| 87 | +{ | ||
| 88 | + asm ("imb"); | ||
| 89 | +} | ||
| 90 | +#endif | ||
| 91 | + | ||
| 79 | extern FILE *logfile; | 92 | extern FILE *logfile; |
| 80 | extern int loglevel; | 93 | extern int loglevel; |
| 81 | 94 |