mirror of https://github.com/xemu-project/xemu.git
158 lines
4.6 KiB
C++
158 lines
4.6 KiB
C++
/*
|
|
* Power ISA decode for misc instructions
|
|
*
|
|
* Copyright (c) 2024, IBM Corporation.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/*
|
|
* Memory Barrier Instructions
|
|
*/
|
|
|
|
static bool trans_SYNC(DisasContext *ctx, arg_X_sync *a)
|
|
{
|
|
TCGBar bar = TCG_MO_ALL;
|
|
uint32_t l = a->l;
|
|
uint32_t sc = a->sc;
|
|
|
|
/*
|
|
* BookE uses the msync mnemonic. This means hwsync, except in the
|
|
* 440, where it an execution serialisation point that requires all
|
|
* previous storage accesses to have been performed to memory (which
|
|
* doesn't matter for TCG).
|
|
*/
|
|
if (!(ctx->insns_flags & PPC_MEM_SYNC)) {
|
|
if (ctx->insns_flags & PPC_BOOKE) {
|
|
tcg_gen_mb(bar | TCG_BAR_SC);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* In ISA v3.1, the L field grew one bit. Mask that out to ignore it in
|
|
* older processors. It also added the SC field, zero this to ignore
|
|
* it too.
|
|
*/
|
|
if (!(ctx->insns_flags2 & PPC2_ISA310)) {
|
|
l &= 0x3;
|
|
sc = 0;
|
|
}
|
|
|
|
if (sc) {
|
|
/* Store syncs [stsync, stcisync, stncisync]. These ignore L. */
|
|
bar = TCG_MO_ST_ST;
|
|
} else {
|
|
if (((l == 1) && (ctx->insns_flags2 & PPC2_MEM_LWSYNC)) || (l == 5)) {
|
|
/* lwsync, or plwsync on POWER10 and later */
|
|
bar = TCG_MO_LD_LD | TCG_MO_LD_ST | TCG_MO_ST_ST;
|
|
}
|
|
|
|
/*
|
|
* We may need to check for a pending TLB flush.
|
|
*
|
|
* We do this on ptesync (l == 2) on ppc64 and any sync on ppc32.
|
|
*
|
|
* Additionally, this can only happen in kernel mode however so
|
|
* check MSR_PR as well.
|
|
*/
|
|
if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) {
|
|
gen_check_tlb_flush(ctx, true);
|
|
}
|
|
}
|
|
|
|
tcg_gen_mb(bar | TCG_BAR_SC);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool trans_EIEIO(DisasContext *ctx, arg_EIEIO *a)
|
|
{
|
|
TCGBar bar = TCG_MO_ALL;
|
|
|
|
/*
|
|
* BookE uses the mbar instruction instead of eieio, which is basically
|
|
* full hwsync memory barrier, but is not execution synchronising. For
|
|
* the purpose of TCG the distinction is not relevant.
|
|
*/
|
|
if (!(ctx->insns_flags & PPC_MEM_EIEIO)) {
|
|
if ((ctx->insns_flags & PPC_BOOKE) ||
|
|
(ctx->insns_flags2 & PPC2_BOOKE206)) {
|
|
tcg_gen_mb(bar | TCG_BAR_SC);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* eieio has complex semanitcs. It provides memory ordering between
|
|
* operations in the set:
|
|
* - loads from CI memory.
|
|
* - stores to CI memory.
|
|
* - stores to WT memory.
|
|
*
|
|
* It separately also orders memory for operations in the set:
|
|
* - stores to cacheble memory.
|
|
*
|
|
* It also serializes instructions:
|
|
* - dcbt and dcbst.
|
|
*
|
|
* It separately serializes:
|
|
* - tlbie and tlbsync.
|
|
*
|
|
* And separately serializes:
|
|
* - slbieg, slbiag, and slbsync.
|
|
*
|
|
* The end result is that CI memory ordering requires TCG_MO_ALL
|
|
* and it is not possible to special-case more relaxed ordering for
|
|
* cacheable accesses. TCG_BAR_SC is required to provide this
|
|
* serialization.
|
|
*/
|
|
|
|
/*
|
|
* POWER9 has a eieio instruction variant using bit 6 as a hint to
|
|
* tell the CPU it is a store-forwarding barrier.
|
|
*/
|
|
if (ctx->opcode & 0x2000000) {
|
|
/*
|
|
* ISA says that "Reserved fields in instructions are ignored
|
|
* by the processor". So ignore the bit 6 on non-POWER9 CPU but
|
|
* as this is not an instruction software should be using,
|
|
* complain to the user.
|
|
*/
|
|
if (!(ctx->insns_flags2 & PPC2_ISA300)) {
|
|
qemu_log_mask(LOG_GUEST_ERROR, "invalid eieio using bit 6 at @"
|
|
TARGET_FMT_lx "\n", ctx->cia);
|
|
} else {
|
|
bar = TCG_MO_ST_LD;
|
|
}
|
|
}
|
|
|
|
tcg_gen_mb(bar | TCG_BAR_SC);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool trans_ATTN(DisasContext *ctx, arg_ATTN *a)
|
|
{
|
|
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
|
|
gen_helper_attn(tcg_env);
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|