Revision 932a6909

b/exec-all.h
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");
b/tcg/ppc/tcg-target.c
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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" } },
b/tcg/tcg.h
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

Also available in: Unified diff