Commit d19893dab57d29507ebec946f822a5894e873863
1 parent
2521d698
extracted generic code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@242 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
176 additions
and
233 deletions
translate-i386.c
| ... | ... | @@ -25,97 +25,13 @@ |
| 25 | 25 | #include <signal.h> |
| 26 | 26 | #include <assert.h> |
| 27 | 27 | |
| 28 | -#include "disas.h" | |
| 29 | - | |
| 30 | -#define DEBUG_DISAS | |
| 31 | - | |
| 32 | -#define IN_OP_I386 | |
| 33 | 28 | #include "cpu-i386.h" |
| 34 | 29 | #include "exec.h" |
| 30 | +#include "disas.h" | |
| 35 | 31 | |
| 36 | 32 | /* XXX: move that elsewhere */ |
| 37 | 33 | static uint16_t *gen_opc_ptr; |
| 38 | 34 | static uint32_t *gen_opparam_ptr; |
| 39 | -int __op_param1, __op_param2, __op_param3; | |
| 40 | -#ifdef USE_DIRECT_JUMP | |
| 41 | -int __op_jmp0, __op_jmp1; | |
| 42 | -#endif | |
| 43 | - | |
| 44 | -#ifdef __i386__ | |
| 45 | -static inline void flush_icache_range(unsigned long start, unsigned long stop) | |
| 46 | -{ | |
| 47 | -} | |
| 48 | -#endif | |
| 49 | - | |
| 50 | -#ifdef __s390__ | |
| 51 | -static inline void flush_icache_range(unsigned long start, unsigned long stop) | |
| 52 | -{ | |
| 53 | -} | |
| 54 | -#endif | |
| 55 | - | |
| 56 | -#ifdef __ia64__ | |
| 57 | -static inline void flush_icache_range(unsigned long start, unsigned long stop) | |
| 58 | -{ | |
| 59 | -} | |
| 60 | -#endif | |
| 61 | - | |
| 62 | -#ifdef __powerpc__ | |
| 63 | - | |
| 64 | -#define MIN_CACHE_LINE_SIZE 8 /* conservative value */ | |
| 65 | - | |
| 66 | -static void inline flush_icache_range(unsigned long start, unsigned long stop) | |
| 67 | -{ | |
| 68 | - unsigned long p; | |
| 69 | - | |
| 70 | - p = start & ~(MIN_CACHE_LINE_SIZE - 1); | |
| 71 | - stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1); | |
| 72 | - | |
| 73 | - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { | |
| 74 | - asm volatile ("dcbst 0,%0" : : "r"(p) : "memory"); | |
| 75 | - } | |
| 76 | - asm volatile ("sync" : : : "memory"); | |
| 77 | - for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { | |
| 78 | - asm volatile ("icbi 0,%0" : : "r"(p) : "memory"); | |
| 79 | - } | |
| 80 | - asm volatile ("sync" : : : "memory"); | |
| 81 | - asm volatile ("isync" : : : "memory"); | |
| 82 | -} | |
| 83 | -#endif | |
| 84 | - | |
| 85 | -#ifdef __alpha__ | |
| 86 | -static inline void flush_icache_range(unsigned long start, unsigned long stop) | |
| 87 | -{ | |
| 88 | - asm ("imb"); | |
| 89 | -} | |
| 90 | -#endif | |
| 91 | - | |
| 92 | -#ifdef __sparc__ | |
| 93 | - | |
| 94 | -static void inline flush_icache_range(unsigned long start, unsigned long stop) | |
| 95 | -{ | |
| 96 | - unsigned long p; | |
| 97 | - | |
| 98 | - p = start & ~(8UL - 1UL); | |
| 99 | - stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL); | |
| 100 | - | |
| 101 | - for (; p < stop; p += 8) | |
| 102 | - __asm__ __volatile__("flush\t%0" : : "r" (p)); | |
| 103 | -} | |
| 104 | - | |
| 105 | -#endif | |
| 106 | - | |
| 107 | -#ifdef __arm__ | |
| 108 | -static inline void flush_icache_range(unsigned long start, unsigned long stop) | |
| 109 | -{ | |
| 110 | - register unsigned long _beg __asm ("a1") = start; | |
| 111 | - register unsigned long _end __asm ("a2") = stop; | |
| 112 | - register unsigned long _flg __asm ("a3") = 0; | |
| 113 | - __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg)); | |
| 114 | -} | |
| 115 | -#endif | |
| 116 | - | |
| 117 | -extern FILE *logfile; | |
| 118 | -extern int loglevel; | |
| 119 | 35 | |
| 120 | 36 | #define PREFIX_REPZ 0x01 |
| 121 | 37 | #define PREFIX_REPNZ 0x02 |
| ... | ... | @@ -142,7 +58,7 @@ typedef struct DisasContext { |
| 142 | 58 | int cpl; |
| 143 | 59 | int iopl; |
| 144 | 60 | int tf; /* TF cpu flag */ |
| 145 | - TranslationBlock *tb; | |
| 61 | + struct TranslationBlock *tb; | |
| 146 | 62 | } DisasContext; |
| 147 | 63 | |
| 148 | 64 | /* i386 arith/logic operations */ |
| ... | ... | @@ -176,8 +92,7 @@ enum { |
| 176 | 92 | NB_OPS, |
| 177 | 93 | }; |
| 178 | 94 | |
| 179 | -#include "dyngen.h" | |
| 180 | -#include "op-i386.h" | |
| 95 | +#include "gen-op-i386.h" | |
| 181 | 96 | |
| 182 | 97 | /* operand size */ |
| 183 | 98 | enum { |
| ... | ... | @@ -3748,61 +3663,10 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len) |
| 3748 | 3663 | } |
| 3749 | 3664 | } |
| 3750 | 3665 | |
| 3751 | - | |
| 3752 | -#ifdef DEBUG_DISAS | |
| 3753 | -static const char *op_str[] = { | |
| 3754 | -#define DEF(s, n, copy_size) #s, | |
| 3755 | -#include "opc-i386.h" | |
| 3756 | -#undef DEF | |
| 3757 | -}; | |
| 3758 | - | |
| 3759 | -static uint8_t op_nb_args[] = { | |
| 3760 | -#define DEF(s, n, copy_size) n, | |
| 3761 | -#include "opc-i386.h" | |
| 3762 | -#undef DEF | |
| 3763 | -}; | |
| 3764 | - | |
| 3765 | -static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) | |
| 3766 | -{ | |
| 3767 | - const uint16_t *opc_ptr; | |
| 3768 | - const uint32_t *opparam_ptr; | |
| 3769 | - int c, n, i; | |
| 3770 | - | |
| 3771 | - opc_ptr = opc_buf; | |
| 3772 | - opparam_ptr = opparam_buf; | |
| 3773 | - for(;;) { | |
| 3774 | - c = *opc_ptr++; | |
| 3775 | - n = op_nb_args[c]; | |
| 3776 | - fprintf(logfile, "0x%04x: %s", | |
| 3777 | - (int)(opc_ptr - opc_buf - 1), op_str[c]); | |
| 3778 | - for(i = 0; i < n; i++) { | |
| 3779 | - fprintf(logfile, " 0x%x", opparam_ptr[i]); | |
| 3780 | - } | |
| 3781 | - fprintf(logfile, "\n"); | |
| 3782 | - if (c == INDEX_op_end) | |
| 3783 | - break; | |
| 3784 | - opparam_ptr += n; | |
| 3785 | - } | |
| 3786 | -} | |
| 3787 | - | |
| 3788 | -#endif | |
| 3789 | - | |
| 3790 | -/* XXX: make safe guess about sizes */ | |
| 3791 | -#define MAX_OP_PER_INSTR 32 | |
| 3792 | -#define OPC_BUF_SIZE 512 | |
| 3793 | -#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR) | |
| 3794 | - | |
| 3795 | -#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3) | |
| 3796 | - | |
| 3797 | -static uint16_t gen_opc_buf[OPC_BUF_SIZE]; | |
| 3798 | -static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; | |
| 3799 | -static uint32_t gen_opc_pc[OPC_BUF_SIZE]; | |
| 3800 | -static uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; | |
| 3801 | - | |
| 3802 | 3666 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for |
| 3803 | 3667 | basic block 'tb'. If search_pc is TRUE, also generate PC |
| 3804 | 3668 | information for each intermediate instruction. */ |
| 3805 | -static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) | |
| 3669 | +int gen_intermediate_code(TranslationBlock *tb, int search_pc) | |
| 3806 | 3670 | { |
| 3807 | 3671 | DisasContext dc1, *dc = &dc1; |
| 3808 | 3672 | uint8_t *pc_ptr; |
| ... | ... | @@ -3833,7 +3697,7 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) |
| 3833 | 3697 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
| 3834 | 3698 | gen_opparam_ptr = gen_opparam_buf; |
| 3835 | 3699 | |
| 3836 | - dc->is_jmp = 0; | |
| 3700 | + dc->is_jmp = DISAS_NEXT; | |
| 3837 | 3701 | pc_ptr = pc_start; |
| 3838 | 3702 | lj = -1; |
| 3839 | 3703 | do { |
| ... | ... | @@ -3865,10 +3729,10 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) |
| 3865 | 3729 | } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && |
| 3866 | 3730 | (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32)); |
| 3867 | 3731 | /* we must store the eflags state if it is not already done */ |
| 3868 | - if (dc->is_jmp != 3) { | |
| 3732 | + if (dc->is_jmp != DISAS_TB_JUMP) { | |
| 3869 | 3733 | if (dc->cc_op != CC_OP_DYNAMIC) |
| 3870 | 3734 | gen_op_set_cc_op(dc->cc_op); |
| 3871 | - if (dc->is_jmp != 1) { | |
| 3735 | + if (dc->is_jmp != DISAS_JUMP) { | |
| 3872 | 3736 | /* we add an additionnal jmp to update the simulated PC */ |
| 3873 | 3737 | gen_op_jmp_im(ret - (unsigned long)dc->cs_base); |
| 3874 | 3738 | } |
| ... | ... | @@ -3880,15 +3744,13 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) |
| 3880 | 3744 | /* indicate that the hash table must be used to find the next TB */ |
| 3881 | 3745 | gen_op_movl_T0_0(); |
| 3882 | 3746 | } |
| 3883 | - | |
| 3884 | 3747 | *gen_opc_ptr = INDEX_op_end; |
| 3885 | 3748 | |
| 3886 | 3749 | #ifdef DEBUG_DISAS |
| 3887 | 3750 | if (loglevel) { |
| 3888 | 3751 | fprintf(logfile, "----------------\n"); |
| 3889 | 3752 | fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); |
| 3890 | - disas(logfile, pc_start, pc_ptr - pc_start, | |
| 3891 | - dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086); | |
| 3753 | + disas(logfile, pc_start, pc_ptr - pc_start, 0, !dc->code32); | |
| 3892 | 3754 | fprintf(logfile, "\n"); |
| 3893 | 3755 | |
| 3894 | 3756 | fprintf(logfile, "OP:\n"); |
| ... | ... | @@ -3912,98 +3774,13 @@ static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc) |
| 3912 | 3774 | return 0; |
| 3913 | 3775 | } |
| 3914 | 3776 | |
| 3915 | - | |
| 3916 | -/* return non zero if the very first instruction is invalid so that | |
| 3917 | - the virtual CPU can trigger an exception. | |
| 3918 | - | |
| 3919 | - '*gen_code_size_ptr' contains the size of the generated code (host | |
| 3920 | - code). | |
| 3921 | -*/ | |
| 3922 | -int cpu_x86_gen_code(TranslationBlock *tb, | |
| 3923 | - int max_code_size, int *gen_code_size_ptr) | |
| 3924 | -{ | |
| 3925 | - uint8_t *gen_code_buf; | |
| 3926 | - int gen_code_size; | |
| 3927 | - | |
| 3928 | - if (gen_intermediate_code(tb, 0) < 0) | |
| 3929 | - return -1; | |
| 3930 | - | |
| 3931 | - /* generate machine code */ | |
| 3932 | - tb->tb_next_offset[0] = 0xffff; | |
| 3933 | - tb->tb_next_offset[1] = 0xffff; | |
| 3934 | - gen_code_buf = tb->tc_ptr; | |
| 3935 | - gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset, | |
| 3936 | -#ifdef USE_DIRECT_JUMP | |
| 3937 | - tb->tb_jmp_offset, | |
| 3938 | -#else | |
| 3939 | - NULL, | |
| 3940 | -#endif | |
| 3941 | - gen_opc_buf, gen_opparam_buf); | |
| 3942 | - flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size)); | |
| 3943 | - | |
| 3944 | - *gen_code_size_ptr = gen_code_size; | |
| 3945 | -#ifdef DEBUG_DISAS | |
| 3946 | - if (loglevel) { | |
| 3947 | - fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr); | |
| 3948 | - disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET); | |
| 3949 | - fprintf(logfile, "\n"); | |
| 3950 | - fflush(logfile); | |
| 3951 | - } | |
| 3952 | -#endif | |
| 3953 | - return 0; | |
| 3954 | -} | |
| 3955 | - | |
| 3956 | -static const unsigned short opc_copy_size[] = { | |
| 3957 | -#define DEF(s, n, copy_size) copy_size, | |
| 3958 | -#include "opc-i386.h" | |
| 3959 | -#undef DEF | |
| 3960 | -}; | |
| 3961 | - | |
| 3962 | -/* The simulated PC corresponding to | |
| 3963 | - 'searched_pc' in the generated code is searched. 0 is returned if | |
| 3964 | - found. *found_pc contains the found PC. | |
| 3965 | - */ | |
| 3966 | -int cpu_x86_search_pc(TranslationBlock *tb, | |
| 3967 | - uint32_t *found_pc, unsigned long searched_pc) | |
| 3968 | -{ | |
| 3969 | - int j, c; | |
| 3970 | - unsigned long tc_ptr; | |
| 3971 | - uint16_t *opc_ptr; | |
| 3972 | - | |
| 3973 | - if (gen_intermediate_code(tb, 1) < 0) | |
| 3974 | - return -1; | |
| 3975 | - | |
| 3976 | - /* find opc index corresponding to search_pc */ | |
| 3977 | - tc_ptr = (unsigned long)tb->tc_ptr; | |
| 3978 | - if (searched_pc < tc_ptr) | |
| 3979 | - return -1; | |
| 3980 | - j = 0; | |
| 3981 | - opc_ptr = gen_opc_buf; | |
| 3982 | - for(;;) { | |
| 3983 | - c = *opc_ptr; | |
| 3984 | - if (c == INDEX_op_end) | |
| 3985 | - return -1; | |
| 3986 | - tc_ptr += opc_copy_size[c]; | |
| 3987 | - if (searched_pc < tc_ptr) | |
| 3988 | - break; | |
| 3989 | - opc_ptr++; | |
| 3990 | - } | |
| 3991 | - j = opc_ptr - gen_opc_buf; | |
| 3992 | - /* now find start of instruction before */ | |
| 3993 | - while (gen_opc_instr_start[j] == 0) | |
| 3994 | - j--; | |
| 3995 | - *found_pc = gen_opc_pc[j]; | |
| 3996 | - return 0; | |
| 3997 | -} | |
| 3998 | - | |
| 3999 | - | |
| 4000 | 3777 | CPUX86State *cpu_x86_init(void) |
| 4001 | 3778 | { |
| 4002 | 3779 | CPUX86State *env; |
| 4003 | 3780 | int i; |
| 4004 | 3781 | static int inited; |
| 4005 | 3782 | |
| 4006 | - cpu_x86_tblocks_init(); | |
| 3783 | + cpu_exec_init(); | |
| 4007 | 3784 | |
| 4008 | 3785 | env = malloc(sizeof(CPUX86State)); |
| 4009 | 3786 | if (!env) |
| ... | ... | @@ -4020,7 +3797,6 @@ CPUX86State *cpu_x86_init(void) |
| 4020 | 3797 | if (!inited) { |
| 4021 | 3798 | inited = 1; |
| 4022 | 3799 | optimize_flags_init(); |
| 4023 | - page_init(); | |
| 4024 | 3800 | } |
| 4025 | 3801 | return env; |
| 4026 | 3802 | } | ... | ... |
translate.c
0 โ 100644
| 1 | +/* | |
| 2 | + * Host code generation | |
| 3 | + * | |
| 4 | + * Copyright (c) 2003 Fabrice Bellard | |
| 5 | + * | |
| 6 | + * This library is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU Lesser General Public | |
| 8 | + * License as published by the Free Software Foundation; either | |
| 9 | + * version 2 of the License, or (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This library is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 14 | + * Lesser General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public | |
| 17 | + * License along with this library; if not, write to the Free Software | |
| 18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | + */ | |
| 20 | +#include <stdarg.h> | |
| 21 | +#include <stdlib.h> | |
| 22 | +#include <stdio.h> | |
| 23 | +#include <string.h> | |
| 24 | +#include <inttypes.h> | |
| 25 | + | |
| 26 | +#include "config.h" | |
| 27 | +#define IN_OP_I386 | |
| 28 | +#include "cpu-" TARGET_ARCH ".h" | |
| 29 | +#include "exec.h" | |
| 30 | +#include "disas.h" | |
| 31 | + | |
| 32 | +enum { | |
| 33 | +#define DEF(s, n, copy_size) INDEX_op_ ## s, | |
| 34 | +#include "opc-" TARGET_ARCH ".h" | |
| 35 | +#undef DEF | |
| 36 | + NB_OPS, | |
| 37 | +}; | |
| 38 | + | |
| 39 | +#include "dyngen.h" | |
| 40 | +#include "op-" TARGET_ARCH ".h" | |
| 41 | + | |
| 42 | +uint16_t gen_opc_buf[OPC_BUF_SIZE]; | |
| 43 | +uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; | |
| 44 | +uint32_t gen_opc_pc[OPC_BUF_SIZE]; | |
| 45 | +uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; | |
| 46 | + | |
| 47 | + | |
| 48 | +#ifdef DEBUG_DISAS | |
| 49 | +static const char *op_str[] = { | |
| 50 | +#define DEF(s, n, copy_size) #s, | |
| 51 | +#include "opc-" TARGET_ARCH ".h" | |
| 52 | +#undef DEF | |
| 53 | +}; | |
| 54 | + | |
| 55 | +static uint8_t op_nb_args[] = { | |
| 56 | +#define DEF(s, n, copy_size) n, | |
| 57 | +#include "opc-" TARGET_ARCH ".h" | |
| 58 | +#undef DEF | |
| 59 | +}; | |
| 60 | + | |
| 61 | +void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) | |
| 62 | +{ | |
| 63 | + const uint16_t *opc_ptr; | |
| 64 | + const uint32_t *opparam_ptr; | |
| 65 | + int c, n, i; | |
| 66 | + | |
| 67 | + opc_ptr = opc_buf; | |
| 68 | + opparam_ptr = opparam_buf; | |
| 69 | + for(;;) { | |
| 70 | + c = *opc_ptr++; | |
| 71 | + n = op_nb_args[c]; | |
| 72 | + fprintf(logfile, "0x%04x: %s", | |
| 73 | + (int)(opc_ptr - opc_buf - 1), op_str[c]); | |
| 74 | + for(i = 0; i < n; i++) { | |
| 75 | + fprintf(logfile, " 0x%x", opparam_ptr[i]); | |
| 76 | + } | |
| 77 | + fprintf(logfile, "\n"); | |
| 78 | + if (c == INDEX_op_end) | |
| 79 | + break; | |
| 80 | + opparam_ptr += n; | |
| 81 | + } | |
| 82 | +} | |
| 83 | + | |
| 84 | +#endif | |
| 85 | + | |
| 86 | +/* return non zero if the very first instruction is invalid so that | |
| 87 | + the virtual CPU can trigger an exception. | |
| 88 | + | |
| 89 | + '*gen_code_size_ptr' contains the size of the generated code (host | |
| 90 | + code). | |
| 91 | +*/ | |
| 92 | +int cpu_gen_code(TranslationBlock *tb, | |
| 93 | + int max_code_size, int *gen_code_size_ptr) | |
| 94 | +{ | |
| 95 | + uint8_t *gen_code_buf; | |
| 96 | + int gen_code_size; | |
| 97 | + | |
| 98 | + if (gen_intermediate_code(tb, 0) < 0) | |
| 99 | + return -1; | |
| 100 | + | |
| 101 | + /* generate machine code */ | |
| 102 | + tb->tb_next_offset[0] = 0xffff; | |
| 103 | + tb->tb_next_offset[1] = 0xffff; | |
| 104 | + gen_code_buf = tb->tc_ptr; | |
| 105 | + gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset, | |
| 106 | +#ifdef USE_DIRECT_JUMP | |
| 107 | + tb->tb_jmp_offset, | |
| 108 | +#else | |
| 109 | + NULL, | |
| 110 | +#endif | |
| 111 | + gen_opc_buf, gen_opparam_buf); | |
| 112 | + *gen_code_size_ptr = gen_code_size; | |
| 113 | +#ifdef DEBUG_DISAS | |
| 114 | + if (loglevel) { | |
| 115 | + fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr); | |
| 116 | + disas(logfile, gen_code_buf, *gen_code_size_ptr, 1, 0); | |
| 117 | + fprintf(logfile, "\n"); | |
| 118 | + fflush(logfile); | |
| 119 | + } | |
| 120 | +#endif | |
| 121 | + return 0; | |
| 122 | +} | |
| 123 | + | |
| 124 | +static const unsigned short opc_copy_size[] = { | |
| 125 | +#define DEF(s, n, copy_size) copy_size, | |
| 126 | +#include "opc-i386.h" | |
| 127 | +#undef DEF | |
| 128 | +}; | |
| 129 | + | |
| 130 | +/* The simulated PC corresponding to | |
| 131 | + 'searched_pc' in the generated code is searched. 0 is returned if | |
| 132 | + found. *found_pc contains the found PC. | |
| 133 | + */ | |
| 134 | +int cpu_search_pc(TranslationBlock *tb, | |
| 135 | + uint32_t *found_pc, unsigned long searched_pc) | |
| 136 | +{ | |
| 137 | + int j, c; | |
| 138 | + unsigned long tc_ptr; | |
| 139 | + uint16_t *opc_ptr; | |
| 140 | + | |
| 141 | + if (gen_intermediate_code(tb, 1) < 0) | |
| 142 | + return -1; | |
| 143 | + | |
| 144 | + /* find opc index corresponding to search_pc */ | |
| 145 | + tc_ptr = (unsigned long)tb->tc_ptr; | |
| 146 | + if (searched_pc < tc_ptr) | |
| 147 | + return -1; | |
| 148 | + j = 0; | |
| 149 | + opc_ptr = gen_opc_buf; | |
| 150 | + for(;;) { | |
| 151 | + c = *opc_ptr; | |
| 152 | + if (c == INDEX_op_end) | |
| 153 | + return -1; | |
| 154 | + tc_ptr += opc_copy_size[c]; | |
| 155 | + if (searched_pc < tc_ptr) | |
| 156 | + break; | |
| 157 | + opc_ptr++; | |
| 158 | + } | |
| 159 | + j = opc_ptr - gen_opc_buf; | |
| 160 | + /* now find start of instruction before */ | |
| 161 | + while (gen_opc_instr_start[j] == 0) | |
| 162 | + j--; | |
| 163 | + *found_pc = gen_opc_pc[j]; | |
| 164 | + return 0; | |
| 165 | +} | |
| 166 | + | |
| 167 | + | ... | ... |