~ubuntu-branches/ubuntu/hardy/kvm/hardy-backports

« back to all changes in this revision

Viewing changes to qemu/dyngen.c

  • Committer: Bazaar Package Importer
  • Author(s): Soren Hansen
  • Date: 2008-02-26 13:10:57 UTC
  • mfrom: (1.1.18 upstream)
  • Revision ID: james.westby@ubuntu.com-20080226131057-s67x6l89mtjw1x9b
Tags: 1:62+dfsg-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1212
1212
 
1213
1213
#endif /* CONFIG_FORMAT_MACH */
1214
1214
 
1215
 
void get_reloc_expr(char *name, int name_size, const char *sym_name)
 
1215
/* return true if the expression is a label reference */
 
1216
int get_reloc_expr(char *name, int name_size, const char *sym_name)
1216
1217
{
1217
1218
    const char *p;
1218
1219
 
1219
1220
    if (strstart(sym_name, "__op_param", &p)) {
1220
1221
        snprintf(name, name_size, "param%s", p);
1221
1222
    } else if (strstart(sym_name, "__op_gen_label", &p)) {
1222
 
        snprintf(name, name_size, "gen_labels[param%s]", p);
 
1223
        snprintf(name, name_size, "param%s", p);
 
1224
        return 1;
1223
1225
    } else {
1224
1226
#ifdef HOST_SPARC
1225
1227
        if (sym_name[0] == '.')
1230
1232
#endif
1231
1233
            snprintf(name, name_size, "(long)(&%s)", sym_name);
1232
1234
    }
 
1235
    return 0;
1233
1236
}
1234
1237
 
1235
1238
#ifdef HOST_IA64
1846
1849
#if defined(HOST_I386)
1847
1850
            {
1848
1851
                char relname[256];
1849
 
                int type;
 
1852
                int type, is_label;
1850
1853
                int addend;
1851
1854
                int reloc_offset;
1852
1855
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1868
1871
                        continue;
1869
1872
                    }
1870
1873
 
1871
 
                    get_reloc_expr(relname, sizeof(relname), sym_name);
 
1874
                    is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1872
1875
                    addend = get32((uint32_t *)(text + rel->r_offset));
1873
1876
#ifdef CONFIG_FORMAT_ELF
1874
1877
                    type = ELF32_R_TYPE(rel->r_info);
1875
 
                    switch(type) {
1876
 
                    case R_386_32:
1877
 
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1878
 
                                reloc_offset, relname, addend);
1879
 
                        break;
1880
 
                    case R_386_PC32:
1881
 
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1882
 
                                reloc_offset, relname, reloc_offset, addend);
1883
 
                        break;
1884
 
                    default:
1885
 
                        error("unsupported i386 relocation (%d)", type);
 
1878
                    if (is_label) {
 
1879
                        switch(type) {
 
1880
                        case R_386_32:
 
1881
                        case R_386_PC32:
 
1882
                            fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
 
1883
                                    reloc_offset, type, relname, addend);
 
1884
                            break;
 
1885
                        default:
 
1886
                            error("unsupported i386 relocation (%d)", type);
 
1887
                        }
 
1888
                    } else {
 
1889
                        switch(type) {
 
1890
                        case R_386_32:
 
1891
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
 
1892
                                    reloc_offset, relname, addend);
 
1893
                            break;
 
1894
                        case R_386_PC32:
 
1895
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
 
1896
                                    reloc_offset, relname, reloc_offset, addend);
 
1897
                            break;
 
1898
                        default:
 
1899
                            error("unsupported i386 relocation (%d)", type);
 
1900
                        }
1886
1901
                    }
1887
1902
#elif defined(CONFIG_FORMAT_COFF)
1888
1903
                    {
1899
1914
                        }
1900
1915
                    }
1901
1916
                    type = rel->r_type;
1902
 
                    switch(type) {
1903
 
                    case DIR32:
1904
 
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
1905
 
                                reloc_offset, relname, addend);
1906
 
                        break;
1907
 
                    case DISP32:
1908
 
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
1909
 
                                reloc_offset, relname, reloc_offset, addend);
1910
 
                        break;
1911
 
                    default:
1912
 
                        error("unsupported i386 relocation (%d)", type);
 
