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