Commit 4cbb86e1c45acbad785490679e922344d5f144bf
1 parent
f513a41a
added JUMP_TB2 for a third basic block exit jump point
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@380 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
32 additions
and
8 deletions
exec.h
| ... | ... | @@ -108,7 +108,7 @@ typedef struct TranslationBlock { |
| 108 | 108 | the code of this one. */ |
| 109 | 109 | uint16_t tb_next_offset[2]; /* offset of original jump target */ |
| 110 | 110 | #ifdef USE_DIRECT_JUMP |
| 111 | - uint16_t tb_jmp_offset[2]; /* offset of jump instruction */ | |
| 111 | + uint16_t tb_jmp_offset[4]; /* offset of jump instruction */ | |
| 112 | 112 | #else |
| 113 | 113 | uint32_t tb_next[2]; /* address of jump generated code */ |
| 114 | 114 | #endif |
| ... | ... | @@ -160,18 +160,14 @@ static inline TranslationBlock *tb_find(TranslationBlock ***pptb, |
| 160 | 160 | |
| 161 | 161 | #if defined(__powerpc__) |
| 162 | 162 | |
| 163 | -static inline void tb_set_jmp_target(TranslationBlock *tb, | |
| 164 | - int n, unsigned long addr) | |
| 163 | +static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr) | |
| 165 | 164 | { |
| 166 | 165 | uint32_t val, *ptr; |
| 167 | - unsigned long offset; | |
| 168 | - | |
| 169 | - offset = (unsigned long)(tb->tc_ptr + tb->tb_jmp_offset[n]); | |
| 170 | 166 | |
| 171 | 167 | /* patch the branch destination */ |
| 172 | - ptr = (uint32_t *)offset; | |
| 168 | + ptr = (uint32_t *)jmp_addr; | |
| 173 | 169 | val = *ptr; |
| 174 | - val = (val & ~0x03fffffc) | ((addr - offset) & 0x03fffffc); | |
| 170 | + val = (val & ~0x03fffffc) | ((addr - jmp_addr) & 0x03fffffc); | |
| 175 | 171 | *ptr = val; |
| 176 | 172 | /* flush icache */ |
| 177 | 173 | asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory"); |
| ... | ... | @@ -181,6 +177,18 @@ static inline void tb_set_jmp_target(TranslationBlock *tb, |
| 181 | 177 | asm volatile ("isync" : : : "memory"); |
| 182 | 178 | } |
| 183 | 179 | |
| 180 | +static inline void tb_set_jmp_target(TranslationBlock *tb, | |
| 181 | + int n, unsigned long addr) | |
| 182 | +{ | |
| 183 | + unsigned long offset; | |
| 184 | + | |
| 185 | + offset = tb->tb_jmp_offset[n]; | |
| 186 | + tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr); | |
| 187 | + offset = tb->tb_jmp_offset[n + 2]; | |
| 188 | + if (offset != 0xffff) | |
| 189 | + tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr); | |
| 190 | +} | |
| 191 | + | |
| 184 | 192 | #else |
| 185 | 193 | |
| 186 | 194 | /* set the jump target */ |
| ... | ... | @@ -228,6 +236,11 @@ do {\ |
| 228 | 236 | EXIT_TB();\ |
| 229 | 237 | } while (0) |
| 230 | 238 | |
| 239 | +#define JUMP_TB2(opname, tbparam, n)\ | |
| 240 | +do {\ | |
| 241 | + asm volatile ("b __op_jmp%0\n" : : "i" (n + 2));\ | |
| 242 | +} while (0) | |
| 243 | + | |
| 231 | 244 | #else |
| 232 | 245 | |
| 233 | 246 | /* jump to next block operations (more portable code, does not need |
| ... | ... | @@ -244,6 +257,12 @@ dummy_label ## n:\ |
| 244 | 257 | EXIT_TB();\ |
| 245 | 258 | } while (0) |
| 246 | 259 | |
| 260 | +/* second jump to same destination 'n' */ | |
| 261 | +#define JUMP_TB2(opname, tbparam, n)\ | |
| 262 | +do {\ | |
| 263 | + goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\ | |
| 264 | +} while (0) | |
| 265 | + | |
| 247 | 266 | #endif |
| 248 | 267 | |
| 249 | 268 | /* physical memory access */ | ... | ... |
translate.c
| ... | ... | @@ -120,6 +120,11 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, |
| 120 | 120 | tb->tb_next_offset[0] = 0xffff; |
| 121 | 121 | tb->tb_next_offset[1] = 0xffff; |
| 122 | 122 | gen_code_buf = tb->tc_ptr; |
| 123 | +#ifdef USE_DIRECT_JUMP | |
| 124 | + /* the following two entries are optional (only used for string ops) */ | |
| 125 | + tb->tb_jmp_offset[2] = 0xffff; | |
| 126 | + tb->tb_jmp_offset[3] = 0xffff; | |
| 127 | +#endif | |
| 123 | 128 | gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset, |
| 124 | 129 | #ifdef USE_DIRECT_JUMP |
| 125 | 130 | tb->tb_jmp_offset, | ... | ... |