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:
parent
ad7ee8a290
commit
87462e0f41
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user