Revision 0a878c47
b/exec-all.h | ||
---|---|---|
184 | 184 |
#if defined(USE_DIRECT_JUMP) |
185 | 185 |
|
186 | 186 |
#if defined(__powerpc__) |
187 |
static inline void flush_icache_range(unsigned long start, unsigned long stop); |
|
187 | 188 |
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr) |
188 | 189 |
{ |
189 |
uint32_t val, *ptr; |
|
190 |
/* This must be in concord with INDEX_op_goto_tb inside tcg_out_op */ |
|
191 |
uint32_t *ptr; |
|
190 | 192 |
long disp = addr - jmp_addr; |
193 |
unsigned long patch_size; |
|
191 | 194 |
|
192 | 195 |
ptr = (uint32_t *)jmp_addr; |
193 |
val = *ptr; |
|
194 | 196 |
|
195 | 197 |
if ((disp << 6) >> 6 != disp) { |
196 |
uint16_t *p1; |
|
197 |
|
|
198 |
p1 = (uint16_t *) ptr; |
|
199 |
*ptr = (val & ~0x03fffffc) | 4; |
|
200 |
p1[3] = addr >> 16; |
|
201 |
p1[5] = addr & 0xffff; |
|
198 |
ptr[0] = 0x3c000000 | (addr >> 16); /* lis 0,addr@ha */ |
|
199 |
ptr[1] = 0x60000000 | (addr & 0xffff); /* la 0,addr@l(0) */ |
|
200 |
ptr[2] = 0x7c0903a6; /* mtctr 0 */ |
|
201 |
ptr[3] = 0x4e800420; /* brctr */ |
|
202 |
patch_size = 16; |
|
202 | 203 |
} else { |
203 | 204 |
/* patch the branch destination */ |
204 |
val = (val & ~0x03fffffc) | (disp & 0x03fffffc); |
|
205 |
*ptr = val; |
|
205 |
if (disp != 16) { |
|
206 |
*ptr = 0x48000000 | (disp & 0x03fffffc); /* b disp */ |
|
207 |
patch_size = 4; |
|
208 |
} else { |
|
209 |
ptr[0] = 0x60000000; /* nop */ |
|
210 |
ptr[1] = 0x60000000; |
|
211 |
ptr[2] = 0x60000000; |
|
212 |
ptr[3] = 0x60000000; |
|
213 |
patch_size = 16; |
|
214 |
} |
|
206 | 215 |
} |
207 | 216 |
/* flush icache */ |
208 |
asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory"); |
|
209 |
asm volatile ("sync" : : : "memory"); |
|
210 |
asm volatile ("icbi 0,%0" : : "r"(ptr) : "memory"); |
|
211 |
asm volatile ("sync" : : : "memory"); |
|
212 |
asm volatile ("isync" : : : "memory"); |
|
217 |
flush_icache_range(jmp_addr, jmp_addr + patch_size); |
|
213 | 218 |
} |
214 | 219 |
#elif defined(__i386__) || defined(__x86_64__) |
215 | 220 |
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr) |
b/tcg/ppc/tcg-target.c | ||
---|---|---|
388 | 388 |
else { |
389 | 389 |
tcg_out32 (s, ADDIS | RT (ret) | RA (0) | ((arg >> 16) & 0xffff)); |
390 | 390 |
if (arg & 0xffff) |
391 |
tcg_out32 (s, ORI | RT (ret) | RA (ret) | (arg & 0xffff));
|
|
391 |
tcg_out32 (s, ORI | RS (ret) | RA (ret) | (arg & 0xffff));
|
|
392 | 392 |
} |
393 | 393 |
} |
394 | 394 |
|
... | ... | |
939 | 939 |
tcg_out32 (s, op | RA (arg1) | RB (arg2)); |
940 | 940 |
} |
941 | 941 |
|
942 |
if (l->has_value) { |
|
943 |
tcg_target_long disp; |
|
944 |
|
|
945 |
disp = (tcg_target_long) s->code_ptr - l->u.value; |
|
946 |
if (disp != (int16_t) disp) |
|
947 |
tcg_abort (); |
|
948 |
|
|
942 |
if (l->has_value) |
|
949 | 943 |
tcg_out32 (s, tcg_to_bc[cond] | reloc_pc14_val (s->code_ptr, |
950 | 944 |
l->u.value)); |
951 |
} |
|
952 | 945 |
else { |
953 |
tcg_out32 (s, tcg_to_bc[cond]); |
|
946 |
uint16_t val = *(uint16_t *) &s->code_ptr[2]; |
|
947 |
|
|
948 |
/* Thanks to Andrzej Zaborowski */ |
|
949 |
tcg_out32 (s, tcg_to_bc[cond] | (val & 0xfffc)); |
|
954 | 950 |
tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL14, label_index, 0); |
955 | 951 |
} |
956 | 952 |
} |
... | ... | |
1029 | 1025 |
case INDEX_op_goto_tb: |
1030 | 1026 |
if (s->tb_jmp_offset) { |
1031 | 1027 |
/* direct jump method */ |
1032 |
uint32_t val; |
|
1033 |
uint16_t *p; |
|
1034 | 1028 |
|
1035 | 1029 |
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; |
1036 |
/* Thanks to Andrzej Zaborowski for this */ |
|
1037 |
val = *(uint32_t *) s->code_ptr & 0x3fffffc; |
|
1038 |
|
|
1039 |
tcg_out32 (s, B | val); |
|
1040 |
|
|
1041 |
/* For branches outside of LL range |
|
1042 |
This must be in concord with tb_set_jmp_target1 */ |
|
1043 |
p = (uint16_t *) s->code_ptr; |
|
1044 |
p[0] = (ADDIS | RT (0) | RA (0)) >> 16; |
|
1045 |
p[2] = (ORI | RT (0) | RA (0)) >> 16; |
|
1046 |
s->code_ptr += 8; |
|
1047 |
|
|
1048 |
tcg_out32 (s, MTSPR | RS (0) | CTR); |
|
1049 |
tcg_out32 (s, BCCTR | BO_ALWAYS); |
|
1030 |
s->code_ptr += 16; |
|
1050 | 1031 |
} |
1051 | 1032 |
else { |
1052 | 1033 |
tcg_abort (); |
... | ... | |
1061 | 1042 |
tcg_out_b (s, 0, l->u.value); |
1062 | 1043 |
} |
1063 | 1044 |
else { |
1064 |
tcg_out32 (s, B); |
|
1045 |
uint32_t val = *(uint32_t *) s->code_ptr; |
|
1046 |
|
|
1047 |
/* Thanks to Andrzej Zaborowski */ |
|
1048 |
tcg_out32 (s, B | (val & 0x3fffffc)); |
|
1065 | 1049 |
tcg_out_reloc (s, s->code_ptr - 4, R_PPC_REL24, args[0], 0); |
1066 | 1050 |
} |
1067 | 1051 |
} |
... | ... | |
1222 | 1206 |
case INDEX_op_div2_i32: |
1223 | 1207 |
if (args[0] == args[2] || args[0] == args[3]) { |
1224 | 1208 |
tcg_out32 (s, DIVW | TAB (0, args[2], args[3])); |
1209 |
tcg_out32 (s, MTSPR | RS (0) | CTR); |
|
1225 | 1210 |
tcg_out32 (s, MULLW | TAB (0, 0, args[3])); |
1226 |
tcg_out32 (s, SUBF | TAB (0, 0, args[2])); |
|
1227 |
tcg_out32 (s, DIVW | TAB (args[0], args[2], args[3])); |
|
1228 |
tcg_out_mov (s, args[1], 0); |
|
1211 |
tcg_out32 (s, SUBF | TAB (args[1], 0, args[2])); |
|
1212 |
tcg_out32 (s, MFSPR | RT (args[0]) | CTR); |
|
1229 | 1213 |
} |
1230 | 1214 |
else { |
1231 | 1215 |
tcg_out32 (s, DIVW | TAB (args[0], args[2], args[3])); |
... | ... | |
1236 | 1220 |
case INDEX_op_divu2_i32: |
1237 | 1221 |
if (args[0] == args[2] || args[0] == args[3]) { |
1238 | 1222 |
tcg_out32 (s, DIVWU | TAB (0, args[2], args[3])); |
1223 |
tcg_out32 (s, MTSPR | RS (0) | CTR); |
|
1239 | 1224 |
tcg_out32 (s, MULLW | TAB (0, 0, args[3])); |
1240 |
tcg_out32 (s, SUBF | TAB (0, 0, args[2])); |
|
1241 |
tcg_out32 (s, DIVWU | TAB (args[0], args[2], args[3])); |
|
1242 |
tcg_out_mov (s, args[1], 0); |
|
1225 |
tcg_out32 (s, SUBF | TAB (args[1], 0, args[2])); |
|
1226 |
tcg_out32 (s, MFSPR | RT (args[0]) | CTR); |
|
1243 | 1227 |
} |
1244 | 1228 |
else { |
1245 | 1229 |
tcg_out32 (s, DIVWU | TAB (args[0], args[2], args[3])); |
Also available in: Unified diff