Commit 74c95119f2bceb73c1695ffee08a934cddabe830
1 parent
366c1b8b
Alpha fixes (Falk Hueffner)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@157 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
68 additions
and
12 deletions
dyngen.c
| @@ -429,7 +429,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -429,7 +429,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 429 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | 429 | for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
| 430 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 430 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
| 431 | sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; | 431 | sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
| 432 | - if (!strstart(sym_name, "__op_param", &p)) { | 432 | + if (*sym_name && !strstart(sym_name, "__op_param", &p)) { |
| 433 | #if defined(HOST_SPARC) | 433 | #if defined(HOST_SPARC) |
| 434 | if (sym_name[0] == '.') { | 434 | if (sym_name[0] == '.') { |
| 435 | fprintf(outfile, | 435 | fprintf(outfile, |
| @@ -561,15 +561,17 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -561,15 +561,17 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 561 | for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { | 561 | for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { |
| 562 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | 562 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
| 563 | int type; | 563 | int type; |
| 564 | - sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; | ||
| 565 | - | 564 | + |
| 566 | type = ELF64_R_TYPE(rel->r_info); | 565 | type = ELF64_R_TYPE(rel->r_info); |
| 566 | + sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; | ||
| 567 | switch (type) { | 567 | switch (type) { |
| 568 | case R_ALPHA_GPDISP: | 568 | case R_ALPHA_GPDISP: |
| 569 | - /* Instructions to set up the gp can be nopped, since we keep it current | ||
| 570 | - all the time. FIXME assert that target is really gp */ | ||
| 571 | - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = 0x2ffe0000; /* unop */\n", | 569 | + /* 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. */ | ||
| 571 | + fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n", | ||
| 572 | rel->r_offset - offset); | 572 | rel->r_offset - offset); |
| 573 | + fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n", | ||
| 574 | + rel->r_offset - offset + rel->r_addend); | ||
| 573 | break; | 575 | break; |
| 574 | case R_ALPHA_LITUSE: | 576 | case R_ALPHA_LITUSE: |
| 575 | /* jsr to literal hint. Could be used to optimize to bsr. Ignore for | 577 | /* jsr to literal hint. Could be used to optimize to bsr. Ignore for |
| @@ -580,10 +582,27 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -580,10 +582,27 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
| 580 | correct for in-function jumps. */ | 582 | correct for in-function jumps. */ |
| 581 | break; | 583 | break; |
| 582 | case R_ALPHA_LITERAL: | 584 | case R_ALPHA_LITERAL: |
| 583 | - /* Load a literal from the GOT relative to the gp. Need to patch the | ||
| 584 | - 16-bit immediate offset. */ | ||
| 585 | - fprintf(outfile, " *(int16_t *)(gen_code_ptr + %d) = gp - (long)(&%s);\n", | ||
| 586 | - rel->r_offset - offset, name); | 585 | + /* Load a literal from the GOT relative to the gp. Since there's only a |
| 586 | + single gp, nothing is to be done. */ | ||
| 587 | + break; | ||
| 588 | + case R_ALPHA_GPRELHIGH: | ||
| 589 | + /* Handle fake relocations against __op_param symbol. Need to emit the | ||
| 590 | + high part of the immediate value instead. Other symbols need no | ||
| 591 | + special treatment. */ | ||
| 592 | + if (strstart(sym_name, "__op_param", &p)) | ||
| 593 | + fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n", | ||
| 594 | + rel->r_offset - offset, p); | ||
| 595 | + break; | ||
| 596 | + case R_ALPHA_GPRELLOW: | ||
| 597 | + if (strstart(sym_name, "__op_param", &p)) | ||
| 598 | + fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n", | ||
| 599 | + rel->r_offset - offset, p); | ||
| 600 | + break; | ||
| 601 | + case R_ALPHA_BRSGP: | ||
| 602 | + /* PC-relative jump. Tweak offset to skip the two instructions that try to | ||
| 603 | + 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", | ||
| 605 | + rel->r_offset - offset, sym_name, rel->r_offset - offset); | ||
| 587 | break; | 606 | break; |
| 588 | default: | 607 | default: |
| 589 | error("unsupported Alpha relocation (%d)", type); | 608 | error("unsupported Alpha relocation (%d)", type); |
| @@ -886,7 +905,24 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | @@ -886,7 +905,24 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum) | ||
| 886 | } else { | 905 | } else { |
| 887 | /* generate big code generation switch */ | 906 | /* generate big code generation switch */ |
| 888 | #ifdef HOST_ALPHA | 907 | #ifdef HOST_ALPHA |
| 889 | - fprintf(outfile, "register long gp asm(\"%%$29\");\n"); | 908 | +fprintf(outfile, |
| 909 | +"register int gp asm(\"$29\");\n" | ||
| 910 | +"static inline void immediate_ldah(void *p, int val) {\n" | ||
| 911 | +" uint32_t *dest = p;\n" | ||
| 912 | +" long high = ((val >> 16) + ((val >> 15) & 1)) & 0xffff;\n" | ||
| 913 | +"\n" | ||
| 914 | +" *dest &= ~0xffff;\n" | ||
| 915 | +" *dest |= high;\n" | ||
| 916 | +" *dest |= 31 << 16;\n" | ||
| 917 | +"}\n" | ||
| 918 | +"static inline void immediate_lda(void *dest, int val) {\n" | ||
| 919 | +" *(uint16_t *) dest = val;\n" | ||
| 920 | +"}\n" | ||
| 921 | +"void fix_bsr(void *p, int offset) {\n" | ||
| 922 | +" uint32_t *dest = p;\n" | ||
| 923 | +" *dest &= ~((1 << 21) - 1);\n" | ||
| 924 | +" *dest |= (offset >> 2) & ((1 << 21) - 1);\n" | ||
| 925 | +"}\n"); | ||
| 890 | #endif | 926 | #endif |
| 891 | fprintf(outfile, | 927 | fprintf(outfile, |
| 892 | "int dyngen_code(uint8_t *gen_code_buf,\n" | 928 | "int dyngen_code(uint8_t *gen_code_buf,\n" |
exec-i386.h
| @@ -105,7 +105,13 @@ register struct CPUX86State *env asm("r10"); | @@ -105,7 +105,13 @@ register struct CPUX86State *env asm("r10"); | ||
| 105 | register unsigned int T0 asm("$9"); | 105 | register unsigned int T0 asm("$9"); |
| 106 | register unsigned int T1 asm("$10"); | 106 | register unsigned int T1 asm("$10"); |
| 107 | register unsigned int A0 asm("$11"); | 107 | register unsigned int A0 asm("$11"); |
| 108 | -register struct CPUX86State *env asm("$12"); | 108 | +register unsigned int EAX asm("$12"); |
| 109 | +register unsigned int ESP asm("$13"); | ||
| 110 | +register unsigned int EBP asm("$14"); | ||
| 111 | +register struct CPUX86State *env asm("$15"); | ||
| 112 | +#define reg_EAX | ||
| 113 | +#define reg_ESP | ||
| 114 | +#define reg_EBP | ||
| 109 | #endif | 115 | #endif |
| 110 | #ifdef __ia64__ | 116 | #ifdef __ia64__ |
| 111 | register unsigned int T0 asm("r24"); | 117 | register unsigned int T0 asm("r24"); |
| @@ -165,10 +171,24 @@ register struct CPUX86State *env asm("r27"); | @@ -165,10 +171,24 @@ register struct CPUX86State *env asm("r27"); | ||
| 165 | #define FP_CONVERT (env->fp_convert) | 171 | #define FP_CONVERT (env->fp_convert) |
| 166 | #endif | 172 | #endif |
| 167 | 173 | ||
| 174 | +#ifdef __alpha__ | ||
| 175 | +/* Suggested by Richard Henderson. This will result in code like | ||
| 176 | + ldah $0,__op_param1($29) !gprelhigh | ||
| 177 | + lda $0,__op_param1($0) !gprellow | ||
| 178 | + We can then conveniently change $29 to $31 and adapt the offsets to | ||
| 179 | + emit the appropriate constant. */ | ||
| 180 | +extern int __op_param1 __attribute__((visibility("hidden"))); | ||
| 181 | +extern int __op_param2 __attribute__((visibility("hidden"))); | ||
| 182 | +extern int __op_param3 __attribute__((visibility("hidden"))); | ||
| 183 | +#define PARAM1 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param1)); _r; }) | ||
| 184 | +#define PARAM2 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param2)); _r; }) | ||
| 185 | +#define PARAM3 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param3)); _r; }) | ||
| 186 | +#else | ||
| 168 | extern int __op_param1, __op_param2, __op_param3; | 187 | extern int __op_param1, __op_param2, __op_param3; |
| 169 | #define PARAM1 ((long)(&__op_param1)) | 188 | #define PARAM1 ((long)(&__op_param1)) |
| 170 | #define PARAM2 ((long)(&__op_param2)) | 189 | #define PARAM2 ((long)(&__op_param2)) |
| 171 | #define PARAM3 ((long)(&__op_param3)) | 190 | #define PARAM3 ((long)(&__op_param3)) |
| 191 | +#endif | ||
| 172 | 192 | ||
| 173 | #include "cpu-i386.h" | 193 | #include "cpu-i386.h" |
| 174 | 194 |