Revision b0109805

b/target-arm/exec.h
72 72
uint32_t helper_get_cp(CPUState *, uint32_t);
73 73
void helper_set_cp15(CPUState *, uint32_t, uint32_t);
74 74
uint32_t helper_get_cp15(CPUState *, uint32_t);
75
void helper_set_r13_banked(CPUState *env, int mode, uint32_t val);
76
uint32_t helper_get_r13_banked(CPUState *env, int mode);
77 75
uint32_t helper_v7m_mrs(CPUState *env, int reg);
78 76
void helper_v7m_msr(CPUState *env, int reg, uint32_t val);
79 77

  
b/target-arm/helper.c
513 513
        cpu_abort(env, "Tried to switch out of user mode\n");
514 514
}
515 515

  
516
void helper_set_r13_banked(CPUState *env, int mode, uint32_t val)
516
void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
517 517
{
518 518
    cpu_abort(env, "banked r13 write\n");
519 519
}
520 520

  
521
uint32_t helper_get_r13_banked(CPUState *env, int mode)
521
uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
522 522
{
523 523
    cpu_abort(env, "banked r13 read\n");
524 524
    return 0;
......
1793 1793
    return 0;
1794 1794
}
1795 1795

  
1796
void helper_set_r13_banked(CPUState *env, int mode, uint32_t val)
1796
void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
1797 1797
{
1798 1798
    env->banked_r13[bank_number(mode)] = val;
1799 1799
}
1800 1800

  
1801
uint32_t helper_get_r13_banked(CPUState *env, int mode)
1801
uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
1802 1802
{
1803 1803
    return env->banked_r13[bank_number(mode)];
1804 1804
}
b/target-arm/helpers.h
19 19
{ \
20 20
    tcg_gen_helper_0_2(helper_##name, arg1, arg2); \
21 21
}
22
#define DEF_HELPER_0_3(name, ret, args) \
23
DEF_HELPER(name, ret, args) \
24
static inline void gen_helper_##name( \
25
    TCGv arg1, TCGv arg2, TCGv arg3) \
26
{ \
27
    tcg_gen_helper_0_3(helper_##name, arg1, arg2, arg3); \
28
}
22 29
#define DEF_HELPER_1_0(name, ret, args) \
23 30
DEF_HELPER(name, ret, args) \
24 31
static inline void gen_helper_##name(TCGv ret) \
......
48 55
#define DEF_HELPER_0_0 DEF_HELPER
49 56
#define DEF_HELPER_0_1 DEF_HELPER
50 57
#define DEF_HELPER_0_2 DEF_HELPER
58
#define DEF_HELPER_0_3 DEF_HELPER
51 59
#define DEF_HELPER_1_0 DEF_HELPER
52 60
#define DEF_HELPER_1_1 DEF_HELPER
53 61
#define DEF_HELPER_1_2 DEF_HELPER
......
108 116
DEF_HELPER_0_2(cpsr_write, void, (uint32_t, uint32_t))
109 117
DEF_HELPER_1_0(cpsr_read, uint32_t, (void))
110 118

  
119
DEF_HELPER_1_2(get_r13_banked, uint32_t, (CPUState *, uint32_t))
120
DEF_HELPER_0_3(set_r13_banked, void, (CPUState *, uint32_t, uint32_t))
121

  
122
DEF_HELPER_1_1(get_user_reg, uint32_t, (uint32_t))
123
DEF_HELPER_0_2(set_user_reg, void, (uint32_t, uint32_t))
124

  
111 125
#undef DEF_HELPER
112 126
#undef DEF_HELPER_0_0
113 127
#undef DEF_HELPER_0_1
b/target-arm/op.c
589 589
    FORCE_RET();
590 590
}
591 591

  
592
/* Access to user mode registers from privileged modes.  */
593
void OPPROTO op_movl_T0_user(void)
594
{
595
    int regno = PARAM1;
596
    if (regno == 13) {
597
        T0 = env->banked_r13[0];
598
    } else if (regno == 14) {
599
        T0 = env->banked_r14[0];
600
    } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
601
        T0 = env->usr_regs[regno - 8];
602
    } else {
603
        T0 = env->regs[regno];
604
    }
605
    FORCE_RET();
606
}
607

  
608

  
609
void OPPROTO op_movl_user_T0(void)
610
{
611
    int regno = PARAM1;
612
    if (regno == 13) {
613
        env->banked_r13[0] = T0;
614
    } else if (regno == 14) {
615
        env->banked_r14[0] = T0;
616
    } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
617
        env->usr_regs[regno - 8] = T0;
618
    } else {
619
        env->regs[regno] = T0;
620
    }
621
    FORCE_RET();
622
}
623

  
624
void OPPROTO op_movl_T1_r13_banked(void)
625
{
626
    T1 = helper_get_r13_banked(env, PARAM1);
627
}
628

  
629
void OPPROTO op_movl_r13_T1_banked(void)
630
{
631
    helper_set_r13_banked(env, PARAM1, T1);
632
}
633

  
634 592
void OPPROTO op_v7m_mrs_T0(void)
635 593
{
636 594
    T0 = helper_v7m_mrs(env, PARAM1);
b/target-arm/op_helper.c
459 459
{
460 460
    cpsr_write(env, val, mask);
461 461
}
462

  
463
/* Access to user mode registers from privileged modes.  */
464
uint32_t HELPER(get_user_reg)(uint32_t regno)
465
{
466
    uint32_t val;
467

  
468
    if (regno == 13) {
469
        val = env->banked_r13[0];
470
    } else if (regno == 14) {
471
        val = env->banked_r14[0];
472
    } else if (regno >= 8
473
               && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
474
        val = env->usr_regs[regno - 8];
475
    } else {
476
        val = env->regs[regno];
477
    }
478
    return val;
479
}
480

  
481
void HELPER(set_user_reg)(uint32_t regno, uint32_t val)
482
{
483
    if (regno == 13) {
484
        env->banked_r13[0] = val;
485
    } else if (regno == 14) {
486
        env->banked_r14[0] = val;
487
    } else if (regno >= 8
488
               && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
489
        env->usr_regs[regno - 8] = val;
490
    } else {
491
        env->regs[regno] = val;
492
    }
493
}
494

  
b/target-arm/op_mem.h
1 1
/* ARM memory operations.  */
2 2

  
3
void helper_ld(uint32_t);
4
/* Load from address T1 into T0.  */
5
#define MEM_LD_OP(name) \
6
void OPPROTO glue(op_ld##name,MEMSUFFIX)(void) \
7
{ \
8
    T0 = glue(ld##name,MEMSUFFIX)(T1); \
9
    FORCE_RET(); \
10
}
11

  
12
MEM_LD_OP(ub)
13
MEM_LD_OP(sb)
14
MEM_LD_OP(uw)
15
MEM_LD_OP(sw)
16
MEM_LD_OP(l)
17

  
18
#undef MEM_LD_OP
19

  
20
/* Store T0 to address T1.  */
21
#define MEM_ST_OP(name) \
22
void OPPROTO glue(op_st##name,MEMSUFFIX)(void) \
23
{ \
24
    glue(st##name,MEMSUFFIX)(T1, T0); \
25
    FORCE_RET(); \
26
}
27

  
28
MEM_ST_OP(b)
29
MEM_ST_OP(w)
30
MEM_ST_OP(l)
31

  
32
#undef MEM_ST_OP
33

  
34 3
/* Swap T0 with memory at address T1.  */
35 4
/* ??? Is this exception safe?  */
36 5
#define MEM_SWP_OP(name, lname) \
b/target-arm/translate.c
222 222

  
223 223
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
224 224
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
225
#define gen_op_rev_T0() tcg_gen_bswap_i32(cpu_T[0], cpu_T[0])
226 225

  
227 226
#define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
228 227

  
......
804 803
        gen_op_##name##_kernel(); \
805 804
    } while (0)
806 805
#endif
806
static inline TCGv gen_ld8s(TCGv addr, int index)
807
{
808
    TCGv tmp = new_tmp();
809
    tcg_gen_qemu_ld8s(tmp, addr, index);
810
    return tmp;
811
}
812
static inline TCGv gen_ld8u(TCGv addr, int index)
813
{
814
    TCGv tmp = new_tmp();
815
    tcg_gen_qemu_ld8u(tmp, addr, index);
816
    return tmp;
817
}
818
static inline TCGv gen_ld16s(TCGv addr, int index)
819
{
820
    TCGv tmp = new_tmp();
821
    tcg_gen_qemu_ld16s(tmp, addr, index);
822
    return tmp;
823
}
824
static inline TCGv gen_ld16u(TCGv addr, int index)
825
{
826
    TCGv tmp = new_tmp();
827
    tcg_gen_qemu_ld16u(tmp, addr, index);
828
    return tmp;
829
}
830
static inline TCGv gen_ld32(TCGv addr, int index)
831
{
832
    TCGv tmp = new_tmp();
833
    tcg_gen_qemu_ld32u(tmp, addr, index);
834
    return tmp;
835
}
836
static inline void gen_st8(TCGv val, TCGv addr, int index)
837
{
838
    tcg_gen_qemu_st8(val, addr, index);
839
    dead_tmp(val);
840
}
841
static inline void gen_st16(TCGv val, TCGv addr, int index)
842
{
843
    tcg_gen_qemu_st16(val, addr, index);
844
    dead_tmp(val);
845
}
846
static inline void gen_st32(TCGv val, TCGv addr, int index)
847
{
848
    tcg_gen_qemu_st32(val, addr, index);
849
    dead_tmp(val);
850
}
807 851

  
808 852
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
809 853
{
......
859 903
    s->is_jmp = DISAS_UPDATE;
860 904
}
861 905

  
862
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
906
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
907
                                       TCGv var)
863 908
{
864 909
    int val, rm, shift, shiftop;
865 910
    TCGv offset;
......
870 915
        if (!(insn & (1 << 23)))
871 916
            val = -val;
872 917
        if (val != 0)
873
            gen_op_addl_T1_im(val);
918
            tcg_gen_addi_i32(var, var, val);
874 919
    } else {
875 920
        /* shift/register */
876 921
        rm = (insn) & 0xf;
......
879 924
        offset = load_reg(s, rm);
880 925
        gen_arm_shift_im(offset, shiftop, shift, 0);
881 926
        if (!(insn & (1 << 23)))
882
            tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
927
            tcg_gen_sub_i32(var, var, offset);
883 928
        else
884
            tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset);
929
            tcg_gen_add_i32(var, var, offset);
885 930
        dead_tmp(offset);
886 931
    }
887 932
}
888 933

  
889 934
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
890
                                        int extra)