1917
                    if (is_label) {
 
1918
/* TCG uses elf relocation constants */
 
1919
#define R_386_32        1
 
1920
#define R_386_PC32      2
 
1921
                        switch(type) {
 
1922
                        case DIR32:
 
1923
                            type = R_386_32;
 
1924
                            goto do_reloc;
 
1925
                        case DISP32:
 
1926
                            type = R_386_PC32;
 
1927
                            addend -= 4;
 
1928
                        do_reloc:
 
1929
                            fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
 
1930
                                    reloc_offset, type, relname, addend);
 
1931
                            break;
 
1932
                        default:
 
1933
                            error("unsupported i386 relocation (%d)", type);
 
1934
                        }
 
1935
                    } else {
 
1936
                        switch(type) {
 
1937
                        case DIR32:
 
1938
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
 
1939
                                    reloc_offset, relname, addend);
 
1940
                            break;
 
1941
                        case DISP32:
 
1942
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
 
1943
                                    reloc_offset, relname, reloc_offset, addend);
 
1944
                            break;
 
1945
                        default:
 
1946
                            error("unsupported i386 relocation (%d)", type);
 
1947
                        }
1913
1948
                    }
1914
1949
#else
1915
1950
#error unsupport object format
1920
1955
#elif defined(HOST_X86_64)
1921
1956
            {
1922
1957
                char relname[256];
1923
 
                int type;
 
1958
                int type, is_label;
1924
1959
                int addend;
1925
1960
                int reloc_offset;
1926
1961
                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
1927
1962
                if (rel->r_offset >= start_offset &&
1928
1963
                    rel->r_offset < start_offset + copy_size) {
1929
1964
                    sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
1930
 
                    get_reloc_expr(relname, sizeof(relname), sym_name);
 
1965
                    is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
1931
1966
                    type = ELF32_R_TYPE(rel->r_info);
1932
1967
                    addend = rel->r_addend;
1933
1968
                    reloc_offset = rel->r_offset - start_offset;
1934
 
                    switch(type) {
1935
 
                    case R_X86_64_32:
1936
 
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
1937
 
                                reloc_offset, relname, addend);
1938
 
                        break;
1939
 
                    case R_X86_64_32S:
1940
 
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
1941
 
                                reloc_offset, relname, addend);
1942
 
                        break;
1943
 
                    case R_X86_64_PC32:
1944
 
                        fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
1945
 
                                reloc_offset, relname, reloc_offset, addend);
1946
 
                        break;
1947
 
                    default:
1948
 
                        error("unsupported X86_64 relocation (%d)", type);
 
1969
                    if (is_label) {
 
1970
                        switch(type) {
 
1971
                        case R_X86_64_32:
 
1972
                        case R_X86_64_32S:
 
1973
                        case R_X86_64_PC32:
 
1974
                            fprintf(outfile, "    tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
 
1975
                                    reloc_offset, type, relname, addend);
 
1976
                            break;
 
1977
                        default:
 
1978
                            error("unsupported X86_64 relocation (%d)", type);
 
1979
                        }
 
1980
                    } else {
 
1981
                        switch(type) {
 
1982
                        case R_X86_64_32:
 
1983
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
 
1984
                                    reloc_offset, relname, addend);
 
1985
                            break;
 
1986
                        case R_X86_64_32S:
 
1987
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
 
1988
                                    reloc_offset, relname, addend);
 
1989
                            break;
 
1990
                        case R_X86_64_PC32:
 
1991
                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
 
1992
                                    reloc_offset, relname, reloc_offset, addend);
 
1993
                            break;
 
1994
                        default:
 
1995
                            error("unsupported X86_64 relocation (%d)", type);
 
1996
                        }
1949
1997
                    }
1950
1998
                }
1951
1999
                }
2639
2687
    EXE_SYM *sym;
2640
2688
 
2641
2689
    if (out_type == OUT_INDEX_OP) {
2642
 
        fprintf(outfile, "DEF(end, 0, 0)\n");
2643
 
        fprintf(outfile, "DEF(nop, 0, 0)\n");
2644
 
        fprintf(outfile, "DEF(nop1, 1, 0)\n");
2645
 
        fprintf(outfile, "DEF(nop2, 2, 0)\n");
2646
 
        fprintf(outfile, "DEF(nop3, 3, 0)\n");
2647
2690
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2648
2691
            const char *name;
2649
2692
            name = get_sym_name(sym);
2653
2696
        }
