mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
target/arm: Convert hint instruction space to decodetree
Convert the various instructions in the hint instruction space to decodetree. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20230602155223.2040685-3-peter.maydell@linaro.org
This commit is contained in:
parent
68496d4172
commit
7fefc70661
2 changed files with 185 additions and 123 deletions
|
@ -150,3 +150,34 @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
|
||||||
# the processor is in halting debug state (which we don't implement).
|
# the processor is in halting debug state (which we don't implement).
|
||||||
# The pattern is listed here as documentation.
|
# The pattern is listed here as documentation.
|
||||||
# DRPS 1101011 0101 11111 000000 11111 00000
|
# DRPS 1101011 0101 11111 000000 11111 00000
|
||||||
|
|
||||||
|
# Hint instruction group
|
||||||
|
{
|
||||||
|
[
|
||||||
|
YIELD 1101 0101 0000 0011 0010 0000 001 11111
|
||||||
|
WFE 1101 0101 0000 0011 0010 0000 010 11111
|
||||||
|
WFI 1101 0101 0000 0011 0010 0000 011 11111
|
||||||
|
# We implement WFE to never block, so our SEV/SEVL are NOPs
|
||||||
|
# SEV 1101 0101 0000 0011 0010 0000 100 11111
|
||||||
|
# SEVL 1101 0101 0000 0011 0010 0000 101 11111
|
||||||
|
# Our DGL is a NOP because we don't merge memory accesses anyway.
|
||||||
|
# DGL 1101 0101 0000 0011 0010 0000 110 11111
|
||||||
|
XPACLRI 1101 0101 0000 0011 0010 0000 111 11111
|
||||||
|
PACIA1716 1101 0101 0000 0011 0010 0001 000 11111
|
||||||
|
PACIB1716 1101 0101 0000 0011 0010 0001 010 11111
|
||||||
|
AUTIA1716 1101 0101 0000 0011 0010 0001 100 11111
|
||||||
|
AUTIB1716 1101 0101 0000 0011 0010 0001 110 11111
|
||||||
|
ESB 1101 0101 0000 0011 0010 0010 000 11111
|
||||||
|
PACIAZ 1101 0101 0000 0011 0010 0011 000 11111
|
||||||
|
PACIASP 1101 0101 0000 0011 0010 0011 001 11111
|
||||||
|
PACIBZ 1101 0101 0000 0011 0010 0011 010 11111
|
||||||
|
PACIBSP 1101 0101 0000 0011 0010 0011 011 11111
|
||||||
|
AUTIAZ 1101 0101 0000 0011 0010 0011 100 11111
|
||||||
|
AUTIASP 1101 0101 0000 0011 0010 0011 101 11111
|
||||||
|
AUTIBZ 1101 0101 0000 0011 0010 0011 110 11111
|
||||||
|
AUTIBSP 1101 0101 0000 0011 0010 0011 111 11111
|
||||||
|
]
|
||||||
|
# The canonical NOP has CRm == op2 == 0, but all of the space
|
||||||
|
# that isn't specifically allocated to an instruction must NOP
|
||||||
|
NOP 1101 0101 0000 0011 0010 ---- --- 11111
|
||||||
|
}
|
||||||
|
|
|
@ -1649,25 +1649,15 @@ static bool trans_ERETA(DisasContext *s, arg_reta *a)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HINT instruction group, including various allocated HINTs */
|
static bool trans_NOP(DisasContext *s, arg_NOP *a)
|
||||||
static void handle_hint(DisasContext *s, uint32_t insn,
|
|
||||||
unsigned int op1, unsigned int op2, unsigned int crm)
|
|
||||||
{
|
{
|
||||||
unsigned int selector = crm << 3 | op2;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (op1 != 3) {
|
static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
|
||||||
unallocated_encoding(s);
|
{
|
||||||
return;
|
/*
|
||||||
}
|
* When running in MTTCG we don't generate jumps to the yield and
|
||||||
|
|
||||||
switch (selector) {
|
|
||||||
case 0b00000: /* NOP */
|
|
||||||
break;
|
|
||||||
case 0b00011: /* WFI */
|
|
||||||
s->base.is_jmp = DISAS_WFI;
|
|
||||||
break;
|
|
||||||
case 0b00001: /* YIELD */
|
|
||||||
/* When running in MTTCG we don't generate jumps to the yield and
|
|
||||||
* WFE helpers as it won't affect the scheduling of other vCPUs.
|
* WFE helpers as it won't affect the scheduling of other vCPUs.
|
||||||
* If we wanted to more completely model WFE/SEV so we don't busy
|
* If we wanted to more completely model WFE/SEV so we don't busy
|
||||||
* spin unnecessarily we would need to do something more involved.
|
* spin unnecessarily we would need to do something more involved.
|
||||||
|
@ -1675,43 +1665,71 @@ static void handle_hint(DisasContext *s, uint32_t insn,
|
||||||
if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
|
if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
|
||||||
s->base.is_jmp = DISAS_YIELD;
|
s->base.is_jmp = DISAS_YIELD;
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b00010: /* WFE */
|
}
|
||||||
|
|
||||||
|
static bool trans_WFI(DisasContext *s, arg_WFI *a)
|
||||||
|
{
|
||||||
|
s->base.is_jmp = DISAS_WFI;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool trans_WFE(DisasContext *s, arg_WFI *a)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* When running in MTTCG we don't generate jumps to the yield and
|
||||||
|
* WFE helpers as it won't affect the scheduling of other vCPUs.
|
||||||
|
* If we wanted to more completely model WFE/SEV so we don't busy
|
||||||
|
* spin unnecessarily we would need to do something more involved.
|
||||||
|
*/
|
||||||
if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
|
if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
|
||||||
s->base.is_jmp = DISAS_WFE;
|
s->base.is_jmp = DISAS_WFE;
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b00100: /* SEV */
|
}
|
||||||
case 0b00101: /* SEVL */
|
|
||||||
case 0b00110: /* DGH */
|
static bool trans_XPACLRI(DisasContext *s, arg_XPACLRI *a)
|
||||||
/* we treat all as NOP at least for now */
|
{
|
||||||
break;
|
|
||||||
case 0b00111: /* XPACLRI */
|
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_xpaci(cpu_X[30], cpu_env, cpu_X[30]);
|
gen_helper_xpaci(cpu_X[30], cpu_env, cpu_X[30]);
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b01000: /* PACIA1716 */
|
}
|
||||||
|
|
||||||
|
static bool trans_PACIA1716(DisasContext *s, arg_PACIA1716 *a)
|
||||||
|
{
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_pacia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
|
gen_helper_pacia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b01010: /* PACIB1716 */
|
}
|
||||||
|
|
||||||
|
static bool trans_PACIB1716(DisasContext *s, arg_PACIB1716 *a)
|
||||||
|
{
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_pacib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
|
gen_helper_pacib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b01100: /* AUTIA1716 */
|
}
|
||||||
|
|
||||||
|
static bool trans_AUTIA1716(DisasContext *s, arg_AUTIA1716 *a)
|
||||||
|
{
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_autia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
|
gen_helper_autia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b01110: /* AUTIB1716 */
|
}
|
||||||
|
|
||||||
|
static bool trans_AUTIB1716(DisasContext *s, arg_AUTIB1716 *a)
|
||||||
|
{
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_autib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
|
gen_helper_autib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b10000: /* ESB */
|
}
|
||||||
|
|
||||||
|
static bool trans_ESB(DisasContext *s, arg_ESB *a)
|
||||||
|
{
|
||||||
/* Without RAS, we must implement this as NOP. */
|
/* Without RAS, we must implement this as NOP. */
|
||||||
if (dc_isar_feature(aa64_ras, s)) {
|
if (dc_isar_feature(aa64_ras, s)) {
|
||||||
/*
|
/*
|
||||||
|
@ -1727,55 +1745,71 @@ static void handle_hint(DisasContext *s, uint32_t insn,
|
||||||
gen_helper_vesb(cpu_env);
|
gen_helper_vesb(cpu_env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b11000: /* PACIAZ */
|
}
|
||||||
|
|
||||||
|
static bool trans_PACIAZ(DisasContext *s, arg_PACIAZ *a)
|
||||||
|
{
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30],
|
gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
|
||||||
tcg_constant_i64(0));
|
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b11001: /* PACIASP */
|
}
|
||||||
|
|
||||||
|
static bool trans_PACIASP(DisasContext *s, arg_PACIASP *a)
|
||||||
|
{
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
|
gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b11010: /* PACIBZ */
|
}
|
||||||
|
|
||||||
|
static bool trans_PACIBZ(DisasContext *s, arg_PACIBZ *a)
|
||||||
|
{
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30],
|
gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
|
||||||
tcg_constant_i64(0));
|
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b11011: /* PACIBSP */
|
}
|
||||||
|
|
||||||
|
static bool trans_PACIBSP(DisasContext *s, arg_PACIBSP *a)
|
||||||
|
{
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
|
gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b11100: /* AUTIAZ */
|
}
|
||||||
|
|
||||||
|
static bool trans_AUTIAZ(DisasContext *s, arg_AUTIAZ *a)
|
||||||
|
{
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30],
|
gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
|
||||||
tcg_constant_i64(0));
|
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b11101: /* AUTIASP */
|
}
|
||||||
|
|
||||||
|
static bool trans_AUTIASP(DisasContext *s, arg_AUTIASP *a)
|
||||||
|
{
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
|
gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b11110: /* AUTIBZ */
|
}
|
||||||
|
|
||||||
|
static bool trans_AUTIBZ(DisasContext *s, arg_AUTIBZ *a)
|
||||||
|
{
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30],
|
gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], tcg_constant_i64(0));
|
||||||
tcg_constant_i64(0));
|
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
case 0b11111: /* AUTIBSP */
|
}
|
||||||
|
|
||||||
|
static bool trans_AUTIBSP(DisasContext *s, arg_AUTIBSP *a)
|
||||||
|
{
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
|
gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
|
||||||
}
|
}
|
||||||
break;
|
return true;
|
||||||
default:
|
|
||||||
/* default specified as NOP equivalent */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_clrex(DisasContext *s, uint32_t insn)
|
static void gen_clrex(DisasContext *s, uint32_t insn)
|
||||||
|
@ -2302,9 +2336,6 @@ static void disas_system(DisasContext *s, uint32_t insn)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (crn) {
|
switch (crn) {
|
||||||
case 2: /* HINT (including allocated hints like NOP, YIELD, etc) */
|
|
||||||
handle_hint(s, insn, op1, op2, crm);
|
|
||||||
break;
|
|
||||||
case 3: /* CLREX, DSB, DMB, ISB */
|
case 3: /* CLREX, DSB, DMB, ISB */
|
||||||
handle_sync(s, insn, op1, op2, crm);
|
handle_sync(s, insn, op1, op2, crm);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue