Revision a5e94a9d target-arm/translate-a64.c

b/target-arm/translate-a64.c
950 950
}
951 951

  
952 952
/*
953
 * C3.3.8 Load/store (immediate post-indexed)
954
 * C3.3.9 Load/store (immediate pre-indexed)
955
 * C3.3.12 Load/store (unscaled immediate)
956
 *
957
 * 31 30 29   27  26 25 24 23 22 21  20    12 11 10 9    5 4    0
958
 * +----+-------+---+-----+-----+---+--------+-----+------+------+
959
 * |size| 1 1 1 | V | 0 0 | opc | 0 |  imm9  | idx |  Rn  |  Rt  |
960
 * +----+-------+---+-----+-----+---+--------+-----+------+------+
961
 *
962
 * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
963
 * V = 0 -> non-vector
964
 * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
965
 * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
966
 */
967
static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn)
968
{
969
    int rt = extract32(insn, 0, 5);
970
    int rn = extract32(insn, 5, 5);
971
    int imm9 = sextract32(insn, 12, 9);
972
    int opc = extract32(insn, 22, 2);
973
    int size = extract32(insn, 30, 2);
974
    int idx = extract32(insn, 10, 2);
975
    bool is_signed = false;
976
    bool is_store = false;
977
    bool is_extended = false;
978
    bool is_vector = extract32(insn, 26, 1);
979
    bool post_index;
980
    bool writeback;
981

  
982
    TCGv_i64 tcg_addr;
983

  
984
    if (is_vector) {
985
        size |= (opc & 2) << 1;
986
        if (size > 4) {
987
            unallocated_encoding(s);
988
            return;
989
        }
990
        is_store = ((opc & 1) == 0);
991
    } else {
992
        if (size == 3 && opc == 2) {
993
            /* PRFM - prefetch */
994
            return;
995
        }
996
        if (opc == 3 && size > 1) {
997
            unallocated_encoding(s);
998
            return;
999
        }
1000
        is_store = (opc == 0);
1001
        is_signed = opc & (1<<1);
1002
        is_extended = (size < 3) && (opc & 1);
1003
    }
1004

  
1005
    switch (idx) {
1006
    case 0:
1007
        post_index = false;
1008
        writeback = false;
1009
        break;
1010
    case 1:
1011
        post_index = true;
1012
        writeback = true;
1013
        break;
1014
    case 3:
1015
        post_index = false;
1016
        writeback = true;
1017
        break;
1018
    case 2:
1019
        g_assert(false);
1020
        break;
1021
    }
1022

  
1023
    if (rn == 31) {
1024
        gen_check_sp_alignment(s);
1025
    }
1026
    tcg_addr = read_cpu_reg_sp(s, rn, 1);
1027

  
1028
    if (!post_index) {
1029
        tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
1030
    }
1031

  
1032
    if (is_vector) {
1033
        if (is_store) {
1034
            do_fp_st(s, rt, tcg_addr, size);
1035
        } else {
1036
            do_fp_ld(s, rt, tcg_addr, size);
1037
        }
1038
    } else {
1039
        TCGv_i64 tcg_rt = cpu_reg(s, rt);
1040
        if (is_store) {
1041
            do_gpr_st(s, tcg_rt, tcg_addr, size);
1042
        } else {
1043
            do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
1044
        }
1045
    }
1046

  
1047
    if (writeback) {
1048
        TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
1049
        if (post_index) {
1050
            tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
1051
        }
1052
        tcg_gen_mov_i64(tcg_rn, tcg_addr);
1053
    }
1054
}
1055

  
1056
/*
953 1057
 * C3.3.10 Load/store (register offset)
954 1058
 *
955 1059
 * 31 30 29   27  26 25 24 23 22 21  20  16 15 13 12 11 10 9  5 4  0
......
1116 1220
    }
1117 1221
}
1118 1222

  
1223
/* Load/store register (immediate forms) */
1224
static void disas_ldst_reg_imm(DisasContext *s, uint32_t insn)
1225
{
1226
    switch (extract32(insn, 10, 2)) {
1227
    case 0: case 1: case 3:
1228
        /* Load/store register (unscaled immediate) */
1229
        /* Load/store immediate pre/post-indexed */
1230
        disas_ldst_reg_imm9(s, insn);
1231
        break;
1232
    case 2:
1233
        /* Load/store register unprivileged */
1234
        unsupported_encoding(s, insn);
1235
        break;
1236
    default:
1237
        unallocated_encoding(s);
1238
        break;
1239
    }
1240
}
1241

  
1119 1242
/* Load/store register (all forms) */
1120 1243
static void disas_ldst_reg(DisasContext *s, uint32_t insn)
1121 1244
{
......
1124 1247
        if (extract32(insn, 21, 1) == 1 && extract32(insn, 10, 2) == 2) {
1125 1248
            disas_ldst_reg_roffset(s, insn);
1126 1249
        } else {
1127
            unsupported_encoding(s, insn);
1250
            disas_ldst_reg_imm(s, insn);
1128 1251
        }
1129 1252
        break;
1130 1253
    case 1:

Also available in: Unified diff