2654
2697
    } else if (out_type == OUT_GEN_OP) {
2655
2698
        /* generate gen_xxx functions */
2656
 
        fprintf(outfile, "#include \"dyngen-op.h\"\n");
2657
2699
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2658
2700
            const char *name;
2659
2701
            name = get_sym_name(sym);
2670
2712
        /* generate big code generation switch */
2671
2713
 
2672
2714
#ifdef HOST_ARM
 
2715
#error broken
2673
2716
        /* We need to know the size of all the ops so we can figure out when
2674
2717
           to emit constant pools.  This must be consistent with opc.h.  */
2675
2718
fprintf(outfile,
2690
2733
"};\n");
2691
2734
#endif
2692
2735
 
2693
 
fprintf(outfile,
2694
 
"int dyngen_code(uint8_t *gen_code_buf,\n"
2695
 
"                uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
2696
 
"                const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels)\n"
2697
 
"{\n"
2698
 
"    uint8_t *gen_code_ptr;\n"
2699
 
"    const uint16_t *opc_ptr;\n"
2700
 
"    const uint32_t *opparam_ptr;\n");
2701
 
 
2702
2736
#ifdef HOST_ARM
 
2737
#error broken
2703
2738
/* Arm is tricky because it uses constant pools for loading immediate values.
2704
2739
   We assume (and require) each function is code followed by a constant pool.
2705
2740
   All the ops are small so this should be ok.  For each op we figure
2789
2824
    }
2790
2825
#endif
2791
2826
 
2792
 
fprintf(outfile,
2793
 
"\n"
2794
 
"    gen_code_ptr = gen_code_buf;\n"
2795
 
"    opc_ptr = opc_buf;\n"
2796
 
"    opparam_ptr = opparam_buf;\n");
2797
 
 
2798
 
        /* Generate prologue, if needed. */
2799
 
 
2800
 
fprintf(outfile,
2801
 
"    for(;;) {\n");
2802
 
 
2803
2827
#ifdef HOST_ARM
 
2828
#error broken
2804
2829
/* Generate constant pool if needed */
2805
2830
fprintf(outfile,
2806
2831
"            if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
2813
2838
"            }\n");
2814
2839
#endif
2815
2840
 
2816
 
fprintf(outfile,
2817
 
"        switch(*opc_ptr++) {\n");
2818
 
 
2819
2841
        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
2820
2842
            const char *name;
2821
2843
            name = get_sym_name(sym);
2831
2853
                gen_code(name, sym->st_value, sym->st_size, outfile, 1);
2832
2854
            }
2833
2855
        }
2834
 
 
2835
 
fprintf(outfile,
2836
 
"        case INDEX_op_nop:\n"
2837
 
"            break;\n"
2838
 
"        case INDEX_op_nop1:\n"
2839
 
"            opparam_ptr++;\n"
2840
 
"            break;\n"
2841
 
"        case INDEX_op_nop2:\n"
2842
 
"            opparam_ptr += 2;\n"
2843
 
"            break;\n"
2844
 
"        case INDEX_op_nop3:\n"
2845
 
"            opparam_ptr += 3;\n"
2846
 
"            break;\n"
2847
 
"        default:\n"
2848
 
"            goto the_end;\n"
2849
 
"        }\n");
2850
 
 
2851
 
 
2852
 
fprintf(outfile,
2853
 
"    }\n"
2854
 
" the_end:\n"
2855
 
);
2856
 
#ifdef HOST_IA64
2857
 
    fprintf(outfile,
2858
 
            "    {\n"
2859
 
            "      extern char code_gen_buffer[];\n"
2860
 
            "      ia64_apply_fixes(&gen_code_ptr, ltoff_fixes, "
2861
 
            "(uint64_t) code_gen_buffer + 2*(1<<20), plt_fixes,\n\t\t\t"
2862
 
            "sizeof(plt_target)/sizeof(plt_target[0]),\n\t\t\t"
2863
 
            "plt_target, plt_offset);\n    }\n");
2864
 
#endif
2865
 
 
2866
 
/* generate some code patching */
2867
 
#ifdef HOST_ARM
2868
 
fprintf(outfile,
2869
 
"if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
2870
 
"    gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
2871
 
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
2872
 
#endif
2873
 
    /* flush instruction cache */
2874
 
    fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
2875
 
 
2876
 
    fprintf(outfile, "return gen_code_ptr -  gen_code_buf;\n");
2877
 
    fprintf(outfile, "}\n\n");
2878
 
 
2879
2856
    }
2880
2857
 
2881
2858
    return 0;