Revision 52c8b9af target-arm/translate-a64.c

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