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