Commit 932a69096921c3091ef1ce2b93cc809eb6ec8027
1 parent
da260249
support of long calls for PPC (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4629 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
82 additions
and
34 deletions
exec-all.h
... | ... | @@ -187,12 +187,23 @@ extern int code_gen_max_blocks; |
187 | 187 | static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr) |
188 | 188 | { |
189 | 189 | uint32_t val, *ptr; |
190 | + long disp = addr - jmp_addr; | |
190 | 191 | |
191 | - /* patch the branch destination */ | |
192 | 192 | ptr = (uint32_t *)jmp_addr; |
193 | 193 | val = *ptr; |
194 | - val = (val & ~0x03fffffc) | ((addr - jmp_addr) & 0x03fffffc); | |
195 | - *ptr = val; | |
194 | + | |
195 | + 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; | |
202 | + } else { | |
203 | + /* patch the branch destination */ | |
204 | + val = (val & ~0x03fffffc) | (disp & 0x03fffffc); | |
205 | + *ptr = val; | |
206 | + } | |
196 | 207 | /* flush icache */ |
197 | 208 | asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory"); |
198 | 209 | asm volatile ("sync" : : : "memory"); | ... | ... |
tcg/ppc/tcg-target.c
... | ... | @@ -24,9 +24,6 @@ |
24 | 24 | |
25 | 25 | static uint8_t *tb_ret_addr; |
26 | 26 | |
27 | -#define TCG_CT_PC14 0x100 | |
28 | -#define TCG_CT_PC24 0x200 | |
29 | - | |
30 | 27 | #define FAST_PATH |
31 | 28 | #if TARGET_PHYS_ADDR_BITS <= 32 |
32 | 29 | #define ADDEND_OFFSET 0 |
... | ... | @@ -140,7 +137,13 @@ static const int tcg_target_callee_save_regs[] = { |
140 | 137 | |
141 | 138 | static uint32_t reloc_pc24_val (void *pc, tcg_target_long target) |
142 | 139 | { |
143 | - return (target - (tcg_target_long) pc) & 0x3fffffc; | |
140 | + tcg_target_long disp; | |
141 | + | |
142 | + disp = target - (tcg_target_long) pc; | |
143 | + if ((disp << 6) >> 6 != disp) | |
144 | + tcg_abort (); | |
145 | + | |
146 | + return disp & 0x3fffffc; | |
144 | 147 | } |
145 | 148 | |
146 | 149 | static void reloc_pc24 (void *pc, tcg_target_long target) |
... | ... | @@ -151,7 +154,13 @@ static void reloc_pc24 (void *pc, tcg_target_long target) |
151 | 154 | |
152 | 155 | static uint16_t reloc_pc14_val (void *pc, tcg_target_long target) |
153 | 156 | { |
154 | - return (target - (tcg_target_long) pc) & 0xfffc; | |
157 | + tcg_target_long disp; | |
158 | + | |
159 | + disp = target - (tcg_target_long) pc; | |
160 | + if (disp != (int16_t) disp) | |
161 | + tcg_abort (); | |
162 | + | |
163 | + return disp & 0xfffc; | |
155 | 164 | } |
156 | 165 | |
157 | 166 | static void reloc_pc14 (void *pc, tcg_target_long target) |
... | ... | @@ -218,12 +227,6 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) |
218 | 227 | tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6); |
219 | 228 | tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7); |
220 | 229 | break; |
221 | - case 'J': /* 24 bit displacement */ | |
222 | - ct->ct |= TCG_CT_PC24; | |
223 | - break; | |
224 | - case 'j': /* 16 bit displacement */ | |
225 | - ct->ct |= TCG_CT_PC14; | |
226 | - break; | |
227 | 230 | default: |
228 | 231 | return -1; |
229 | 232 | } |
... | ... | @@ -241,13 +244,6 @@ static int tcg_target_const_match(tcg_target_long val, |
241 | 244 | ct = arg_ct->ct; |
242 | 245 | if (ct & TCG_CT_CONST) |
243 | 246 | return 1; |
244 | - else if (ct & TCG_CT_PC14) { | |
245 | - return val == (int16_t) val; | |
246 | - } | |
247 | - else if (ct & TCG_CT_PC24) { | |
248 | - if (val < 0) return val > -0x800000; | |
249 | - return val < 0x7fffff; | |
250 | - } | |
251 | 247 | return 0; |
252 | 248 | } |
253 | 249 | |
... | ... | @@ -407,6 +403,20 @@ static void tcg_out_ldst (TCGContext *s, int ret, int addr, |
407 | 403 | } |
408 | 404 | } |
409 | 405 | |
406 | +static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target) | |
407 | +{ | |
408 | + tcg_target_long disp; | |
409 | + | |
410 | + disp = target - (tcg_target_long) s->code_ptr; | |
411 | + if ((disp << 6) >> 6 == disp) | |
412 | + tcg_out32 (s, B | disp | mask); | |
413 | + else { | |
414 | + tcg_out_movi (s, TCG_TYPE_I32, 0, (tcg_target_long) target); | |
415 | + tcg_out32 (s, MTSPR | RS (0) | CTR); | |
416 | + tcg_out32 (s, BCCTR | BO_ALWAYS | mask); | |
417 | + } | |
418 | +} | |
419 | + | |
410 | 420 | #if defined(CONFIG_SOFTMMU) |
411 | 421 | extern void __ldb_mmu(void); |
412 | 422 | extern void __ldw_mmu(void); |
... | ... | @@ -507,8 +517,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) |
507 | 517 | tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index); |
508 | 518 | #endif |
509 | 519 | |
510 | - tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, | |
511 | - (tcg_target_long) qemu_ld_helpers[s_bits]) | LK); | |
520 | + tcg_out_b (s, LK, (tcg_target_long) qemu_ld_helpers[s_bits]); | |
512 | 521 | switch (opc) { |
513 | 522 | case 0|4: |
514 | 523 | tcg_out32 (s, EXTSB | RA (data_reg) | RS (3)); |
... | ... | @@ -727,8 +736,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) |
727 | 736 | ir++; |
728 | 737 | |
729 | 738 | tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index); |
730 | - tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, | |
731 | - (tcg_target_long) qemu_st_helpers[opc]) | LK); | |
739 | + tcg_out_b (s, LK, (tcg_target_long) qemu_st_helpers[opc]); | |
732 | 740 | label2_ptr = s->code_ptr; |
733 | 741 | tcg_out32 (s, B); |
734 | 742 | |
... | ... | @@ -932,6 +940,12 @@ static void tcg_out_brcond(TCGContext *s, int cond, |
932 | 940 | } |
933 | 941 | |
934 | 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 | + | |
935 | 949 | tcg_out32 (s, tcg_to_bc[cond] | reloc_pc14_val (s->code_ptr, |
936 | 950 | l->u.value)); |
937 | 951 | } |
... | ... | @@ -1010,14 +1024,31 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
1010 | 1024 | switch (opc) { |
1011 | 1025 | case INDEX_op_exit_tb: |
1012 | 1026 | tcg_out_movi (s, TCG_TYPE_I32, TCG_REG_R3, args[0]); |
1013 | - tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, (tcg_target_long) tb_ret_addr)); | |
1027 | + tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr); | |
1014 | 1028 | break; |
1015 | 1029 | case INDEX_op_goto_tb: |
1016 | 1030 | if (s->tb_jmp_offset) { |
1017 | 1031 | /* direct jump method */ |
1032 | + uint32_t val; | |
1033 | + uint16_t *p; | |
1034 | + | |
1018 | 1035 | s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; |
1019 | - tcg_out32 (s, B | 4); | |
1020 | - } else { | |
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); | |
1050 | + } | |
1051 | + else { | |
1021 | 1052 | tcg_abort (); |
1022 | 1053 | } |
1023 | 1054 | s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; |
... | ... | @@ -1027,7 +1058,7 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
1027 | 1058 | TCGLabel *l = &s->labels[args[0]]; |
1028 | 1059 | |
1029 | 1060 | if (l->has_value) { |
1030 | - tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, l->u.value)); | |
1061 | + tcg_out_b (s, 0, l->u.value); | |
1031 | 1062 | } |
1032 | 1063 | else { |
1033 | 1064 | tcg_out32 (s, B); |
... | ... | @@ -1037,7 +1068,7 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
1037 | 1068 | break; |
1038 | 1069 | case INDEX_op_call: |
1039 | 1070 | if (const_args[0]) { |
1040 | - tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, args[0]) | LK); | |
1071 | + tcg_out_b (s, LK, args[0]); | |
1041 | 1072 | } |
1042 | 1073 | else { |
1043 | 1074 | tcg_out32 (s, MTSPR | RS (args[0]) | LR); |
... | ... | @@ -1046,7 +1077,7 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
1046 | 1077 | break; |
1047 | 1078 | case INDEX_op_jmp: |
1048 | 1079 | if (const_args[0]) { |
1049 | - tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, args[0])); | |
1080 | + tcg_out_b (s, 0, args[0]); | |
1050 | 1081 | } |
1051 | 1082 | else { |
1052 | 1083 | tcg_out32 (s, MTSPR | RS (args[0]) | CTR); |
... | ... | @@ -1122,7 +1153,8 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
1122 | 1153 | if (const_args[2]) { |
1123 | 1154 | if (args[2]) { |
1124 | 1155 | if (args[2] & 0xffff) { |
1125 | - tcg_out32 (s, ORI | RS (args[1]) | RA (args[0]) | (args[2] & 0xffff)); | |
1156 | + tcg_out32 (s, ORI | RS (args[1]) | RA (args[0]) | |
1157 | + | (args[2] & 0xffff)); | |
1126 | 1158 | if (args[2] >> 16) |
1127 | 1159 | tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0]) |
1128 | 1160 | | ((args[2] >> 16) & 0xffff)); |
... | ... | @@ -1338,8 +1370,8 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
1338 | 1370 | static const TCGTargetOpDef ppc_op_defs[] = { |
1339 | 1371 | { INDEX_op_exit_tb, { } }, |
1340 | 1372 | { INDEX_op_goto_tb, { } }, |
1341 | - { INDEX_op_call, { "rJ" } }, | |
1342 | - { INDEX_op_jmp, { "rJ" } }, | |
1373 | + { INDEX_op_call, { "ri" } }, | |
1374 | + { INDEX_op_jmp, { "ri" } }, | |
1343 | 1375 | { INDEX_op_br, { } }, |
1344 | 1376 | |
1345 | 1377 | { INDEX_op_mov_i32, { "r", "r" } }, | ... | ... |
tcg/tcg.h
... | ... | @@ -410,4 +410,9 @@ uint64_t tcg_helper_divu_i64(uint64_t arg1, uint64_t arg2); |
410 | 410 | uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2); |
411 | 411 | |
412 | 412 | extern uint8_t code_gen_prologue[]; |
413 | +#ifdef __powerpc__ | |
414 | +#define tcg_qemu_tb_exec(tb_ptr) \ | |
415 | + ((long REGPARM __attribute__ ((longcall)) (*)(void *))code_gen_prologue)(tb_ptr) | |
416 | +#else | |
413 | 417 | #define tcg_qemu_tb_exec(tb_ptr) ((long REGPARM (*)(void *))code_gen_prologue)(tb_ptr) |
418 | +#endif | ... | ... |