935
                                        int extra, TCGv var)
891 936
{
892 937
    int val, rm;
893 938
    TCGv offset;
......
899 944
            val = -val;
900 945
        val += extra;
901 946
        if (val != 0)
902
            gen_op_addl_T1_im(val);
947
            tcg_gen_addi_i32(var, var, val);
903 948
    } else {
904 949
        /* register */
905 950
        if (extra)
906
            gen_op_addl_T1_im(extra);
951
            tcg_gen_addi_i32(var, var, extra);
907 952
        rm = (insn) & 0xf;
908 953
        offset = load_reg(s, rm);
909 954
        if (!(insn & (1 << 23)))
910
            tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
955
            tcg_gen_sub_i32(var, var, offset);
911 956
        else
912
            tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset);
957
            tcg_gen_add_i32(var, var, offset);
913 958
        dead_tmp(offset);
914 959
    }
915 960
}
......
1090 1135
{
1091 1136
    int rd, wrd;
1092 1137
    int rdhi, rdlo, rd0, rd1, i;
1138
    TCGv tmp;
1093 1139

  
1094 1140
    if ((insn & 0x0e000e00) == 0x0c000000) {
1095 1141
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
......
1114 1160
            return 1;
1115 1161
        if (insn & ARM_CP_RW_BIT) {
1116 1162
            if ((insn >> 28) == 0xf) {			/* WLDRW wCx */
1117
                gen_ldst(ldl, s);
1163
                tmp = gen_ld32(cpu_T[1], IS_USER(s));
1164
                tcg_gen_mov_i32(cpu_T[0], tmp);
1165
                dead_tmp(tmp);
1118 1166
                gen_op_iwmmxt_movl_wCx_T0(wrd);
1119 1167
            } else {
1120 1168
                if (insn & (1 << 8))
......
1132 1180
        } else {
1133 1181
            if ((insn >> 28) == 0xf) {			/* WSTRW wCx */
1134 1182
                gen_op_iwmmxt_movl_T0_wCx(wrd);
1135
                gen_ldst(stl, s);
1183
                tmp = new_tmp();
1184
                tcg_gen_mov_i32(tmp, cpu_T[0]);
1185
                gen_st32(tmp, cpu_T[1], IS_USER(s));
1136 1186
            } else {
1137 1187
                gen_op_iwmmxt_movq_M0_wRn(wrd);
1138 1188
                if (insn & (1 << 8))
......
2970 3020
    s->is_jmp = DISAS_UPDATE;
2971 3021
}
2972 3022

  
2973
/* Generate a v6 exception return.  */
2974
static void gen_rfe(DisasContext *s)
3023
/* Generate a v6 exception return.  Marks both values as dead.  */
3024
static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
2975 3025
{
2976
    gen_set_cpsr(cpu_T[0], 0xffffffff);
2977
    gen_op_movl_T0_T2();
2978
    gen_set_pc_T0();
3026
    gen_set_cpsr(cpsr, 0xffffffff);
3027
    dead_tmp(cpsr);
3028
    store_reg(s, 15, pc);
2979 3029
    s->is_jmp = DISAS_UPDATE;
2980 3030
}
2981 3031

  
......
3288 3338
    int shift;
3289 3339
    uint32_t mask;
3290 3340
    int n;
3341
    TCGv tmp;
3291 3342

  
3292 3343
    if (!vfp_enabled(env))
3293 3344
      return 1;
......
3316 3367
            for (pass = 0; pass < 2; pass++) {
3317 3368
                if (size == 2) {
3318 3369
                    if (load) {
3319
                        gen_ldst(ldl, s);
3370
                        tmp = gen_ld32(cpu_T[1], IS_USER(s));
3371
                        tcg_gen_mov_i32(cpu_T[0], tmp);
3372
                        dead_tmp(tmp);
3320 3373
                        NEON_SET_REG(T0, rd, pass);
3321 3374
                    } else {
3322 3375
                        NEON_GET_REG(T0, rd, pass);
3323
                        gen_ldst(stl, s);
3376
                        tmp = new_tmp();
3377
                        tcg_gen_mov_i32(tmp, cpu_T[0]);
3378
                        gen_st32(tmp, cpu_T[1], IS_USER(s));
3324 3379
                    }
3325 3380
                    gen_op_addl_T1_im(stride);
3326 3381
                } else if (size == 1) {
3327 3382
                    if (load) {
3328
                        gen_ldst(lduw, s);
3383
                        tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3384
                        tcg_gen_mov_i32(cpu_T[0], tmp);
3385
                        dead_tmp(tmp);
3329 3386
                        gen_op_addl_T1_im(stride);
3330 3387
                        gen_op_movl_T2_T0();
3331
                        gen_ldst(lduw, s);
3388
                        tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3389
                        tcg_gen_mov_i32(cpu_T[0], tmp);
3390
                        dead_tmp(tmp);
3332 3391
                        gen_op_addl_T1_im(stride);
3333 3392
                        gen_op_neon_insert_elt(16, 0xffff);
3334 3393
                        NEON_SET_REG(T2, rd, pass);
3335 3394
                    } else {
3336 3395
                        NEON_GET_REG(T2, rd, pass);
3337 3396
                        gen_op_movl_T0_T2();
3338
                        gen_ldst(stw, s);
3397
                        tmp = new_tmp();
3398
                        tcg_gen_mov_i32(tmp, cpu_T[0]);
3399
                        gen_st16(tmp, cpu_T[1], IS_USER(s));
3339 3400
                        gen_op_addl_T1_im(stride);
3340 3401
                        gen_op_neon_extract_elt(16, 0xffff0000);
3341
                        gen_ldst(stw, s);
3402
                        tmp = new_tmp();
3403
                        tcg_gen_mov_i32(tmp, cpu_T[0]);
3404
                        gen_st16(tmp, cpu_T[1], IS_USER(s));
3342 3405
                        gen_op_addl_T1_im(stride);
3343 3406
                    }
3344 3407
                } else /* size == 0 */ {
3345 3408
                    if (load) {
3346 3409
                        mask = 0xff;
3347 3410
                        for (n = 0; n < 4; n++) {
3348
                            gen_ldst(ldub, s);
3411
                            tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3412
                            tcg_gen_mov_i32(cpu_T[0], tmp);
3413
                            dead_tmp(tmp);
3349 3414
                            gen_op_addl_T1_im(stride);
3350 3415
                            if (n == 0) {
3351 3416
                                gen_op_movl_T2_T0();
......
3364 3429
                            } else {
3365 3430
                                gen_op_neon_extract_elt(n * 8, mask);
3366 3431
                            }
3367
                            gen_ldst(stb, s);
3432
                            tmp = new_tmp();
3433
                            tcg_gen_mov_i32(tmp, cpu_T[0]);
3434
                            gen_st8(tmp, cpu_T[1], IS_USER(s));
3368 3435
                            gen_op_addl_T1_im(stride);
3369 3436
                            mask <<= 8;
3370 3437
                        }
......
3387 3454
            for (reg = 0; reg < nregs; reg++) {
3388 3455
                switch (size) {
3389 3456
                case 0:
3390
                    gen_ldst(ldub, s);
3457
                    tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3458
                    tcg_gen_mov_i32(cpu_T[0], tmp);
3459
                    dead_tmp(tmp);
3391 3460
                    gen_op_neon_dup_u8(0);
3392 3461
                    break;
3393 3462
                case 1:
3394
                    gen_ldst(lduw, s);
3463
                    tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3464
                    tcg_gen_mov_i32(cpu_T[0], tmp);
3465
                    dead_tmp(tmp);
3395 3466
                    gen_op_neon_dup_low16();
3396 3467
                    break;
3397 3468
                case 2:
3398
                    gen_ldst(ldl, s);
3469
                    tmp = gen_ld32(cpu_T[0], IS_USER(s));
3470
                    tcg_gen_mov_i32(cpu_T[0], tmp);
3471
                    dead_tmp(tmp);
3399 3472
                    break;
3400 3473
                case 3:
3401 3474
                    return 1;
......
3437 3510
                    }
3438 3511
                    switch (size) {
3439 3512
                    case 0:
3440
                        gen_ldst(ldub, s);
3513
                        tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3441 3514
                        break;
3442 3515
                    case 1:
3443
                        gen_ldst(lduw, s);
3516
                        tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3444 3517
                        break;
3445 3518
                    case 2:
3446
                        gen_ldst(ldl, s);
3447
                        NEON_SET_REG(T0, rd, pass);
3519
                        tmp = gen_ld32(cpu_T[1], IS_USER(s));
3448 3520
                        break;
3449 3521
                    }
3522
                    tcg_gen_mov_i32(cpu_T[0], tmp);
3523
                    dead_tmp(tmp);
3450 3524
                    if (size != 2) {
3451 3525
                        gen_op_neon_insert_elt(shift, ~mask);
3452 3526
                        NEON_SET_REG(T0, rd, pass);
3527
                    } else {
3528
                        NEON_SET_REG(T0, rd, pass);
3453 3529
                    }
3454 3530
                } else { /* Store */
3455 3531
                    if (size == 2) {
......
3458 3534
                        NEON_GET_REG(T2, rd, pass);
3459 3535
                        gen_op_neon_extract_elt(shift, mask);
3460 3536
                    }
3537
                    tmp = new_tmp();
3538
                    tcg_gen_mov_i32(tmp, cpu_T[0]);
3461 3539
                    switch (size) {
3462 3540
                    case 0:
3463
                        gen_ldst(stb, s);
3541
                        gen_st8(tmp, cpu_T[1], IS_USER(s));
3464 3542
                        break;
3465 3543
                    case 1:
3466
                        gen_ldst(stw, s);
3544
                        gen_st16(tmp, cpu_T[1], IS_USER(s));
3467 3545
                        break;
3468 3546
                    case 2:
3469
                        gen_ldst(stl, s);
3547
                        gen_st32(tmp, cpu_T[1], IS_USER(s));
3470 3548
                        break;
3471 3549
                    }
3472 3550
                }
......
4647 4725
                        NEON_GET_REG(T0, rm, pass * 2);
4648 4726
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4649 4727
                        switch (size) {
4650
                        case 0: gen_op_rev_T0(); break;
4728
                        case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
4651 4729
                        case 1: gen_swap_half(cpu_T[0]); break;
4652 4730
                        case 2: /* no-op */ break;
4653 4731
                        default: abort();
......
4658 4736
                        } else {
4659 4737
                            gen_op_movl_T0_T1();
4660 4738
                            switch (size) {
4661
                            case 0: gen_op_rev_T0(); break;
4739
                            case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
4662 4740
                            case 1: gen_swap_half(cpu_T[0]); break;
4663 4741
                            default: abort();
4664 4742
                            }
......
4827 4905
                        switch (op) {
4828 4906
                        case 1: /* VREV32 */
4829 4907
                            switch (size) {
4830
                            case 0: gen_op_rev_T0(); break;
4908
                            case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break;
4831 4909
                            case 1: gen_swap_half(cpu_T[0]); break;
4832 4910
                            default: return 1;
4833 4911
                            }
......
5099 5177
    TCGv tmp;
5100 5178
    TCGv tmp2;
5101 5179
    TCGv tmp3;
5180
    TCGv addr;
5102 5181

  
5103 5182
    insn = ldl_code(s->pc);
5104 5183
    s->pc += 4;
......
5160 5239
            ARCH(6);
5161 5240
            op1 = (insn & 0x1f);
5162 5241
            if (op1 == (env->uncached_cpsr & CPSR_M)) {
5163
                gen_movl_T1_reg(s, 13);
5242
                addr = load_reg(s, 13);
5164 5243
            } else {
5165
                gen_op_movl_T1_r13_banked(op1);
5244
                addr = new_tmp();
5245
                gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
5166 5246
            }
5167 5247
            i = (insn >> 23) & 3;
5168 5248
            switch (i) {
......
5173 5253
            default: abort();
5174 5254
            }
5175 5255
            if (offset)
5176
                gen_op_addl_T1_im(offset);
5177
            gen_movl_T0_reg(s, 14);
5178
            gen_ldst(stl, s);
5179
            gen_helper_cpsr_read(cpu_T[0]);
5180
            gen_op_addl_T1_im(4);
5181
            gen_ldst(stl, s);
5256
                tcg_gen_addi_i32(addr, addr, offset);
5257
            tmp = load_reg(s, 14);
5258
            gen_st32(tmp, addr, 0);
5259
            tmp = new_tmp();
5260
            gen_helper_cpsr_read(tmp);
5261
            tcg_gen_addi_i32(addr, addr, 4);
5262
            gen_st32(tmp, addr, 0);
5182 5263
            if (insn & (1 << 21)) {
5183 5264
                /* Base writeback.  */
5184 5265
                switch (i) {
......
5189 5270
                default: abort();
5190 5271
                }
5191 5272
                if (offset)
5192
                    gen_op_addl_T1_im(offset);
5273
                    tcg_gen_addi_i32(addr, tmp, offset);
5193 5274
                if (op1 == (env->uncached_cpsr & CPSR_M)) {
5194 5275
                    gen_movl_reg_T1(s, 13);
5195 5276
                } else {
5196
                    gen_op_movl_r13_T1_banked(op1);
5277
                    gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), cpu_T[1]);
5197 5278
                }
5279
            } else {
5280
                dead_tmp(addr);
5198 5281
            }
5199 5282
        } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5200 5283
            /* rfe */
......
5203 5286
                goto illegal_op;
5204 5287
            ARCH(6);
5205 5288
            rn = (insn >> 16) & 0xf;
5206
            gen_movl_T1_reg(s, rn);
5289
            addr = load_reg(s, rn);
5207 5290
            i = (insn >> 23) & 3;
5208 5291
            switch (i) {
5209
            case 0: offset = 0; break; /* DA */
5210
            case 1: offset = -4; break; /* DB */
5211
            case 2: offset = 4; break; /* IA */
5212
            case 3: offset = 8; break; /* IB */
5292
            case 0: offset = -4; break; /* DA */
5293
            case 1: offset = -8; break; /* DB */
5294
            case 2: offset = 0; break; /* IA */
5295
            case 3: offset = 4; break; /* IB */
5213 5296
            default: abort();
5214 5297
            }
5215 5298
            if (offset)
5216
                gen_op_addl_T1_im(offset);
5217
            /* Load CPSR into T2 and PC into T0.  */
5218
            gen_ldst(ldl, s);
5219
            gen_op_movl_T2_T0();
5220
            gen_op_addl_T1_im(-4);
5221
            gen_ldst(ldl, s);
5299
                tcg_gen_addi_i32(addr, addr, offset);
5300
            /* Load PC into tmp and CPSR into tmp2.  */
5301
            tmp = gen_ld32(addr, 0);
5302
            tcg_gen_addi_i32(addr, addr, 4);
5303
            tmp2 = gen_ld32(addr, 0);
5222 5304
            if (insn & (1 << 21)) {
5223 5305
                /* Base writeback.  */
5224 5306
                switch (i) {
5225
                case 0: offset = -4; break;
5226
                case 1: offset = 0; break;
5227
                case 2: offset = 8; break;
5228
                case 3: offset = 4; break;
5307
                case 0: offset = -8; break;
5308
                case 1: offset = -4; break;
5309
                case 2: offset = 4; break;
5310
                case 3: offset = 0; break;
5229 5311
                default: abort();
5230 5312
                }
5231 5313
                if (offset)
5232
                    gen_op_addl_T1_im(offset);
5233
                gen_movl_reg_T1(s, rn);
5314
                    tcg_gen_addi_i32(addr, addr, offset);
5315
                store_reg(s, rn, addr);
5316
            } else {
5317
                dead_tmp(addr);
5234 5318
            }
5235
            gen_rfe(s);
5319
            gen_rfe(s, tmp, tmp2);
5236 5320
        } else if ((insn & 0x0e000000) == 0x0a000000) {
5237 5321
            /* branch link and change to thumb (blx <offset>) */
5238 5322
            int32_t offset;
......
5707 5791
                /* Misc load/store */
5708 5792
                rn = (insn >> 16) & 0xf;
5709 5793
                rd = (insn >> 12) & 0xf;
5710
                gen_movl_T1_reg(s, rn);
5794
                addr = load_reg(s, rn);
5711 5795
                if (insn & (1 << 24))
5712
                    gen_add_datah_offset(s, insn, 0);
5796
                    gen_add_datah_offset(s, insn, 0, addr);
5713 5797
                address_offset = 0;
5714 5798
                if (insn & (1 << 20)) {
5715 5799
                    /* load */
5716 5800
                    switch(sh) {
5717 5801
                    case 1:
5718
                        gen_ldst(lduw, s);
5802
                        tmp = gen_ld16u(addr, IS_USER(s));
5719 5803
                        break;
5720 5804
                    case 2:
5721
                        gen_ldst(ldsb, s);
5805
                        tmp = gen_ld8s(addr, IS_USER(s));
5722 5806
                        break;
5723 5807
                    default:
5724 5808
                    case 3:
5725
                        gen_ldst(ldsw, s);
5809
                        tmp = gen_ld16s(addr, IS_USER(s));
5726 5810
                        break;
5727 5811
                    }
5728 5812
                    load = 1;
......
5730 5814
                    /* doubleword */
5731 5815
                    if (sh & 1) {
5732 5816
                        /* store */
5733
                        gen_movl_T0_reg(s, rd);
5734
                        gen_ldst(stl, s);
5735
                        gen_op_addl_T1_im(4);
5736
                        gen_movl_T0_reg(s, rd + 1);
5737
                        gen_ldst(stl, s);
5817
                        tmp = load_reg(s, rd);
5818
                        gen_st32(tmp, addr, IS_USER(s));
5819
                        tcg_gen_addi_i32(addr, addr, 4);
5820
                        tmp = load_reg(s, rd + 1);
5821
                        gen_st32(tmp, addr, IS_USER(s));
5738 5822
                        load = 0;
5739 5823
                    } else {
5740 5824
                        /* load */
5741
                        gen_ldst(ldl, s);
5742
                        gen_movl_reg_T0(s, rd);
5743
                        gen_op_addl_T1_im(4);
5744
                        gen_ldst(ldl, s);
5825
                        tmp = gen_ld32(addr, IS_USER(s));
5826
                        store_reg(s, rd, tmp);
5827
                        tcg_gen_addi_i32(addr, addr, 4);
5828
                        tmp = gen_ld32(addr, IS_USER(s));
5745 5829
                        rd++;
5746 5830
                        load = 1;
5747 5831
                    }
5748 5832
                    address_offset = -4;
5749 5833
                } else {
5750 5834
                    /* store */
5751
                    gen_movl_T0_reg(s, rd);
5752
                    gen_ldst(stw, s);
5835
                    tmp = load_reg(s, rd);
5836
                    gen_st16(tmp, addr, IS_USER(s));
5753 5837
                    load = 0;
5754 5838
                }
5755 5839
                /* Perform base writeback before the loaded value to
......
5757 5841
                   ldrd with base writeback is is undefined if the
5758 5842
                   destination and index registers overlap.  */
5759 5843
                if (!(insn & (1 << 24))) {
5760
                    gen_add_datah_offset(s, insn, address_offset);
5761
                    gen_movl_reg_T1(s, rn);
5844
                    gen_add_datah_offset(s, insn, address_offset, addr);
5845
                    store_reg(s, rn, addr);
5762 5846
                } else if (insn & (1 << 21)) {
5763 5847
                    if (address_offset)
5764
                        gen_op_addl_T1_im(address_offset);
5765
                    gen_movl_reg_T1(s, rn);
5848
                        tcg_gen_addi_i32(addr, addr, address_offset);
5849
                    store_reg(s, rn, addr);
5850
                } else {
5851
                    dead_tmp(addr);
5766 5852
                }
5767 5853
                if (load) {
5768 5854
                    /* Complete the load.  */
5769
                    gen_movl_reg_T0(s, rd);
5855
                    store_reg(s, rd, tmp);
5770 5856
                }
5771 5857
            }
5772 5858
            break;
......
5882 5968
                        gen_movl_reg_T1(s, rd);
5883 5969
                    } else if ((insn & 0x003f0f60) == 0x003f0f20) {
5884 5970
                        /* rev */
5885
                        gen_movl_T0_reg(s, rm);
5971
                        tmp = load_reg(s, rm);
5886 5972
                        if (insn & (1 << 22)) {
5887 5973
                            if (insn & (1 << 7)) {
5888
                                gen_revsh(cpu_T[0]);
5974
                                gen_revsh(tmp);
5889 5975
                            } else {
5890 5976
                                ARCH(6T2);
5891
                                gen_helper_rbit(cpu_T[0], cpu_T[0]);
5977
                                gen_helper_rbit(tmp, tmp);
5892 5978
                            }
5893 5979
                        } else {
5894 5980
                            if (insn & (1 << 7))
5895
                                gen_rev16(cpu_T[0]);
5981
                                gen_rev16(tmp);
5896 5982
                            else
5897
                                gen_op_rev_T0();
5983
                                tcg_gen_bswap_i32(tmp, tmp);
5898 5984
                        }
5899
                        gen_movl_reg_T0(s, rd);
5985
                        store_reg(s, rd, tmp);
5900 5986
                    } else {
5901 5987
                        goto illegal_op;
5902 5988
                    }
......
6020 6106
            /* load/store byte/word */
6021 6107
            rn = (insn >> 16) & 0xf;
6022 6108
            rd = (insn >> 12) & 0xf;
6023
            gen_movl_T1_reg(s, rn);
6109
            tmp2 = load_reg(s, rn);
6024 6110
            i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6025 6111
            if (insn & (1 << 24))
6026
                gen_add_data_offset(s, insn);
6112
                gen_add_data_offset(s, insn, tmp2);
6027 6113
            if (insn & (1 << 20)) {
6028 6114
                /* load */
6029 6115
                s->is_mem = 1;
6030
#if defined(CONFIG_USER_ONLY)
6031
                if (insn & (1 << 22))
6032
                    gen_op_ldub_raw();
6033
                else
6034
                    gen_op_ldl_raw();
6035
#else
6036 6116
                if (insn & (1 << 22)) {
6037
                    if (i)
6038
                        gen_op_ldub_user();
6039
                    else
6040
                        gen_op_ldub_kernel();
6117
                    tmp = gen_ld8u(tmp2, i);
6041 6118
                } else {
6042
                    if (i)
6043
                        gen_op_ldl_user();
6044
                    else
6045
                        gen_op_ldl_kernel();
6119
                    tmp = gen_ld32(tmp2, i);
6046 6120
                }
6047
#endif
6048 6121
            } else {
6049 6122
                /* store */
6050
                gen_movl_T0_reg(s, rd);
6051
#if defined(CONFIG_USER_ONLY)
6123
                tmp = load_reg(s, rd);
6052 6124
                if (insn & (1 << 22))
6053
                    gen_op_stb_raw();
6125
                    gen_st8(tmp, tmp2, i);
6054 6126
                else
6055
                    gen_op_stl_raw();
6056
#else
6057
                if (insn & (1 << 22)) {
6058
                    if (i)
6059
                        gen_op_stb_user();
6060
                    else
6061
                        gen_op_stb_kernel();
6062
                } else {
6063
                    if (i)
6064
                        gen_op_stl_user();
6065
                    else
6066
                        gen_op_stl_kernel();
6067
                }
6068
#endif
6127
                    gen_st32(tmp, tmp2, i);
6069 6128
            }
6070 6129
            if (!(insn & (1 << 24))) {
6071
                gen_add_data_offset(s, insn);
6072
                gen_movl_reg_T1(s, rn);
6073
            } else if (insn & (1 << 21))
6074
                gen_movl_reg_T1(s, rn); {
6130
                gen_add_data_offset(s, insn, tmp2);
6131
                store_reg(s, rn, tmp2);
6132
            } else if (insn & (1 << 21)) {
6133
                store_reg(s, rn, tmp2);
6134
            } else {
6135
                dead_tmp(tmp2);
6075 6136
            }
6076 6137
            if (insn & (1 << 20)) {
6077 6138
                /* Complete the load.  */
6078 6139
                if (rd == 15)
6079
                    gen_bx_T0(s);
6140
                    gen_bx(s, tmp);
6080 6141
                else
6081
                    gen_movl_reg_T0(s, rd);
6142
                    store_reg(s, rd, tmp);
6082 6143
            }
6083 6144
            break;
6084 6145
        case 0x08:
6085 6146
        case 0x09:
6086 6147
            {
6087 6148
                int j, n, user, loaded_base;
6149
                TCGv loaded_var;
6088 6150
                /* load/store multiple words */
6089 6151
                /* XXX: store correct base if write back */
6090 6152
                user = 0;
......
6096 6158
                        user = 1;
6097 6159
                }
6098 6160
                rn = (insn >> 16) & 0xf;
6099
                gen_movl_T1_reg(s, rn);
6161
                addr = load_reg(s, rn);
6100 6162

  
6101 6163
                /* compute total size */
6102 6164
                loaded_base = 0;
......
6109 6171
                if (insn & (1 << 23)) {
6110 6172
                    if (insn & (1 << 24)) {
6111 6173
                        /* pre increment */
6112
                        gen_op_addl_T1_im(4);
6174
                        tcg_gen_addi_i32(addr, addr, 4);
6113 6175
                    } else {
6114 6176
                        /* post increment */
6115 6177
                    }
6116 6178
                } else {
6117 6179
                    if (insn & (1 << 24)) {
6118 6180
                        /* pre decrement */
6119
                        gen_op_addl_T1_im(-(n * 4));
6181
                        tcg_gen_addi_i32(addr, addr, -(n * 4));
6120 6182
                    } else {
6121 6183
                        /* post decrement */
6122 6184
                        if (n != 1)
6123
                            gen_op_addl_T1_im(-((n - 1) * 4));
6185
                        tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6124 6186
                    }
6125 6187
                }
6126 6188
                j = 0;
......
6128 6190
                    if (insn & (1 << i)) {
6129 6191
                        if (insn & (1 << 20)) {
6130 6192
                            /* load */
6131
                            gen_ldst(ldl, s);
6193
                            tmp = gen_ld32(addr, IS_USER(s));
6132 6194
                            if (i == 15) {
6133
                                gen_bx_T0(s);
6195
                                gen_bx(s, tmp);
6134 6196
                            } else if (user) {
6135
                                gen_op_movl_user_T0(i);
6197
                                gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6198
                                dead_tmp(tmp);
6136 6199
                            } else if (i == rn) {
6137
                                gen_op_movl_T2_T0();
6200
                                loaded_var = tmp;
6138 6201
                                loaded_base = 1;
6139 6202
                            } else {
6140
                                gen_movl_reg_T0(s, i);
6203
                                store_reg(s, i, tmp);
6141 6204
                            }
6142 6205
                        } else {
6143 6206
                            /* store */
6144 6207
                            if (i == 15) {
6145 6208
                                /* special case: r15 = PC + 8 */
6146 6209
                                val = (long)s->pc + 4;
6147
                                gen_op_movl_T0_im(val);
6210
                                tmp = new_tmp();
6211
                                tcg_gen_movi_i32(tmp, val);
6148 6212
                            } else if (user) {
6149
                                gen_op_movl_T0_user(i);
6213
                                tmp = new_tmp();
6214
                                gen_helper_get_user_reg(tmp, tcg_const_i32(i));
6150 6215
                            } else {
6151
                                gen_movl_T0_reg(s, i);
6216
                                tmp = load_reg(s, i);
6152 6217
                            }
6153
                            gen_ldst(stl, s);
6218
                            gen_st32(tmp, addr, IS_USER(s));
6154 6219
                        }
6155 6220
                        j++;
6156 6221
                        /* no need to add after the last transfer */
6157 6222
                        if (j != n)
6158
                            gen_op_addl_T1_im(4);
6223
                            tcg_gen_addi_i32(addr, addr, 4);
6159 6224
                    }
6160 6225
                }
6161 6226
                if (insn & (1 << 21)) {
......
6165 6230
                            /* pre increment */
6166 6231
                        } else {
6167 6232
                            /* post increment */
6168
                            gen_op_addl_T1_im(4);
6233
                            tcg_gen_addi_i32(addr, addr, 4);
6169 6234
                        }
6170 6235
                    } else {
6171 6236
                        if (insn & (1 << 24)) {
6172 6237
                            /* pre decrement */
6173 6238
                            if (n != 1)
6174
                                gen_op_addl_T1_im(-((n - 1) * 4));
6239
                                tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6175 6240
                        } else {
6176 6241
                            /* post decrement */
6177
                            gen_op_addl_T1_im(-(n * 4));
6242
                            tcg_gen_addi_i32(addr, addr, -(n * 4));
6178 6243
                        }
6179 6244
                    }
6180
                    gen_movl_reg_T1(s, rn);
6245
                    store_reg(s, rn, addr);
6246
                } else {
6247
                    dead_tmp(addr);
6181 6248
                }
6182 6249
                if (loaded_base) {
6183
                    gen_op_movl_T0_T2();
6184
                    gen_movl_reg_T0(s, rn);
6250
                    store_reg(s, rn, loaded_var);
6185 6251
                }
6186 6252
                if ((insn & (1 << 22)) && !user) {
6187 6253
                    /* Restore CPSR from SPSR.  */
......
6319 6385
   is not legal.  */
6320 6386
static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
6321 6387
{
6322
    uint32_t insn, imm, shift, offset, addr;
6388
    uint32_t insn, imm, shift, offset;
6323 6389
    uint32_t rd, rn, rm, rs;
6324 6390
    TCGv tmp;
6325 6391
    TCGv tmp2;
6326 6392
    TCGv tmp3;
6393
    TCGv addr;
6327 6394
    int op;
6328 6395
    int shiftop;
6329 6396
    int conds;
......
6341 6408
            tcg_gen_addi_i32(tmp, tmp, offset);
6342 6409
            tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
6343 6410

  
6344
            addr = (uint32_t)s->pc;
6345 6411
            tmp2 = new_tmp();
6346
            tcg_gen_movi_i32(tmp2, addr | 1);
6412
            tcg_gen_movi_i32(tmp2, s->pc | 1);
6347 6413
            store_reg(s, 14, tmp2);
6348 6414
            gen_bx(s, tmp);
6349 6415
            return 0;
......
6354 6420
            tmp = load_reg(s, 14);
6355 6421
            tcg_gen_addi_i32(tmp, tmp, 14);
6356 6422

  
6357
            addr = (uint32_t)s->pc;
6358 6423
            tmp2 = new_tmp();
6359
            tcg_gen_movi_i32(tmp2, addr | 1);
6424
            tcg_gen_movi_i32(tmp2, s->pc | 1);
6360 6425
            store_reg(s, 14, tmp2);
6361 6426
            gen_bx(s, tmp);
6362 6427
            return 0;
......
6366 6431
               16-bit instructions in case the second half causes an
6367 6432
               prefetch abort.  */
6368 6433
            offset = ((int32_t)insn << 21) >> 9;
6369
            addr = s->pc + 2 + offset;
6370
            gen_op_movl_T0_im(addr);
6434
            gen_op_movl_T0_im(s->pc + 2 + offset);
6371 6435
            gen_movl_reg_T0(s, 14);
6372 6436
            return 0;
6373 6437
        }
......
6396 6460
            if (insn & 0x01200000) {
6397 6461
                /* Load/store doubleword.  */
6398 6462
                if (rn == 15) {
6399
                    gen_op_movl_T1_im(s->pc & ~3);
6463
                    addr = new_tmp();
6464
                    tcg_gen_movi_i32(addr, s->pc & ~3);
6400 6465
                } else {
6401
                    gen_movl_T1_reg(s, rn);
6466
                    addr = load_reg(s, rn);
6402 6467
                }
6403 6468
                offset = (insn & 0xff) * 4;
6404 6469
                if ((insn & (1 << 23)) == 0)
6405 6470
                    offset = -offset;
6406 6471
                if (insn & (1 << 24)) {
6407
                    gen_op_addl_T1_im(offset);
6472
                    tcg_gen_addi_i32(addr, addr, offset);
6408 6473
                    offset = 0;
6409 6474
                }
6410 6475
                if (insn & (1 << 20)) {
6411 6476
                    /* ldrd */
6412
                    gen_ldst(ldl, s);
6413
                    gen_movl_reg_T0(s, rs);
6414
                    gen_op_addl_T1_im(4);
6415
                    gen_ldst(ldl, s);
6416
                    gen_movl_reg_T0(s, rd);
6477
                    tmp = gen_ld32(addr, IS_USER(s));
6478
                    store_reg(s, rs, tmp);
6479
                    tcg_gen_addi_i32(addr, addr, 4);
6480
                    tmp = gen_ld32(addr, IS_USER(s));
6481
                    store_reg(s, rd, tmp);
6417 6482
                } else {
6418 6483
                    /* strd */
6419
                    gen_movl_T0_reg(s, rs);
6420
                    gen_ldst(stl, s);
6421
                    gen_op_addl_T1_im(4);
6422
                    gen_movl_T0_reg(s, rd);
6423
                    gen_ldst(stl, s);
6484
                    tmp = load_reg(s, rs);
6485
                    gen_st32(tmp, addr, IS_USER(s));
6486
                    tcg_gen_addi_i32(addr, addr, 4);
6487
                    tmp = load_reg(s, rd);
6488
                    gen_st32(tmp, addr, IS_USER(s));
6424 6489
                }
6425 6490
                if (insn & (1 << 21)) {
6426 6491
                    /* Base writeback.  */
6427 6492
                    if (rn == 15)
6428 6493
                        goto illegal_op;
6429
                    gen_op_addl_T1_im(offset - 4);
6430
                    gen_movl_reg_T1(s, rn);
6494
                    tcg_gen_addi_i32(addr, addr, offset - 4);
6495
                    store_reg(s, rn, addr);
6496
                } else {
6497
                    dead_tmp(addr);
6431 6498
                }
6432 6499
            } else if ((insn & (1 << 23)) == 0) {
6433 6500
                /* Load/store exclusive word.  */
......
6442 6509
            } else if ((insn & (1 << 6)) == 0) {
6443 6510
                /* Table Branch.  */
6444 6511
                if (rn == 15) {
6445
                    gen_op_movl_T1_im(s->pc);
6512
                    addr = new_tmp();
6513
                    tcg_gen_movi_i32(addr, s->pc);
6446 6514
                } else {
6447
                    gen_movl_T1_reg(s, rn);
6515
                    addr = load_reg(s, rn);
6448 6516
                }
6449 6517
                tmp = load_reg(s, rm);
6450
                tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
6518
                tcg_gen_add_i32(addr, addr, tmp);
6451 6519
                if (insn & (1 << 4)) {
6452 6520
                    /* tbh */
6453
                    tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
6521
                    tcg_gen_add_i32(addr, addr, tmp);
6454 6522
                    dead_tmp(tmp);
6455
                    gen_ldst(lduw, s);
6523
                    tmp = gen_ld16u(addr, IS_USER(s));
6456 6524
                } else { /* tbb */
6457 6525
                    dead_tmp(tmp);
6458
                    gen_ldst(ldub, s);
6526
                    tmp = gen_ld8u(addr, IS_USER(s));
6459 6527
                }
6460
                tcg_gen_shli_i32(cpu_T[0], cpu_T[0], 1);
6461
                tcg_gen_addi_i32(cpu_T[0], cpu_T[0], s->pc);
6462
                gen_movl_reg_T0(s, 15);
6528
                dead_tmp(addr);
6529
                tcg_gen_shli_i32(tmp, tmp, 1);
6530
                tcg_gen_addi_i32(tmp, tmp, s->pc);
6531
                store_reg(s, 15, tmp);
6463 6532
            } else {
6464 6533
                /* Load/store exclusive byte/halfword/doubleword.  */
6465 6534
                op = (insn >> 4) & 0x3;
......
6503 6572
            /* Load/store multiple, RFE, SRS.  */
6504 6573
            if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
6505 6574
                /* Not available in user mode.  */
6506
                if (!IS_USER(s))
6575
                if (IS_USER(s))
6507 6576
                    goto illegal_op;
6508 6577
                if (insn & (1 << 20)) {
6509 6578
                    /* rfe */
6510
                    gen_movl_T1_reg(s, rn);
6511
                    if (insn & (1 << 24)) {
6512
                        gen_op_addl_T1_im(4);
6513
                    } else {
6514
                        gen_op_addl_T1_im(-4);
6515
                    }
6516
                    /* Load CPSR into T2 and PC into T0.  */
6517
                    gen_ldst(ldl, s);
6518
                    gen_op_movl_T2_T0();
6519
                    gen_op_addl_T1_im(-4);
6520
                    gen_ldst(ldl, s);
6579
                    addr = load_reg(s, rn);
6580
                    if ((insn & (1 << 24)) == 0)
6581
                        tcg_gen_addi_i32(addr, addr, -8);
6582
                    /* Load PC into tmp and CPSR into tmp2.  */
6583
                    tmp = gen_ld32(addr, 0);
6584
                    tcg_gen_addi_i32(addr, addr, 4);
6585
                    tmp2 = gen_ld32(addr, 0);
6521 6586
                    if (insn & (1 << 21)) {
6522 6587
                        /* Base writeback.  */
6523
                        if (insn & (1 << 24))
6524
                            gen_op_addl_T1_im(8);
6525
                        gen_movl_reg_T1(s, rn);
6588
                        if (insn & (1 << 24)) {
6589
                            tcg_gen_addi_i32(addr, addr, 4);
6590
                        } else {
6591
                            tcg_gen_addi_i32(addr, addr, -4);
6592
                        }
6593
                        store_reg(s, rn, addr);
6594
                    } else {
6595
                        dead_tmp(addr);
6526 6596
                    }
6527
                    gen_rfe(s);
6597
                    gen_rfe(s, tmp, tmp2);
6528 6598
                } else {
6529 6599
                    /* srs */
6530 6600
                    op = (insn & 0x1f);
6531 6601
                    if (op == (env->uncached_cpsr & CPSR_M)) {
6532
                        gen_movl_T1_reg(s, 13);
6602
                        addr = load_reg(s, 13);
6533 6603
                    } else {
6534
                        gen_op_movl_T1_r13_banked(op);
6604
                        addr = new_tmp();
6605
                        gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
6535 6606
                    }
6536 6607
                    if ((insn & (1 << 24)) == 0) {
6537
                        gen_op_addl_T1_im(-8);
6608
                        tcg_gen_addi_i32(addr, addr, -8);
6538 6609
                    }
6539
                    gen_movl_T0_reg(s, 14);
6540
                    gen_ldst(stl, s);
6541
                    gen_helper_cpsr_read(cpu_T[0]);
6542
                    gen_op_addl_T1_im(4);
6543
                    gen_ldst(stl, s);
6610
                    tmp = load_reg(s, 14);
6611
                    gen_st32(tmp, addr, 0);
6612
                    tcg_gen_addi_i32(addr, addr, 4);
6613
                    tmp = new_tmp();
6614
                    gen_helper_cpsr_read(tmp);
6615
                    gen_st32(tmp, addr, 0);
6544 6616
                    if (insn & (1 << 21)) {
6545 6617
                        if ((insn & (1 << 24)) == 0) {
6546
                            gen_op_addl_T1_im(-4);
6618
                            tcg_gen_addi_i32(addr, addr, -4);
6547 6619
                        } else {
6548
                            gen_op_addl_T1_im(4);
6620
                            tcg_gen_addi_i32(addr, addr, 4);
6549 6621
                        }
6550 6622
                        if (op == (env->uncached_cpsr & CPSR_M)) {
6551
                            gen_movl_reg_T1(s, 13);
6623
                            store_reg(s, 13, addr);
6552 6624
                        } else {
6553
                            gen_op_movl_r13_T1_banked(op);
6625
                            gen_helper_set_r13_banked(cpu_env,
6626
                                tcg_const_i32(op), addr);
6554 6627
                        }
6628
                    } else {
6629
                        dead_tmp(addr);
6555 6630
                    }
6556 6631
                }
6557 6632
            } else {
6558 6633
                int i;
6559 6634
                /* Load/store multiple.  */
6560
                gen_movl_T1_reg(s, rn);
6635
                addr = load_reg(s, rn);
6561 6636
                offset = 0;
6562 6637
                for (i = 0; i < 16; i++) {
6563 6638
                    if (insn & (1 << i))
6564 6639
                        offset += 4;
6565 6640
                }
6566 6641
                if (insn & (1 << 24)) {
6567
                    gen_op_addl_T1_im(-offset);
6642
                    tcg_gen_addi_i32(addr, addr, -offset);
6568 6643
                }
6569 6644

  
6570 6645
                for (i = 0; i < 16; i++) {
......
6572 6647
                        continue;
6573 6648
                    if (insn & (1 << 20)) {
6574 6649
                        /* Load.  */
6575
                        gen_ldst(ldl, s);
6650
                        tmp = gen_ld32(addr, IS_USER(s));
6576 6651
                        if (i == 15) {
6577
                            gen_bx_T0(s);
6652
                            gen_bx(s, tmp);
6578 6653
                        } else {
6579
                            gen_movl_reg_T0(s, i);
6654
                            store_reg(s, i, tmp);
6580 6655
                        }
6581 6656
                    } else {
6582 6657
                        /* Store.  */
6583
                        gen_movl_T0_reg(s, i);
6584
                        gen_ldst(stl, s);
6658
                        tmp = load_reg(s, i);
6659
                        gen_st32(tmp, addr, IS_USER(s));
6585 6660
                    }
6586
                    gen_op_addl_T1_im(4);
6661
                    tcg_gen_addi_i32(addr, addr, 4);
6587 6662
                }
6588 6663
                if (insn & (1 << 21)) {
6589 6664
                    /* Base register writeback.  */
6590 6665
                    if (insn & (1 << 24)) {
6591
                        gen_op_addl_T1_im(-offset);
6666
                        tcg_gen_addi_i32(addr, addr, -offset);
6592 6667
                    }
6593 6668
                    /* Fault if writeback register is in register list.  */
6594 6669
                    if (insn & (1 << rn))
6595 6670
                        goto illegal_op;
6596
                    gen_movl_reg_T1(s, rn);
6671
                    store_reg(s, rn, addr);
6672
                } else {
6673
                    dead_tmp(addr);
6597 6674
                }
6598 6675
            }
6599 6676
        }
......
6892 6969
                offset ^= ((~insn) & (1 << 13)) << 10;
6893 6970
                offset ^= ((~insn) & (1 << 11)) << 11;
6894 6971

  
6895
                addr = s->pc;
6896 6972
                if (insn & (1 << 14)) {
6897 6973
                    /* Branch and link.  */
6898
                    gen_op_movl_T1_im(addr | 1);
6974
                    gen_op_movl_T1_im(s->pc | 1);
6899 6975
                    gen_movl_reg_T1(s, 14);
6900 6976
                }
6901 6977

  
6902
                addr += offset;
6978
                offset += s->pc;
6903 6979
                if (insn & (1 << 12)) {
6904 6980
                    /* b/bl */
6905
                    gen_jmp(s, addr);
6981
                    gen_jmp(s, offset);
6906 6982
                } else {
6907 6983
                    /* blx */
6908
                    addr &= ~(uint32_t)2;
6909
                    gen_bx_im(s, addr);
6984
                    offset &= ~(uint32_t)2;
6985
                    gen_bx_im(s, offset);
6910 6986
                }
6911 6987
            } else if (((insn >> 23) & 7) == 7) {
6912 6988
                /* Misc control */
......
7025 7101
                offset |= (insn & (1 << 11)) << 8;
7026 7102

  
7027 7103
                /* jump to the offset */
7028
                addr = s->pc + offset;
7029
                gen_jmp(s, addr);
7104
                gen_jmp(s, s->pc + offset);
7030 7105
            }
