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 | 58 | #define elf_check_arch(x) ((x) == EM_ALPHA) |
| 59 | 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 | 68 | #else |
| 62 | 69 | #error unsupported CPU - please update the code |
| 63 | 70 | #endif |
| 64 | 71 | |
| 72 | +#include "elf.h" | |
| 73 | + | |
| 65 | 74 | #if ELF_CLASS == ELFCLASS32 |
| 66 | 75 | typedef int32_t host_long; |
| 67 | 76 | typedef uint32_t host_ulong; |
| 77 | +#define swabls(x) swab32s(x) | |
| 68 | 78 | #else |
| 69 | 79 | typedef int64_t host_long; |
| 70 | 80 | typedef uint64_t host_ulong; |
| 81 | +#define swabls(x) swab64s(x) | |
| 71 | 82 | #endif |
| 72 | 83 | |
| 73 | -#include "elf.h" | |
| 74 | - | |
| 75 | 84 | #include "thunk.h" |
| 76 | 85 | |
| 77 | 86 | /* all dynamically generated functions begin with this code */ |
| ... | ... | @@ -104,12 +113,6 @@ void swab64s(uint64_t *p) |
| 104 | 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 | 116 | void elf_swap_ehdr(struct elfhdr *h) |
| 114 | 117 | { |
| 115 | 118 | swab16s(&h->e_type); /* Object file type */ |
| ... | ... | @@ -187,7 +190,7 @@ void put32(uint32_t *p, uint32_t val) |
| 187 | 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 | 195 | va_list ap; |
| 193 | 196 | va_start(ap, fmt); |
| ... | ... | @@ -295,10 +298,36 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
| 295 | 298 | if (p == p_start) |
| 296 | 299 | error("empty code for %s", name); |
| 297 | 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 | 302 | copy_size = p - p_start; |
| 300 | 303 | } |
| 301 | 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 | 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 | 373 | |
| 345 | 374 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 346 | 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 | 377 | if (!strstart(sym_name, "__op_param", &p)) { |
| 349 | 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 | 393 | int addend; |
| 365 | 394 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 366 | 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 | 397 | if (strstart(sym_name, "__op_param", &p)) { |
| 369 | 398 | snprintf(name, sizeof(name), "param%s", p); |
| 370 | 399 | } else { |
| ... | ... | @@ -394,7 +423,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
| 394 | 423 | int addend; |
| 395 | 424 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 396 | 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 | 427 | if (strstart(sym_name, "__op_param", &p)) { |
| 399 | 428 | snprintf(name, sizeof(name), "param%s", p); |
| 400 | 429 | } else { |
| ... | ... | @@ -437,7 +466,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
| 437 | 466 | int addend; |
| 438 | 467 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 439 | 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 | 470 | if (strstart(sym_name, "__op_param", &p)) { |
| 442 | 471 | snprintf(name, sizeof(name), "param%s", p); |
| 443 | 472 | } else { |
| ... | ... | @@ -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 | 557 | #else |
| 468 | 558 | #error unsupported CPU |
| 469 | 559 | #endif |
| ... | ... | @@ -564,17 +654,17 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) |
| 564 | 654 | nb_relocs = sec->sh_size / sec->sh_entsize; |
| 565 | 655 | if (do_swap) { |
| 566 | 656 | if (sec->sh_type == SHT_REL) { |
| 567 | - Elf32_Rel *rel = relocs; | |
| 657 | + ElfW(Rel) *rel = relocs; | |
| 568 | 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 | 662 | } else { |
| 573 | - Elf32_Rela *rel = relocs; | |
| 663 | + ElfW(Rela) *rel = relocs; | |
| 574 | 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 | 680 | symtab = load_data(fd, symtab_sec->sh_offset, symtab_sec->sh_size); |
| 591 | 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 | 684 | if (do_swap) { |
| 595 | 685 | for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { |
| 596 | 686 | swab32s(&sym->st_name); |
| ... | ... | @@ -612,6 +702,9 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) |
| 612 | 702 | } |
| 613 | 703 | } else { |
| 614 | 704 | /* generate big code generation switch */ |
| 705 | +#ifdef HOST_ALPHA | |
| 706 | + fprintf(outfile, "register long gp asm(\"%%$29\");\n"); | |
| 707 | +#endif | |
| 615 | 708 | fprintf(outfile, |
| 616 | 709 | "int dyngen_code(uint8_t *gen_code_buf,\n" |
| 617 | 710 | " const uint16_t *opc_buf, const uint32_t *opparam_buf)\n" |
| ... | ... | @@ -660,6 +753,14 @@ fprintf(outfile, |
| 660 | 753 | case EM_S390: |
| 661 | 754 | fprintf(outfile, "*((uint16_t *)gen_code_ptr)++ = 0x07fe; /* br %%r14 */\n"); |
| 662 | 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 | 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 | 53 | } |
| 54 | 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 | 62 | #ifdef __powerpc__ |
| 57 | 63 | |
| 58 | 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 | 82 | } |
| 77 | 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 | 92 | extern FILE *logfile; |
| 80 | 93 | extern int loglevel; |
| 81 | 94 | ... | ... |