target/microblaze: Convert mbar to decodetree

Split this out of the normal branch instructions,
as it requires special handling.

Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2020-08-23 09:38:15 -07:00
parent f523531471
commit ee8c7f9f9a
2 changed files with 49 additions and 38 deletions

View File

@ -127,6 +127,8 @@ lwea 110010 ..... ..... ..... 0001 000 0000 @typea
lwx 110010 ..... ..... ..... 1000 000 0000 @typea
lwi 111010 ..... ..... ................ @typeb
mbar 101110 imm:5 00010 0000 0000 0000 0100
mul 010000 ..... ..... ..... 000 0000 0000 @typea
mulh 010000 ..... ..... ..... 000 0000 0001 @typea
mulhu 010000 ..... ..... ..... 000 0000 0011 @typea

View File

@ -1127,6 +1127,52 @@ static bool trans_brki(DisasContext *dc, arg_typeb_br *arg)
return true;
}
static bool trans_mbar(DisasContext *dc, arg_mbar *arg)
{
int mbar_imm = arg->imm;
/* Data access memory barrier. */
if ((mbar_imm & 2) == 0) {
tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
}
/* Sleep. */
if (mbar_imm & 16) {
TCGv_i32 tmp_1;
if (trap_userspace(dc, true)) {
/* Sleep is a privileged instruction. */
return true;
}
t_sync_flags(dc);
tmp_1 = tcg_const_i32(1);
tcg_gen_st_i32(tmp_1, cpu_env,
-offsetof(MicroBlazeCPU, env)
+offsetof(CPUState, halted));
tcg_temp_free_i32(tmp_1);
tcg_gen_movi_i32(cpu_pc, dc->base.pc_next + 4);
gen_raise_exception(dc, EXCP_HLT);
}
/*
* If !(mbar_imm & 1), this is an instruction access memory barrier
* and we need to end the TB so that we recognize self-modified
* code immediately.
*
* However, there are some data mbars that need the TB break
* (and return to main loop) to recognize interrupts right away.
* E.g. recognizing a change to an interrupt controller register.
*
* Therefore, choose to end the TB always.
*/
dc->cpustate_changed = 1;
return true;
}
static bool trans_zero(DisasContext *dc, arg_zero *arg)
{
/* If opcode_0_illegal, trap. */
@ -1417,50 +1463,13 @@ static void dec_bcc(DisasContext *dc)
static void dec_br(DisasContext *dc)
{
unsigned int dslot, link, abs, mbar;
unsigned int dslot, link, abs;
uint32_t add_pc;
dslot = dc->ir & (1 << 20);
abs = dc->ir & (1 << 19);
link = dc->ir & (1 << 18);
/* Memory barrier. */
mbar = (dc->ir >> 16) & 31;
if (mbar == 2 && dc->imm == 4) {
uint16_t mbar_imm = dc->rd;
/* Data access memory barrier. */
if ((mbar_imm & 2) == 0) {
tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
}
/* mbar IMM & 16 decodes to sleep. */
if (mbar_imm & 16) {
TCGv_i32 tmp_1;
if (trap_userspace(dc, true)) {
/* Sleep is a privileged instruction. */
return;
}
t_sync_flags(dc);
tmp_1 = tcg_const_i32(1);
tcg_gen_st_i32(tmp_1, cpu_env,
-offsetof(MicroBlazeCPU, env)
+offsetof(CPUState, halted));
tcg_temp_free_i32(tmp_1);
tcg_gen_movi_i32(cpu_pc, dc->base.pc_next + 4);
gen_raise_exception(dc, EXCP_HLT);
return;
}
/* Break the TB. */
dc->cpustate_changed = 1;
return;
}
if (dslot) {
dec_setup_dslot(dc);
}