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 | ... | ... |