7031 7106
        } else {
7032 7107
            /* Data processing immediate.  */
......
7114 7189
                    } else {
7115 7190
                        /* Add/sub 12-bit immediate.  */
7116 7191
                        if (rn == 15) {
7117
                            addr = s->pc & ~(uint32_t)3;
7192
                            offset = s->pc & ~(uint32_t)3;
7118 7193
                            if (insn & (1 << 23))
7119
                                addr -= imm;
7194
                                offset -= imm;
7120 7195
                            else
7121
                                addr += imm;
7122
                            gen_op_movl_T0_im(addr);
7196
                                offset += imm;
7197
                            gen_op_movl_T0_im(offset);
7123 7198
                        } else {
7124 7199
                            gen_movl_T0_reg(s, rn);
7125 7200
                            gen_op_movl_T1_im(imm);
......
7179 7254
        {
7180 7255
        int postinc = 0;
7181 7256
        int writeback = 0;
7257
        int user;
7182 7258
        if ((insn & 0x01100000) == 0x01000000) {
7183 7259
            if (disas_neon_ls_insn(env, s, insn))
7184 7260
                goto illegal_op;
7185 7261
            break;
7186 7262
        }
7263
        user = IS_USER(s);
7187 7264
        if (rn == 15) {
7265
            addr = new_tmp();
7188 7266
            /* PC relative.  */
7189 7267
            /* s->pc has already been incremented by 4.  */
7190 7268
            imm = s->pc & 0xfffffffc;
......
7192 7270
                imm += insn & 0xfff;
7193 7271
            else
7194 7272
                imm -= insn & 0xfff;
7195
            gen_op_movl_T1_im(imm);
7273
            tcg_gen_movi_i32(addr, imm);
7196 7274
        } else {
7197
            gen_movl_T1_reg(s, rn);
7275
            addr = load_reg(s, rn);
7198 7276
            if (insn & (1 << 23)) {
7199 7277
                /* Positive offset.  */
7200 7278
                imm = insn & 0xfff;
7201
                gen_op_addl_T1_im(imm);
7279
                tcg_gen_addi_i32(addr, addr, imm);
7202 7280
            } else {
7203 7281
                op = (insn >> 8) & 7;
7204 7282
                imm = insn & 0xff;
......
7210 7288
                    tmp = load_reg(s, rm);
7211 7289
                    if (shift)
7212 7290
                        tcg_gen_shli_i32(tmp, tmp, shift);
7213
                    tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
7291
                    tcg_gen_add_i32(addr, addr, tmp);
7214 7292
                    dead_tmp(tmp);
7215 7293
                    break;
7216 7294
                case 4: /* Negative offset.  */
7217
                    gen_op_addl_T1_im(-imm);
7295
                    tcg_gen_addi_i32(addr, addr, -imm);
7218 7296
                    break;
7219 7297
                case 6: /* User privilege.  */
7220
                    gen_op_addl_T1_im(imm);
7298
                    tcg_gen_addi_i32(addr, addr, imm);
7299
                    user = 1;
7221 7300
                    break;
7222 7301
                case 1: /* Post-decrement.  */
7223 7302
                    imm = -imm;
......
7230 7309
                    imm = -imm;
7231 7310
                    /* Fall through.  */
7232 7311
                case 7: /* Pre-increment.  */
7233
                    gen_op_addl_T1_im(imm);
7312
                    tcg_gen_addi_i32(addr, addr, imm);
7234 7313
                    writeback = 1;
7235 7314
                    break;
7236 7315
                default:
......
7247 7326
                /* Memory hint.  Implemented as NOP.  */
7248 7327
            } else {
7249 7328
                switch (op) {
7250
                case 0: gen_ldst(ldub, s); break;
7251
                case 4: gen_ldst(ldsb, s); break;
7252
                case 1: gen_ldst(lduw, s); break;
7253
                case 5: gen_ldst(ldsw, s); break;
7254
                case 2: gen_ldst(ldl, s); break;
7329
                case 0: tmp = gen_ld8u(addr, user); break;
7330
                case 4: tmp = gen_ld8s(addr, user); break;
7331
                case 1: tmp = gen_ld16u(addr, user); break;
7332
                case 5: tmp = gen_ld16s(addr, user); break;
7333
                case 2: tmp = gen_ld32(addr, user); break;
7255 7334
                default: goto illegal_op;
7256 7335
                }
7257 7336
                if (rs == 15) {
7258
                    gen_bx_T0(s);
7337
                    gen_bx(s, tmp);
7259 7338
                } else {
7260
                    gen_movl_reg_T0(s, rs);
7339
                    store_reg(s, rs, tmp);
7261 7340
                }
7262 7341
            }
7263 7342
        } else {
7264 7343
            /* Store.  */
7265 7344
            if (rs == 15)
7266 7345
                goto illegal_op;
7267
            gen_movl_T0_reg(s, rs);
7346
            tmp = load_reg(s, rs);
7268 7347
            switch (op) {
7269
            case 0: gen_ldst(stb, s); break;
7270
            case 1: gen_ldst(stw, s); break;
7271
            case 2: gen_ldst(stl, s); break;
7348
            case 0: gen_st8(tmp, addr, user); break;
7349
            case 1: gen_st16(tmp, addr, user); break;
7350
            case 2: gen_st32(tmp, addr, user); break;
7272 7351
            default: goto illegal_op;
7273 7352
            }
7274 7353
        }
7275 7354
        if (postinc)
7276
            gen_op_addl_T1_im(imm);
7277
        if (writeback)
7278
            gen_movl_reg_T1(s, rn);
7355
            tcg_gen_addi_i32(addr, addr, imm);
7356
        if (writeback) {
7357
            store_reg(s, rn, addr);
7358
        } else {
7359
            dead_tmp(addr);
7360
        }
7279 7361
        }
7280 7362
        break;
7281 7363
    default:
......
7293 7375
    int i;
7294 7376
    TCGv tmp;
7295 7377
    TCGv tmp2;
7378
    TCGv addr;
7296 7379

  
7297 7380
    if (s->condexec_mask) {
7298 7381
        cond = s->condexec_cond;
......
7383 7466
            /* load pc-relative.  Bit 1 of PC is ignored.  */
7384 7467
            val = s->pc + 2 + ((insn & 0xff) * 4);
7385 7468
            val &= ~(uint32_t)2;
7386
            gen_op_movl_T1_im(val);
7387
            gen_ldst(ldl, s);
7388
            gen_movl_reg_T0(s, rd);
7469
            addr = new_tmp();
7470
            tcg_gen_movi_i32(addr, val);
7471
            tmp = gen_ld32(addr, IS_USER(s));
7472
            dead_tmp(addr);
7473
            store_reg(s, rd, tmp);
7389 7474
            break;
7390 7475
        }
7391 7476
        if (insn & (1 << 10)) {
......
7410 7495
                gen_movl_reg_T0(s, rd);
7411 7496
                break;
7412 7497
            case 3:/* branch [and link] exchange thumb register */
7498
                tmp = load_reg(s, rm);
7413 7499
                if (insn & (1 << 7)) {
7414 7500
                    val = (uint32_t)s->pc | 1;
7415
                    gen_op_movl_T1_im(val);
7416
                    gen_movl_reg_T1(s, 14);
7501
                    tmp2 = new_tmp();
7502
                    tcg_gen_movi_i32(tmp2, val);
7503
                    store_reg(s, 14, tmp2);
7417 7504
                }
7418
                tmp = load_reg(s, rm);
7419 7505
                gen_bx(s, tmp);
7420 7506
                break;
7421 7507
            }
......
7553 7639
        rn = (insn >> 3) & 7;
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff