Revision 934814f1 target-arm/translate.c
b/target-arm/translate.c | ||
---|---|---|
3397 | 3397 |
VFP_DREG_D(rd, insn); |
3398 | 3398 |
else |
3399 | 3399 |
rd = VFP_SREG_D(insn); |
3400 |
if (s->thumb && rn == 15) { |
|
3401 |
addr = tcg_temp_new_i32(); |
|
3402 |
tcg_gen_movi_i32(addr, s->pc & ~2); |
|
3403 |
} else { |
|
3404 |
addr = load_reg(s, rn); |
|
3405 |
} |
|
3406 | 3400 |
if ((insn & 0x01200000) == 0x01000000) { |
3407 | 3401 |
/* Single load/store */ |
3408 | 3402 |
offset = (insn & 0xff) << 2; |
3409 | 3403 |
if ((insn & (1 << 23)) == 0) |
3410 | 3404 |
offset = -offset; |
3405 |
if (s->thumb && rn == 15) { |
|
3406 |
/* This is actually UNPREDICTABLE */ |
|
3407 |
addr = tcg_temp_new_i32(); |
|
3408 |
tcg_gen_movi_i32(addr, s->pc & ~2); |
|
3409 |
} else { |
|
3410 |
addr = load_reg(s, rn); |
|
3411 |
} |
|
3411 | 3412 |
tcg_gen_addi_i32(addr, addr, offset); |
3412 | 3413 |
if (insn & (1 << 20)) { |
3413 | 3414 |
gen_vfp_ld(s, dp, addr); |
... | ... | |
3419 | 3420 |
tcg_temp_free_i32(addr); |
3420 | 3421 |
} else { |
3421 | 3422 |
/* load/store multiple */ |
3423 |
int w = insn & (1 << 21); |
|
3422 | 3424 |
if (dp) |
3423 | 3425 |
n = (insn >> 1) & 0x7f; |
3424 | 3426 |
else |
3425 | 3427 |
n = insn & 0xff; |
3426 | 3428 |
|
3429 |
if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) { |
|
3430 |
/* P == U , W == 1 => UNDEF */ |
|
3431 |
return 1; |
|
3432 |
} |
|
3433 |
if (n == 0 || (rd + n) > 32 || (dp && n > 16)) { |
|
3434 |
/* UNPREDICTABLE cases for bad immediates: we choose to |
|
3435 |
* UNDEF to avoid generating huge numbers of TCG ops |
|
3436 |
*/ |
|
3437 |
return 1; |
|
3438 |
} |
|
3439 |
if (rn == 15 && w) { |
|
3440 |
/* writeback to PC is UNPREDICTABLE, we choose to UNDEF */ |
|
3441 |
return 1; |
|
3442 |
} |
|
3443 |
|
|
3444 |
if (s->thumb && rn == 15) { |
|
3445 |
/* This is actually UNPREDICTABLE */ |
|
3446 |
addr = tcg_temp_new_i32(); |
|
3447 |
tcg_gen_movi_i32(addr, s->pc & ~2); |
|
3448 |
} else { |
|
3449 |
addr = load_reg(s, rn); |
|
3450 |
} |
|
3427 | 3451 |
if (insn & (1 << 24)) /* pre-decrement */ |
3428 | 3452 |
tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2)); |
3429 | 3453 |
|
... | ... | |
3443 | 3467 |
} |
3444 | 3468 |
tcg_gen_addi_i32(addr, addr, offset); |
3445 | 3469 |
} |
3446 |
if (insn & (1 << 21)) {
|
|
3470 |
if (w) {
|
|
3447 | 3471 |
/* writeback */ |
3448 | 3472 |
if (insn & (1 << 24)) |
3449 | 3473 |
offset = -offset * n; |
Also available in: Unified diff