429 |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { |
430 |
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
431 |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
432 |
if (!strstart(sym_name, "__op_param", &p)) { |
if (*sym_name && !strstart(sym_name, "__op_param", &p)) { |
433 |
#if defined(HOST_SPARC) |
#if defined(HOST_SPARC) |
434 |
if (sym_name[0] == '.') { |
if (sym_name[0] == '.') { |
435 |
fprintf(outfile, |
fprintf(outfile, |
561 |
for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { |
for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { |
562 |
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
563 |
int type; |
int type; |
564 |
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; |
|
|
|
|
565 |
type = ELF64_R_TYPE(rel->r_info); |
type = ELF64_R_TYPE(rel->r_info); |
566 |
|
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; |
567 |
switch (type) { |
switch (type) { |
568 |
case R_ALPHA_GPDISP: |
case R_ALPHA_GPDISP: |
569 |
/* Instructions to set up the gp can be nopped, since we keep it current |
/* The gp is just 32 bit, and never changes, so it's easiest to emit it |
570 |
all the time. FIXME assert that target is really gp */ |
as an immediate instead of constructing it from the pv or ra. */ |
571 |
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = 0x2ffe0000; /* unop */\n", |
fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n", |
572 |
rel->r_offset - offset); |
rel->r_offset - offset); |
573 |
|
fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n", |
574 |
|
rel->r_offset - offset + rel->r_addend); |
575 |
break; |
break; |
576 |
case R_ALPHA_LITUSE: |
case R_ALPHA_LITUSE: |
577 |
/* jsr to literal hint. Could be used to optimize to bsr. Ignore for |
/* jsr to literal hint. Could be used to optimize to bsr. Ignore for |
582 |
correct for in-function jumps. */ |
correct for in-function jumps. */ |
583 |
break; |
break; |
584 |
case R_ALPHA_LITERAL: |
case R_ALPHA_LITERAL: |
585 |
/* Load a literal from the GOT relative to the gp. Need to patch the |
/* Load a literal from the GOT relative to the gp. Since there's only a |
586 |
16-bit immediate offset. */ |
single gp, nothing is to be done. */ |
587 |
fprintf(outfile, " *(int16_t *)(gen_code_ptr + %d) = gp - (long)(&%s);\n", |
break; |
588 |
rel->r_offset - offset, name); |
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); |
606 |
break; |
break; |
607 |
default: |
default: |
608 |
error("unsupported Alpha relocation (%d)", type); |
error("unsupported Alpha relocation (%d)", type); |
905 |
} else { |
} else { |
906 |
/* generate big code generation switch */ |
/* generate big code generation switch */ |
907 |
#ifdef HOST_ALPHA |
#ifdef HOST_ALPHA |
908 |
fprintf(outfile, "register long gp asm(\"%%$29\");\n"); |
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"); |
926 |
#endif |
#endif |
927 |
fprintf(outfile, |
fprintf(outfile, |
928 |
"int dyngen_code(uint8_t *gen_code_buf,\n" |
"int dyngen_code(uint8_t *gen_code_buf,\n" |