From 90426a4e2d1994026a3ca6fdc149f55730aa2b8a Mon Sep 17 00:00:00 2001 From: bellard Date: Sun, 25 May 2008 19:01:05 +0000 Subject: ppc dyngen fix (malc) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4585 c046a42c-6fe2-441c-8c8c-71466251a162 --- dyngen.c | 64 +++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 25 deletions(-) (limited to 'dyngen.c') diff --git a/dyngen.c b/dyngen.c index f3b9638..c38d123 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); + } } } } -- cgit v1.1