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