summaryrefslogtreecommitdiff
path: root/dyngen.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-25 19:01:05 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-25 19:01:05 +0000
commit90426a4e2d1994026a3ca6fdc149f55730aa2b8a (patch)
tree90ad680ebb9dc6f83ff6a065a80850cd64f8e4e6 /dyngen.c
parent2662e13f683c5a315edb81e5418d41fd9536aef6 (diff)
downloadqemu-90426a4e2d1994026a3ca6fdc149f55730aa2b8a.tar.gz
ppc dyngen fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4585 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'dyngen.c')
-rw-r--r--dyngen.c64
1 files changed, 39 insertions, 25 deletions
diff --git a/dyngen.c b/dyngen.c
index f3b9638982..c38d12386f 100644
--- a/dyngen.c
+++ b/dyngen.c
@@ -1910,10 +1910,11 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
char relname[256];
int type;
int addend;
+ int is_label;
int reloc_offset;
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
if (rel->r_offset >= start_offset &&
- rel->r_offset < start_offset + copy_size) {
+ rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
reloc_offset = rel->r_offset - start_offset;
if (strstart(sym_name, "__op_jmp", &p)) {
@@ -1930,31 +1931,44 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
get_reloc_expr(relname, sizeof(relname), sym_name);
type = ELF32_R_TYPE(rel->r_info);
+ is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
addend = rel->r_addend;
- switch(type) {
- case R_PPC_ADDR32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
- reloc_offset, relname, addend);
- break;
- case R_PPC_ADDR16_LO:
- fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
- reloc_offset, relname, addend);
- break;
- case R_PPC_ADDR16_HI:
- fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
- reloc_offset, relname, addend);
- break;
- case R_PPC_ADDR16_HA:
- fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
- reloc_offset, relname, addend);
- break;
- case R_PPC_REL24:
- /* warning: must be at 32 MB distancy */
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
- reloc_offset, reloc_offset, relname, reloc_offset, addend);
- break;
- default:
- error("unsupported powerpc relocation (%d)", type);
+ if (is_label) {
+ switch (type) {
+ case R_PPC_REL24:
+ fprintf (outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
+ reloc_offset, type, relname, addend);
+ break;
+ default:
+ error ("unsupported ppc relocation (%d)", type);
+ }
+ }
+ else {
+ switch(type) {
+ case R_PPC_ADDR32:
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
+ reloc_offset, relname, addend);
+ break;
+ case R_PPC_ADDR16_LO:
+ fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
+ reloc_offset, relname, addend);
+ break;
+ case R_PPC_ADDR16_HI:
+ fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
+ reloc_offset, relname, addend);
+ break;
+ case R_PPC_ADDR16_HA:
+ fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
+ reloc_offset, relname, addend);
+ break;
+ case R_PPC_REL24:
+ /* warning: must be at 32 MB distancy */
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
+ reloc_offset, reloc_offset, relname, reloc_offset, addend);
+ break;
+ default:
+ error("unsupported powerpc relocation (%d)", type);
+ }
}
}
}