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,12 +187,23 @@ extern int code_gen_max_blocks; | ||
| 187 | static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr) | 187 | static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr) |
| 188 | { | 188 | { |
| 189 | uint32_t val, *ptr; | 189 | uint32_t val, *ptr; |
| 190 | + long disp = addr - jmp_addr; | ||
| 190 | 191 | ||
| 191 | - /* patch the branch destination */ | ||
| 192 | ptr = (uint32_t *)jmp_addr; | 192 | ptr = (uint32_t *)jmp_addr; |
| 193 | val = *ptr; | 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 | /* flush icache */ | 207 | /* flush icache */ |
| 197 | asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory"); | 208 | asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory"); |
| 198 | asm volatile ("sync" : : : "memory"); | 209 | asm volatile ("sync" : : : "memory"); |
tcg/ppc/tcg-target.c
| @@ -24,9 +24,6 @@ | @@ -24,9 +24,6 @@ | ||
| 24 | 24 | ||
| 25 | static uint8_t *tb_ret_addr; | 25 | static uint8_t *tb_ret_addr; |
| 26 | 26 | ||
| 27 | -#define TCG_CT_PC14 0x100 | ||
| 28 | -#define TCG_CT_PC24 0x200 | ||
| 29 | - | ||
| 30 | #define FAST_PATH | 27 | #define FAST_PATH |
| 31 | #if TARGET_PHYS_ADDR_BITS <= 32 | 28 | #if TARGET_PHYS_ADDR_BITS <= 32 |
| 32 | #define ADDEND_OFFSET 0 | 29 | #define ADDEND_OFFSET 0 |
| @@ -140,7 +137,13 @@ static const int tcg_target_callee_save_regs[] = { | @@ -140,7 +137,13 @@ static const int tcg_target_callee_save_regs[] = { | ||
| 140 | 137 | ||
| 141 | static uint32_t reloc_pc24_val (void *pc, tcg_target_long target) | 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 | static void reloc_pc24 (void *pc, tcg_target_long target) | 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,7 +154,13 @@ static void reloc_pc24 (void *pc, tcg_target_long target) | ||
| 151 | 154 | ||
| 152 | static uint16_t reloc_pc14_val (void *pc, tcg_target_long target) | 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 | static void reloc_pc14 (void *pc, tcg_target_long target) | 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,12 +227,6 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) | ||
| 218 | tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6); | 227 | tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6); |
| 219 | tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7); | 228 | tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7); |
| 220 | break; | 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 | default: | 230 | default: |
| 228 | return -1; | 231 | return -1; |
| 229 | } | 232 | } |
| @@ -241,13 +244,6 @@ static int tcg_target_const_match(tcg_target_long val, | @@ -241,13 +244,6 @@ static int tcg_target_const_match(tcg_target_long val, | ||
| 241 | ct = arg_ct->ct; | 244 | ct = arg_ct->ct; |
| 242 | if (ct & TCG_CT_CONST) | 245 | if (ct & TCG_CT_CONST) |
| 243 | return 1; | 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 | return 0; | 247 | return 0; |
| 252 | } | 248 | } |
| 253 | 249 | ||
| @@ -407,6 +403,20 @@ static void tcg_out_ldst (TCGContext *s, int ret, int addr, | @@ -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 | #if defined(CONFIG_SOFTMMU) | 420 | #if defined(CONFIG_SOFTMMU) |
| 411 | extern void __ldb_mmu(void); | 421 | extern void __ldb_mmu(void); |
| 412 | extern void __ldw_mmu(void); | 422 | extern void __ldw_mmu(void); |
| @@ -507,8 +517,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) | @@ -507,8 +517,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) | ||
| 507 | tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index); | 517 | tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index); |
| 508 | #endif | 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 | switch (opc) { | 521 | switch (opc) { |
| 513 | case 0|4: | 522 | case 0|4: |
| 514 | tcg_out32 (s, EXTSB | RA (data_reg) | RS (3)); | 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,8 +736,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) | ||
| 727 | ir++; | 736 | ir++; |
| 728 | 737 | ||
| 729 | tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index); | 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 | label2_ptr = s->code_ptr; | 740 | label2_ptr = s->code_ptr; |
| 733 | tcg_out32 (s, B); | 741 | tcg_out32 (s, B); |
| 734 | 742 | ||
| @@ -932,6 +940,12 @@ static void tcg_out_brcond(TCGContext *s, int cond, | @@ -932,6 +940,12 @@ static void tcg_out_brcond(TCGContext *s, int cond, | ||
| 932 | } | 940 | } |
| 933 | 941 | ||
| 934 | if (l->has_value) { | 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 | tcg_out32 (s, tcg_to_bc[cond] | reloc_pc14_val (s->code_ptr, | 949 | tcg_out32 (s, tcg_to_bc[cond] | reloc_pc14_val (s->code_ptr, |
| 936 | l->u.value)); | 950 | l->u.value)); |
| 937 | } | 951 | } |
| @@ -1010,14 +1024,31 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | @@ -1010,14 +1024,31 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 1010 | switch (opc) { | 1024 | switch (opc) { |
| 1011 | case INDEX_op_exit_tb: | 1025 | case INDEX_op_exit_tb: |
| 1012 | tcg_out_movi (s, TCG_TYPE_I32, TCG_REG_R3, args[0]); | 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 | break; | 1028 | break; |
| 1015 | case INDEX_op_goto_tb: | 1029 | case INDEX_op_goto_tb: |
| 1016 | if (s->tb_jmp_offset) { | 1030 | if (s->tb_jmp_offset) { |
| 1017 | /* direct jump method */ | 1031 | /* direct jump method */ |
| 1032 | + uint32_t val; | ||
| 1033 | + uint16_t *p; | ||
| 1034 | + | ||
| 1018 | s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; | 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 | tcg_abort (); | 1052 | tcg_abort (); |
| 1022 | } | 1053 | } |
| 1023 | s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; | 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,7 +1058,7 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 1027 | TCGLabel *l = &s->labels[args[0]]; | 1058 | TCGLabel *l = &s->labels[args[0]]; |
| 1028 | 1059 | ||
| 1029 | if (l->has_value) { | 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 | else { | 1063 | else { |
| 1033 | tcg_out32 (s, B); | 1064 | tcg_out32 (s, B); |
| @@ -1037,7 +1068,7 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | @@ -1037,7 +1068,7 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 1037 | break; | 1068 | break; |
| 1038 | case INDEX_op_call: | 1069 | case INDEX_op_call: |
| 1039 | if (const_args[0]) { | 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 | else { | 1073 | else { |
| 1043 | tcg_out32 (s, MTSPR | RS (args[0]) | LR); | 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,7 +1077,7 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 1046 | break; | 1077 | break; |
| 1047 | case INDEX_op_jmp: | 1078 | case INDEX_op_jmp: |
| 1048 | if (const_args[0]) { | 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 | else { | 1082 | else { |
| 1052 | tcg_out32 (s, MTSPR | RS (args[0]) | CTR); | 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,7 +1153,8 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 1122 | if (const_args[2]) { | 1153 | if (const_args[2]) { |
| 1123 | if (args[2]) { | 1154 | if (args[2]) { |
| 1124 | if (args[2] & 0xffff) { | 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 | if (args[2] >> 16) | 1158 | if (args[2] >> 16) |
| 1127 | tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0]) | 1159 | tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0]) |
| 1128 | | ((args[2] >> 16) & 0xffff)); | 1160 | | ((args[2] >> 16) & 0xffff)); |
| @@ -1338,8 +1370,8 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | @@ -1338,8 +1370,8 @@ static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, | ||
| 1338 | static const TCGTargetOpDef ppc_op_defs[] = { | 1370 | static const TCGTargetOpDef ppc_op_defs[] = { |
| 1339 | { INDEX_op_exit_tb, { } }, | 1371 | { INDEX_op_exit_tb, { } }, |
| 1340 | { INDEX_op_goto_tb, { } }, | 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 | { INDEX_op_br, { } }, | 1375 | { INDEX_op_br, { } }, |
| 1344 | 1376 | ||
| 1345 | { INDEX_op_mov_i32, { "r", "r" } }, | 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,4 +410,9 @@ uint64_t tcg_helper_divu_i64(uint64_t arg1, uint64_t arg2); | ||
| 410 | uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2); | 410 | uint64_t tcg_helper_remu_i64(uint64_t arg1, uint64_t arg2); |
| 411 | 411 | ||
| 412 | extern uint8_t code_gen_prologue[]; | 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 | #define tcg_qemu_tb_exec(tb_ptr) ((long REGPARM (*)(void *))code_gen_prologue)(tb_ptr) | 417 | #define tcg_qemu_tb_exec(tb_ptr) ((long REGPARM (*)(void *))code_gen_prologue)(tb_ptr) |
| 418 | +#endif |