Commit 74c95119f2bceb73c1695ffee08a934cddabe830

Authored by bellard
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 429 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
430 430 if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
431 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 433 #if defined(HOST_SPARC)
434 434 if (sym_name[0] == '.') {
435 435 fprintf(outfile,
... ... @@ -561,15 +561,17 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
561 561 for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
562 562 if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
563 563 int type;
564   - sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
565   -
  564 +
566 565 type = ELF64_R_TYPE(rel->r_info);
  566 + sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
567 567 switch (type) {
568 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 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 575 break;
574 576 case R_ALPHA_LITUSE:
575 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 582 correct for in-function jumps. */
581 583 break;
582 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 606 break;
588 607 default:
589 608 error("unsupported Alpha relocation (%d)", type);
... ... @@ -886,7 +905,24 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum)
886 905 } else {
887 906 /* generate big code generation switch */
888 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 926 #endif
891 927 fprintf(outfile,
892 928 "int dyngen_code(uint8_t *gen_code_buf,\n"
... ...
exec-i386.h
... ... @@ -105,7 +105,13 @@ register struct CPUX86State *env asm(&quot;r10&quot;);
105 105 register unsigned int T0 asm("$9");
106 106 register unsigned int T1 asm("$10");
107 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 115 #endif
110 116 #ifdef __ia64__
111 117 register unsigned int T0 asm("r24");
... ... @@ -165,10 +171,24 @@ register struct CPUX86State *env asm(&quot;r27&quot;);
165 171 #define FP_CONVERT (env->fp_convert)
166 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 187 extern int __op_param1, __op_param2, __op_param3;
169 188 #define PARAM1 ((long)(&__op_param1))
170 189 #define PARAM2 ((long)(&__op_param2))
171 190 #define PARAM3 ((long)(&__op_param3))
  191 +#endif
172 192  
173 193 #include "cpu-i386.h"
174 194  
... ...