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>
This commit is contained in:
Claudio Fontana 2013-12-17 19:42:32 +00:00 committed by Peter Maydell
parent ad7ee8a290
commit 87462e0f41
1 changed files with 129 additions and 2 deletions

View File

@ -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)
{