Revision 8e18cde3

b/target-arm/translate.c
2648 2648
    tcg_temp_free_i32(tmp);
2649 2649
}
2650 2650

  
2651
static TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size)
2652
{
2653
    /* Load a single Neon element and replicate into a 32 bit TCG reg */
2654
    TCGv tmp;
2655
    switch (size) {
2656
    case 0:
2657
        tmp = gen_ld8u(addr, IS_USER(s));
2658
        gen_neon_dup_u8(tmp, 0);
2659
        break;
2660
    case 1:
2661
        tmp = gen_ld16u(addr, IS_USER(s));
2662
        gen_neon_dup_low16(tmp);
2663
        break;
2664
    case 2:
2665
        tmp = gen_ld32(addr, IS_USER(s));
2666
        break;
2667
    default: /* Avoid compiler warnings.  */
2668
        abort();
2669
    }
2670
    return tmp;
2671
}
2672

  
2651 2673
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
2652 2674
   (ie. an undefined instruction).  */
2653 2675
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
......
3890 3912
        size = (insn >> 10) & 3;
3891 3913
        if (size == 3) {
3892 3914
            /* Load single element to all lanes.  */
3893
            if (!load)
3915
            int a = (insn >> 4) & 1;
3916
            if (!load) {
3894 3917
                return 1;
3918
            }
3895 3919
            size = (insn >> 6) & 3;
3896 3920
            nregs = ((insn >> 8) & 3) + 1;
3897
            stride = (insn & (1 << 5)) ? 2 : 1;
3898
            load_reg_var(s, addr, rn);
3899
            for (reg = 0; reg < nregs; reg++) {
3900
                switch (size) {
3901
                case 0:
3902
                    tmp = gen_ld8u(addr, IS_USER(s));
3903
                    gen_neon_dup_u8(tmp, 0);
3904
                    break;
3905
                case 1:
3906
                    tmp = gen_ld16u(addr, IS_USER(s));
3907
                    gen_neon_dup_low16(tmp);
3908
                    break;
3909
                case 2:
3910
                    tmp = gen_ld32(addr, IS_USER(s));
3911
                    break;
3912
                case 3:
3921

  
3922
            if (size == 3) {
3923
                if (nregs != 4 || a == 0) {
3913 3924
                    return 1;
3914
                default: /* Avoid compiler warnings.  */
3915
                    abort();
3916 3925
                }
3917
                tcg_gen_addi_i32(addr, addr, 1 << size);
3918
                tmp2 = tcg_temp_new_i32();
3919
                tcg_gen_mov_i32(tmp2, tmp);
3920
                neon_store_reg(rd, 0, tmp2);
3921
                neon_store_reg(rd, 1, tmp);
3922
                rd += stride;
3926
                /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
3927
                size = 2;
3928
            }
3929
            if (nregs == 1 && a == 1 && size == 0) {
3930
                return 1;
3931
            }
3932
            if (nregs == 3 && a == 1) {
3933
                return 1;
3934
            }
3935
            load_reg_var(s, addr, rn);
3936
            if (nregs == 1) {
3937
                /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
3938
                tmp = gen_load_and_replicate(s, addr, size);
3939
                tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
3940
                tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
3941
                if (insn & (1 << 5)) {
3942
                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
3943
                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
3944
                }
3945
                tcg_temp_free_i32(tmp);
3946
            } else {
3947
                /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
3948
                stride = (insn & (1 << 5)) ? 2 : 1;
3949
                for (reg = 0; reg < nregs; reg++) {
3950
                    tmp = gen_load_and_replicate(s, addr, size);
3951
                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
3952
                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
3953
                    tcg_temp_free_i32(tmp);
3954
                    tcg_gen_addi_i32(addr, addr, 1 << size);
3955
                    rd += stride;
3956
                }
3923 3957
            }
3924 3958
            stride = (1 << size) * nregs;
3925 3959
        } else {

Also available in: Unified diff