Skip to content

Commit

Permalink
target/microblaze: Convert mbar to decodetree
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
rth7680 committed Sep 1, 2020
1 parent f523531 commit ee8c7f9
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 38 deletions.
2 changes: 2 additions & 0 deletions target/microblaze/insns.decode
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
85 changes: 47 additions & 38 deletions target/microblaze/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit ee8c7f9

Please sign in to comment.