diff options
author | Claudio Fontana <claudio.fontana@linaro.org> | 2013-12-17 19:42:32 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2013-12-17 19:42:32 +0000 |
commit | 87462e0f41fccc353f9c902caed563ab7cbdd8ed (patch) | |
tree | aad41097ea2f30dcf7cfbb19dab823dc0443373a /target-arm | |
parent | ad7ee8a290d08a2fe9d408af2461d1f583d96f7d (diff) |
target-arm: A64: expand decoding skeleton for system instructions
Decode the various kinds of system instructions:
hints (HINT), which include NOP, YIELD, WFE, WFI, SEV, SEL
sync instructions, which include CLREX, DSB, DMB, ISB
msr_i, which move immediate to processor state field
sys, which include all SYS and SYSL instructions
msr, which move from a gp register to a system register
mrs, which move from a system register to a gp register
Provide implementations where they are trivial nops.
Signed-off-by: Claudio Fontana <claudio.fontana@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target-arm')
-rw-r--r-- | target-arm/translate-a64.c | 131 |
1 files changed, 129 insertions, 2 deletions
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 8e16cb1a1c..1e2b371d4b 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -190,12 +190,139 @@ static void disas_cond_b_imm(DisasContext *s, uint32_t insn) unsupported_encoding(s, insn); } -/* System */ -static void disas_system(DisasContext *s, uint32_t insn) +/* C5.6.68 HINT */ +static void handle_hint(DisasContext *s, uint32_t insn, + unsigned int op1, unsigned int op2, unsigned int crm) +{ + unsigned int selector = crm << 3 | op2; + + if (op1 != 3) { + unallocated_encoding(s); + return; + } + + switch (selector) { + case 0: /* NOP */ + return; + case 1: /* YIELD */ + case 2: /* WFE */ + case 3: /* WFI */ + case 4: /* SEV */ + case 5: /* SEVL */ + /* we treat all as NOP at least for now */ + return; + default: + /* default specified as NOP equivalent */ + return; + } +} + +/* CLREX, DSB, DMB, ISB */ +static void handle_sync(DisasContext *s, uint32_t insn, + unsigned int op1, unsigned int op2, unsigned int crm) +{ + if (op1 != 3) { + unallocated_encoding(s); + return; + } + + switch (op2) { + case 2: /* CLREX */ + unsupported_encoding(s, insn); + return; + case 4: /* DSB */ + case 5: /* DMB */ + case 6: /* ISB */ + /* We don't emulate caches so barriers are no-ops */ + return; + default: + unallocated_encoding(s); + return; + } +} + +/* C5.6.130 MSR (immediate) - move immediate to processor state field */ +static void handle_msr_i(DisasContext *s, uint32_t insn, + unsigned int op1, unsigned int op2, unsigned int crm) { unsupported_encoding(s, insn); } +/* C5.6.204 SYS */ +static void handle_sys(DisasContext *s, uint32_t insn, unsigned int l, + unsigned int op1, unsigned int op2, + unsigned int crn, unsigned int crm, unsigned int rt) +{ + unsupported_encoding(s, insn); +} + +/* C5.6.129 MRS - move from system register */ +static void handle_mrs(DisasContext *s, uint32_t insn, unsigned int op0, + unsigned int op1, unsigned int op2, + unsigned int crn, unsigned int crm, unsigned int rt) +{ + unsupported_encoding(s, insn); +} + +/* C5.6.131 MSR (register) - move to system register */ +static void handle_msr(DisasContext *s, uint32_t insn, unsigned int op0, + unsigned int op1, unsigned int op2, + unsigned int crn, unsigned int crm, unsigned int rt) +{ + unsupported_encoding(s, insn); +} + +/* C3.2.4 System + * 31 22 21 20 19 18 16 15 12 11 8 7 5 4 0 + * +---------------------+---+-----+-----+-------+-------+-----+------+ + * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 | CRn | CRm | op2 | Rt | + * +---------------------+---+-----+-----+-------+-------+-----+------+ + */ +static void disas_system(DisasContext *s, uint32_t insn) +{ + unsigned int l, op0, op1, crn, crm, op2, rt; + l = extract32(insn, 21, 1); + op0 = extract32(insn, 19, 2); + op1 = extract32(insn, 16, 3); + crn = extract32(insn, 12, 4); + crm = extract32(insn, 8, 4); + op2 = extract32(insn, 5, 3); + rt = extract32(insn, 0, 5); + + if (op0 == 0) { + if (l || rt != 31) { + unallocated_encoding(s); + return; + } + switch (crn) { + case 2: /* C5.6.68 HINT */ + handle_hint(s, insn, op1, op2, crm); + break; + case 3: /* CLREX, DSB, DMB, ISB */ + handle_sync(s, insn, op1, op2, crm); + break; + case 4: /* C5.6.130 MSR (immediate) */ + handle_msr_i(s, insn, op1, op2, crm); + break; + default: + unallocated_encoding(s); + break; + } + return; + } + + if (op0 == 1) { + /* C5.6.204 SYS */ + handle_sys(s, insn, l, op1, op2, crn, crm, rt); + } else if (l) { /* op0 > 1 */ + /* C5.6.129 MRS - move from system register */ + handle_mrs(s, insn, op0, op1, op2, crn, crm, rt); + } else { + /* C5.6.131 MSR (register) - move to system register */ + handle_msr(s, insn, op0, op1, op2, crn, crm, rt); + } +} + /* Exception generation */ static void disas_exc(DisasContext *s, uint32_t insn) { |