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 | ... | ... |