mirror of https://gitee.com/openkylin/qemu.git
target/microblaze: Convert dec_bit to decodetree
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:
parent
e98651d9ca
commit
39cf386458
|
@ -17,6 +17,7 @@
|
|||
# License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
&typea0 rd ra
|
||||
&typea rd ra rb
|
||||
&typeb rd ra imm
|
||||
|
||||
|
@ -26,6 +27,9 @@
|
|||
@typea ...... rd:5 ra:5 rb:5 ... .... .... &typea
|
||||
@typeb ...... rd:5 ra:5 ................ &typeb imm=%extimm
|
||||
|
||||
# Officially typea, but with rb==0, which is not used.
|
||||
@typea0 ...... rd:5 ra:5 ................ &typea0
|
||||
|
||||
###
|
||||
|
||||
{
|
||||
|
@ -47,6 +51,8 @@ andi 101001 ..... ..... ................ @typeb
|
|||
andn 100011 ..... ..... ..... 000 0000 0000 @typea
|
||||
andni 101011 ..... ..... ................ @typeb
|
||||
|
||||
clz 100100 ..... ..... 00000 000 1110 0000 @typea0
|
||||
|
||||
cmp 000101 ..... ..... ..... 000 0000 0001 @typea
|
||||
cmpu 000101 ..... ..... ..... 000 0000 0011 @typea
|
||||
|
||||
|
@ -76,5 +82,19 @@ rsubic 001011 ..... ..... ................ @typeb
|
|||
rsubik 001101 ..... ..... ................ @typeb
|
||||
rsubikc 001111 ..... ..... ................ @typeb
|
||||
|
||||
sext8 100100 ..... ..... 00000 000 0110 0000 @typea0
|
||||
sext16 100100 ..... ..... 00000 000 0110 0001 @typea0
|
||||
|
||||
sra 100100 ..... ..... 00000 000 0000 0001 @typea0
|
||||
src 100100 ..... ..... 00000 000 0010 0001 @typea0
|
||||
srl 100100 ..... ..... 00000 000 0100 0001 @typea0
|
||||
|
||||
swapb 100100 ..... ..... 00000 001 1110 0000 @typea0
|
||||
swaph 100100 ..... ..... 00000 001 1110 0010 @typea0
|
||||
|
||||
# Cache operations have no effect in qemu: discard the arguments.
|
||||
wdic 100100 00000 ----- ----- -00 -11- 01-0 # wdc
|
||||
wdic 100100 00000 ----- ----- 000 0110 1000 # wic
|
||||
|
||||
xor 100010 ..... ..... ..... 000 0000 0000 @typea
|
||||
xori 101010 ..... ..... ................ @typeb
|
||||
|
|
|
@ -241,6 +241,21 @@ static bool do_typea(DisasContext *dc, arg_typea *arg, bool side_effects,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool do_typea0(DisasContext *dc, arg_typea0 *arg, bool side_effects,
|
||||
void (*fn)(TCGv_i32, TCGv_i32))
|
||||
{
|
||||
TCGv_i32 rd, ra;
|
||||
|
||||
if (arg->rd == 0 && !side_effects) {
|
||||
return true;
|
||||
}
|
||||
|
||||
rd = reg_for_write(dc, arg->rd);
|
||||
ra = reg_for_read(dc, arg->ra);
|
||||
fn(rd, ra);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool do_typeb_imm(DisasContext *dc, arg_typeb *arg, bool side_effects,
|
||||
void (*fni)(TCGv_i32, TCGv_i32, int32_t))
|
||||
{
|
||||
|
@ -283,6 +298,14 @@ static bool do_typeb_val(DisasContext *dc, arg_typeb *arg, bool side_effects,
|
|||
static bool trans_##NAME(DisasContext *dc, arg_typea *a) \
|
||||
{ return dc->cpu->cfg.CFG && do_typea(dc, a, SE, FN); }
|
||||
|
||||
#define DO_TYPEA0(NAME, SE, FN) \
|
||||
static bool trans_##NAME(DisasContext *dc, arg_typea0 *a) \
|
||||
{ return do_typea0(dc, a, SE, FN); }
|
||||
|
||||
#define DO_TYPEA0_CFG(NAME, CFG, SE, FN) \
|
||||
static bool trans_##NAME(DisasContext *dc, arg_typea0 *a) \
|
||||
{ return dc->cpu->cfg.CFG && do_typea0(dc, a, SE, FN); }
|
||||
|
||||
#define DO_TYPEBI(NAME, SE, FNI) \
|
||||
static bool trans_##NAME(DisasContext *dc, arg_typeb *a) \
|
||||
{ return do_typeb_imm(dc, a, SE, FNI); }
|
||||
|
@ -345,6 +368,13 @@ DO_TYPEBI(andi, false, tcg_gen_andi_i32)
|
|||
DO_TYPEA(andn, false, tcg_gen_andc_i32)
|
||||
DO_TYPEBI(andni, false, gen_andni)
|
||||
|
||||
static void gen_clz(TCGv_i32 out, TCGv_i32 ina)
|
||||
{
|
||||
tcg_gen_clzi_i32(out, ina, 32);
|
||||
}
|
||||
|
||||
DO_TYPEA0_CFG(clz, use_pcmp_instr, false, gen_clz)
|
||||
|
||||
static void gen_cmp(TCGv_i32 out, TCGv_i32 ina, TCGv_i32 inb)
|
||||
{
|
||||
TCGv_i32 lt = tcg_temp_new_i32();
|
||||
|
@ -474,6 +504,51 @@ DO_TYPEBV(rsubic, true, gen_rsubc)
|
|||
DO_TYPEBV(rsubik, false, gen_rsubk)
|
||||
DO_TYPEBV(rsubikc, true, gen_rsubkc)
|
||||
|
||||
DO_TYPEA0(sext8, false, tcg_gen_ext8s_i32)
|
||||
DO_TYPEA0(sext16, false, tcg_gen_ext16s_i32)
|
||||
|
||||
static void gen_sra(TCGv_i32 out, TCGv_i32 ina)
|
||||
{
|
||||
tcg_gen_andi_i32(cpu_msr_c, ina, 1);
|
||||
tcg_gen_sari_i32(out, ina, 1);
|
||||
}
|
||||
|
||||
static void gen_src(TCGv_i32 out, TCGv_i32 ina)
|
||||
{
|
||||
TCGv_i32 tmp = tcg_temp_new_i32();
|
||||
|
||||
tcg_gen_mov_i32(tmp, cpu_msr_c);
|
||||
tcg_gen_andi_i32(cpu_msr_c, ina, 1);
|
||||
tcg_gen_extract2_i32(out, ina, tmp, 1);
|
||||
|
||||
tcg_temp_free_i32(tmp);
|
||||
}
|
||||
|
||||
static void gen_srl(TCGv_i32 out, TCGv_i32 ina)
|
||||
{
|
||||
tcg_gen_andi_i32(cpu_msr_c, ina, 1);
|
||||
tcg_gen_shri_i32(out, ina, 1);
|
||||
}
|
||||
|
||||
DO_TYPEA0(sra, false, gen_sra)
|
||||
DO_TYPEA0(src, false, gen_src)
|
||||
DO_TYPEA0(srl, false, gen_srl)
|
||||
|
||||
static void gen_swaph(TCGv_i32 out, TCGv_i32 ina)
|
||||
{
|
||||
tcg_gen_rotri_i32(out, ina, 16);
|
||||
}
|
||||
|
||||
DO_TYPEA0(swapb, false, tcg_gen_bswap32_i32)
|
||||
DO_TYPEA0(swaph, false, gen_swaph)
|
||||
|
||||
static bool trans_wdic(DisasContext *dc, arg_wdic *a)
|
||||
{
|
||||
/* Cache operations are nops: only check for supervisor mode. */
|
||||
trap_userspace(dc, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
DO_TYPEA(xor, false, tcg_gen_xor_i32)
|
||||
DO_TYPEBI(xori, false, tcg_gen_xori_i32)
|
||||
|
||||
|
@ -754,78 +829,6 @@ static void dec_barrel(DisasContext *dc)
|
|||
}
|
||||
}
|
||||
|
||||
static void dec_bit(DisasContext *dc)
|
||||
{
|
||||
CPUState *cs = CPU(dc->cpu);
|
||||
TCGv_i32 t0;
|
||||
unsigned int op;
|
||||
|
||||
op = dc->ir & ((1 << 9) - 1);
|
||||
switch (op) {
|
||||
case 0x21:
|
||||
/* src. */
|
||||
t0 = tcg_temp_new_i32();
|
||||
|
||||
tcg_gen_shli_i32(t0, cpu_msr_c, 31);
|
||||
tcg_gen_andi_i32(cpu_msr_c, cpu_R[dc->ra], 1);
|
||||
if (dc->rd) {
|
||||
tcg_gen_shri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 1);
|
||||
tcg_gen_or_i32(cpu_R[dc->rd], cpu_R[dc->rd], t0);
|
||||
}
|
||||
tcg_temp_free_i32(t0);
|
||||
break;
|
||||
|
||||
case 0x1:
|
||||
case 0x41:
|
||||
/* srl. */
|
||||
tcg_gen_andi_i32(cpu_msr_c, cpu_R[dc->ra], 1);
|
||||
if (dc->rd) {
|
||||
if (op == 0x41)
|
||||
tcg_gen_shri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 1);
|
||||
else
|
||||
tcg_gen_sari_i32(cpu_R[dc->rd], cpu_R[dc->ra], 1);
|
||||
}
|
||||
break;
|
||||
case 0x60:
|
||||
tcg_gen_ext8s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
|
||||
break;
|
||||
case 0x61:
|
||||
tcg_gen_ext16s_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
|
||||
break;
|
||||
case 0x64:
|
||||
case 0x66:
|
||||
case 0x74:
|
||||
case 0x76:
|
||||
/* wdc. */
|
||||
trap_userspace(dc, true);
|
||||
break;
|
||||
case 0x68:
|
||||
/* wic. */
|
||||
trap_userspace(dc, true);
|
||||
break;
|
||||
case 0xe0:
|
||||
if (trap_illegal(dc, !dc->cpu->cfg.use_pcmp_instr)) {
|
||||
return;
|
||||
}
|
||||
if (dc->cpu->cfg.use_pcmp_instr) {
|
||||
tcg_gen_clzi_i32(cpu_R[dc->rd], cpu_R[dc->ra], 32);
|
||||
}
|
||||
break;
|
||||
case 0x1e0:
|
||||
/* swapb */
|
||||
tcg_gen_bswap32_i32(cpu_R[dc->rd], cpu_R[dc->ra]);
|
||||
break;
|
||||
case 0x1e2:
|
||||
/*swaph */
|
||||
tcg_gen_rotri_i32(cpu_R[dc->rd], cpu_R[dc->ra], 16);
|
||||
break;
|
||||
default:
|
||||
cpu_abort(cs, "unknown bit oc=%x op=%x rd=%d ra=%d rb=%d\n",
|
||||
(uint32_t)dc->base.pc_next, op, dc->rd, dc->ra, dc->rb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void sync_jmpstate(DisasContext *dc)
|
||||
{
|
||||
if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
|
||||
|
@ -1548,7 +1551,6 @@ static struct decoder_info {
|
|||
};
|
||||
void (*dec)(DisasContext *dc);
|
||||
} decinfo[] = {
|
||||
{DEC_BIT, dec_bit},
|
||||
{DEC_BARREL, dec_barrel},
|
||||
{DEC_LD, dec_load},
|
||||
{DEC_ST, dec_store},
|
||||
|
|
Loading…
Reference in New Issue