Revision 52c8b9af
b/target-arm/translate-a64.c | ||
---|---|---|
2128 | 2128 |
tcg_temp_free_i64(tcg_result); |
2129 | 2129 |
} |
2130 | 2130 |
|
2131 |
/* Data-processing (3 source) */ |
|
2131 |
/* C3.5.9 Data-processing (3 source) |
|
2132 |
|
|
2133 |
31 30 29 28 24 23 21 20 16 15 14 10 9 5 4 0 |
|
2134 |
+--+------+-----------+------+------+----+------+------+------+ |
|
2135 |
|sf| op54 | 1 1 0 1 1 | op31 | Rm | o0 | Ra | Rn | Rd | |
|
2136 |
+--+------+-----------+------+------+----+------+------+------+ |
|
2137 |
|
|
2138 |
*/ |
|
2132 | 2139 |
static void disas_data_proc_3src(DisasContext *s, uint32_t insn) |
2133 | 2140 |
{ |
2134 |
unsupported_encoding(s, insn); |
|
2141 |
int rd = extract32(insn, 0, 5); |
|
2142 |
int rn = extract32(insn, 5, 5); |
|
2143 |
int ra = extract32(insn, 10, 5); |
|
2144 |
int rm = extract32(insn, 16, 5); |
|
2145 |
int op_id = (extract32(insn, 29, 3) << 4) | |
|
2146 |
(extract32(insn, 21, 3) << 1) | |
|
2147 |
extract32(insn, 15, 1); |
|
2148 |
bool sf = extract32(insn, 31, 1); |
|
2149 |
bool is_sub = extract32(op_id, 0, 1); |
|
2150 |
bool is_high = extract32(op_id, 2, 1); |
|
2151 |
bool is_signed = false; |
|
2152 |
TCGv_i64 tcg_op1; |
|
2153 |
TCGv_i64 tcg_op2; |
|
2154 |
TCGv_i64 tcg_tmp; |
|
2155 |
|
|
2156 |
/* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */ |
|
2157 |
switch (op_id) { |
|
2158 |
case 0x42: /* SMADDL */ |
|
2159 |
case 0x43: /* SMSUBL */ |
|
2160 |
case 0x44: /* SMULH */ |
|
2161 |
is_signed = true; |
|
2162 |
break; |
|
2163 |
case 0x0: /* MADD (32bit) */ |
|
2164 |
case 0x1: /* MSUB (32bit) */ |
|
2165 |
case 0x40: /* MADD (64bit) */ |
|
2166 |
case 0x41: /* MSUB (64bit) */ |
|
2167 |
case 0x4a: /* UMADDL */ |
|
2168 |
case 0x4b: /* UMSUBL */ |
|
2169 |
case 0x4c: /* UMULH */ |
|
2170 |
break; |
|
2171 |
default: |
|
2172 |
unallocated_encoding(s); |
|
2173 |
return; |
|
2174 |
} |
|
2175 |
|
|
2176 |
if (is_high) { |
|
2177 |
TCGv_i64 low_bits = tcg_temp_new_i64(); /* low bits discarded */ |
|
2178 |
TCGv_i64 tcg_rd = cpu_reg(s, rd); |
|
2179 |
TCGv_i64 tcg_rn = cpu_reg(s, rn); |
|
2180 |
TCGv_i64 tcg_rm = cpu_reg(s, rm); |
|
2181 |
|
|
2182 |
if (is_signed) { |
|
2183 |
tcg_gen_muls2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm); |
|
2184 |
} else { |
|
2185 |
tcg_gen_mulu2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm); |
|
2186 |
} |
|
2187 |
|
|
2188 |
tcg_temp_free_i64(low_bits); |
|
2189 |
return; |
|
2190 |
} |
|
2191 |
|
|
2192 |
tcg_op1 = tcg_temp_new_i64(); |
|
2193 |
tcg_op2 = tcg_temp_new_i64(); |
|
2194 |
tcg_tmp = tcg_temp_new_i64(); |
|
2195 |
|
|
2196 |
if (op_id < 0x42) { |
|
2197 |
tcg_gen_mov_i64(tcg_op1, cpu_reg(s, rn)); |
|
2198 |
tcg_gen_mov_i64(tcg_op2, cpu_reg(s, rm)); |
|
2199 |
} else { |
|
2200 |
if (is_signed) { |
|
2201 |
tcg_gen_ext32s_i64(tcg_op1, cpu_reg(s, rn)); |
|
2202 |
tcg_gen_ext32s_i64(tcg_op2, cpu_reg(s, rm)); |
|
2203 |
} else { |
|
2204 |
tcg_gen_ext32u_i64(tcg_op1, cpu_reg(s, rn)); |
|
2205 |
tcg_gen_ext32u_i64(tcg_op2, cpu_reg(s, rm)); |
|
2206 |
} |
|
2207 |
} |
|
2208 |
|
|
2209 |
if (ra == 31 && !is_sub) { |
|
2210 |
/* Special-case MADD with rA == XZR; it is the standard MUL alias */ |
|
2211 |
tcg_gen_mul_i64(cpu_reg(s, rd), tcg_op1, tcg_op2); |
|
2212 |
} else { |
|
2213 |
tcg_gen_mul_i64(tcg_tmp, tcg_op1, tcg_op2); |
|
2214 |
if (is_sub) { |
|
2215 |
tcg_gen_sub_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp); |
|
2216 |
} else { |
|
2217 |
tcg_gen_add_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp); |
|
2218 |
} |
|
2219 |
} |
|
2220 |
|
|
2221 |
if (!sf) { |
|
2222 |
tcg_gen_ext32u_i64(cpu_reg(s, rd), cpu_reg(s, rd)); |
|
2223 |
} |
|
2224 |
|
|
2225 |
tcg_temp_free_i64(tcg_op1); |
|
2226 |
tcg_temp_free_i64(tcg_op2); |
|
2227 |
tcg_temp_free_i64(tcg_tmp); |
|
2135 | 2228 |
} |
2136 | 2229 |
|
2137 | 2230 |
/* Add/subtract (with carry) */ |
Also available in: Unified diff