target-arm: A64: add support for move wide instructions

This patch adds emulation for the mov wide instructions
(MOVN, MOVZ, MOVK).

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Alex Bennée 2013-12-23 23:27:29 +00:00 committed by Peter Maydell
parent b0ff21b4f9
commit ed6ec679a8

View File

@ -1644,10 +1644,57 @@ static void disas_logic_imm(DisasContext *s, uint32_t insn)
}
}
/* Move wide (immediate) */
/*
* C3.4.5 Move wide (immediate)
*
* 31 30 29 28 23 22 21 20 5 4 0
* +--+-----+-------------+-----+----------------+------+
* |sf| opc | 1 0 0 1 0 1 | hw | imm16 | Rd |
* +--+-----+-------------+-----+----------------+------+
*
* sf: 0 -> 32 bit, 1 -> 64 bit
* opc: 00 -> N, 10 -> Z, 11 -> K
* hw: shift/16 (0,16, and sf only 32, 48)
*/
static void disas_movw_imm(DisasContext *s, uint32_t insn)
{
unsupported_encoding(s, insn);
int rd = extract32(insn, 0, 5);
uint64_t imm = extract32(insn, 5, 16);
int sf = extract32(insn, 31, 1);
int opc = extract32(insn, 29, 2);
int pos = extract32(insn, 21, 2) << 4;
TCGv_i64 tcg_rd = cpu_reg(s, rd);
TCGv_i64 tcg_imm;
if (!sf && (pos >= 32)) {
unallocated_encoding(s);
return;
}
switch (opc) {
case 0: /* MOVN */
case 2: /* MOVZ */
imm <<= pos;
if (opc == 0) {
imm = ~imm;
}
if (!sf) {
imm &= 0xffffffffu;
}
tcg_gen_movi_i64(tcg_rd, imm);
break;
case 3: /* MOVK */
tcg_imm = tcg_const_i64(imm);
tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_imm, pos, 16);
tcg_temp_free_i64(tcg_imm);
if (!sf) {
tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
}
break;
default:
unallocated_encoding(s);
break;
}
}
/* C3.4.2 Bitfield