Commit 90426a4e2d1994026a3ca6fdc149f55730aa2b8a

Authored by bellard
1 parent 2662e13f

ppc dyngen fix (malc)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4585 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 39 additions and 25 deletions
dyngen.c
... ... @@ -1910,10 +1910,11 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
1910 1910 char relname[256];
1911 1911 int type;
1912 1912 int addend;
  1913 + int is_label;
1913 1914 int reloc_offset;
1914 1915 for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1915 1916 if (rel->r_offset >= start_offset &&
1916   - rel->r_offset < start_offset + copy_size) {
  1917 + rel->r_offset < start_offset + copy_size) {
1917 1918 sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1918 1919 reloc_offset = rel->r_offset - start_offset;
1919 1920 if (strstart(sym_name, "__op_jmp", &p)) {
... ... @@ -1930,31 +1931,44 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
1930 1931  
1931 1932 get_reloc_expr(relname, sizeof(relname), sym_name);
1932 1933 type = ELF32_R_TYPE(rel->r_info);
  1934 + is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1933 1935 addend = rel->r_addend;
1934   - switch(type) {
1935   - case R_PPC_ADDR32:
1936   - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1937   - reloc_offset, relname, addend);
1938   - break;
1939   - case R_PPC_ADDR16_LO:
1940   - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
1941   - reloc_offset, relname, addend);
1942   - break;
1943   - case R_PPC_ADDR16_HI:
1944   - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
1945   - reloc_offset, relname, addend);
1946   - break;
1947   - case R_PPC_ADDR16_HA:
1948   - fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
1949   - reloc_offset, relname, addend);
1950   - break;
1951   - case R_PPC_REL24:
1952   - /* warning: must be at 32 MB distancy */
1953   - fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
1954   - reloc_offset, reloc_offset, relname, reloc_offset, addend);
1955   - break;
1956   - default:
1957   - error("unsupported powerpc relocation (%d)", type);
  1936 + if (is_label) {
  1937 + switch (type) {
  1938 + case R_PPC_REL24:
  1939 + fprintf (outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
  1940 + reloc_offset, type, relname, addend);
  1941 + break;
  1942 + default:
  1943 + error ("unsupported ppc relocation (%d)", type);
  1944 + }
  1945 + }
  1946 + else {
  1947 + switch(type) {
  1948 + case R_PPC_ADDR32:
  1949 + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
  1950 + reloc_offset, relname, addend);
  1951 + break;
  1952 + case R_PPC_ADDR16_LO:
  1953 + fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
  1954 + reloc_offset, relname, addend);
  1955 + break;
  1956 + case R_PPC_ADDR16_HI:
  1957 + fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
  1958 + reloc_offset, relname, addend);
  1959 + break;
  1960 + case R_PPC_ADDR16_HA:
  1961 + fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
  1962 + reloc_offset, relname, addend);
  1963 + break;
  1964 + case R_PPC_REL24:
  1965 + /* warning: must be at 32 MB distancy */
  1966 + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
  1967 + reloc_offset, reloc_offset, relname, reloc_offset, addend);
  1968 + break;
  1969 + default:
  1970 + error("unsupported powerpc relocation (%d)", type);
  1971 + }
1958 1972 }
1959 1973 }
1960 1974 }
... ...