mirror of https://github.com/xemu-project/xemu.git
target/sparc: Move RDASR, STBAR, MEMBAR to decodetree
Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
3037663616
commit
af25071c1d
|
@ -22,6 +22,28 @@ SETHI 00 rd:5 100 i:22
|
|||
|
||||
CALL 01 i:s30
|
||||
|
||||
{
|
||||
[
|
||||
STBAR 10 00000 101000 01111 0 0000000000000
|
||||
MEMBAR 10 00000 101000 01111 1 000000 cmask:3 mmask:4
|
||||
|
||||
RDCCR 10 rd:5 101000 00010 0 0000000000000
|
||||
RDASI 10 rd:5 101000 00011 0 0000000000000
|
||||
RDTICK 10 rd:5 101000 00100 0 0000000000000
|
||||
RDPC 10 rd:5 101000 00101 0 0000000000000
|
||||
RDFPRS 10 rd:5 101000 00110 0 0000000000000
|
||||
RDASR17 10 rd:5 101000 10001 0 0000000000000
|
||||
RDGSR 10 rd:5 101000 10011 0 0000000000000
|
||||
RDSOFTINT 10 rd:5 101000 10110 0 0000000000000
|
||||
RDTICK_CMPR 10 rd:5 101000 10111 0 0000000000000
|
||||
RDSTICK 10 rd:5 101000 11000 0 0000000000000
|
||||
RDSTICK_CMPR 10 rd:5 101000 11001 0 0000000000000
|
||||
RDSTRAND_STATUS 10 rd:5 101000 11010 0 0000000000000
|
||||
]
|
||||
# Before v8, all rs1 accepted; otherwise rs1==0.
|
||||
RDY 10 rd:5 101000 rs1:5 0 0000000000000
|
||||
}
|
||||
|
||||
Tcc_r 10 0 cond:4 111010 rs1:5 0 cc:1 0000000 rs2:5
|
||||
{
|
||||
# For v7, the entire simm13 field is present, but masked to 7 bits.
|
||||
|
|
|
@ -36,6 +36,11 @@
|
|||
#include "exec/helper-info.c.inc"
|
||||
#undef HELPER_H
|
||||
|
||||
#ifndef TARGET_SPARC64
|
||||
# define gen_helper_rdccr(D, E) qemu_build_not_reached()
|
||||
# define gen_helper_tick_get_count(D, E, T, C) qemu_build_not_reached()
|
||||
#endif
|
||||
|
||||
/* Dynamic PC, must exit to main loop. */
|
||||
#define DYNAMIC_PC 1
|
||||
/* Dynamic PC, one of two values according to jump_pc[T2]. */
|
||||
|
@ -64,10 +69,21 @@ static TCGv cpu_tick_cmpr, cpu_stick_cmpr, cpu_hstick_cmpr;
|
|||
static TCGv cpu_hintp, cpu_htba, cpu_hver, cpu_ssr, cpu_ver;
|
||||
#else
|
||||
static TCGv cpu_wim;
|
||||
# define cpu_fprs ({ qemu_build_not_reached(); (TCGv)NULL; })
|
||||
# define cpu_gsr ({ qemu_build_not_reached(); (TCGv)NULL; })
|
||||
# define cpu_tick_cmpr ({ qemu_build_not_reached(); (TCGv)NULL; })
|
||||
# define cpu_stick_cmpr ({ qemu_build_not_reached(); (TCGv)NULL; })
|
||||
#endif
|
||||
/* Floating point registers */
|
||||
static TCGv_i64 cpu_fpr[TARGET_DPREGS];
|
||||
|
||||
#define env_field_offsetof(X) offsetof(CPUSPARCState, X)
|
||||
#ifdef TARGET_SPARC64
|
||||
# define env64_field_offsetof(X) env_field_offsetof(X)
|
||||
#else
|
||||
# define env64_field_offsetof(X) ({ qemu_build_not_reached(); 0; })
|
||||
#endif
|
||||
|
||||
typedef struct DisasDelayException {
|
||||
struct DisasDelayException *next;
|
||||
TCGLabel *lab;
|
||||
|
@ -2842,10 +2858,14 @@ static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2)
|
|||
#define avail_ALL(C) true
|
||||
#ifdef TARGET_SPARC64
|
||||
# define avail_32(C) false
|
||||
# define avail_ASR17(C) false
|
||||
# define avail_64(C) true
|
||||
# define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV)
|
||||
#else
|
||||
# define avail_32(C) true
|
||||
# define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17)
|
||||
# define avail_64(C) false
|
||||
# define avail_HYPV(C) false
|
||||
#endif
|
||||
|
||||
/* Default case for non jump instructions. */
|
||||
|
@ -2947,6 +2967,12 @@ static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool raise_priv(DisasContext *dc)
|
||||
{
|
||||
gen_exception(dc, TT_PRIV_INSN);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool do_bpcc(DisasContext *dc, arg_bcc *a)
|
||||
{
|
||||
target_long target = address_mask_i(dc, dc->pc + a->i * 4);
|
||||
|
@ -3117,6 +3143,183 @@ static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a)
|
|||
return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i);
|
||||
}
|
||||
|
||||
static bool trans_STBAR(DisasContext *dc, arg_STBAR *a)
|
||||
{
|
||||
tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
|
||||
return advance_pc(dc);
|
||||
}
|
||||
|
||||
static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a)
|
||||
{
|
||||
if (avail_32(dc)) {
|
||||
return false;
|
||||
}
|
||||
if (a->mmask) {
|
||||
/* Note TCG_MO_* was modeled on sparc64, so mmask matches. */
|
||||
tcg_gen_mb(a->mmask | TCG_BAR_SC);
|
||||
}
|
||||
if (a->cmask) {
|
||||
/* For #Sync, etc, end the TB to recognize interrupts. */
|
||||
dc->base.is_jmp = DISAS_EXIT;
|
||||
}
|
||||
return advance_pc(dc);
|
||||
}
|
||||
|
||||
static bool do_rd_special(DisasContext *dc, bool priv, int rd,
|
||||
TCGv (*func)(DisasContext *, TCGv))
|
||||
{
|
||||
if (!priv) {
|
||||
return raise_priv(dc);
|
||||
}
|
||||
gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd)));
|
||||
return advance_pc(dc);
|
||||
}
|
||||
|
||||
static TCGv do_rdy(DisasContext *dc, TCGv dst)
|
||||
{
|
||||
return cpu_y;
|
||||
}
|
||||
|
||||
static bool trans_RDY(DisasContext *dc, arg_RDY *a)
|
||||
{
|
||||
/*
|
||||
* TODO: Need a feature bit for sparcv8. In the meantime, treat all
|
||||
* 32-bit cpus like sparcv7, which ignores the rs1 field.
|
||||
* This matches after all other ASR, so Leon3 Asr17 is handled first.
|
||||
*/
|
||||
if (avail_64(dc) && a->rs1 != 0) {
|
||||
return false;
|
||||
}
|
||||
return do_rd_special(dc, true, a->rd, do_rdy);
|
||||
}
|
||||
|
||||
static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
/*
|
||||
* TODO: There are many more fields to be filled,
|
||||
* some of which are writable.
|
||||
*/
|
||||
val = dc->def->nwindows - 1; /* [4:0] NWIN */
|
||||
val |= 1 << 8; /* [8] V8 */
|
||||
|
||||
return tcg_constant_tl(val);
|
||||
}
|
||||
|
||||
TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config)
|
||||
|
||||
static TCGv do_rdccr(DisasContext *dc, TCGv dst)
|
||||
{
|
||||
update_psr(dc);
|
||||
gen_helper_rdccr(dst, tcg_env);
|
||||
return dst;
|
||||
}
|
||||
|
||||
TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr)
|
||||
|
||||
static TCGv do_rdasi(DisasContext *dc, TCGv dst)
|
||||
{
|
||||
#ifdef TARGET_SPARC64
|
||||
return tcg_constant_tl(dc->asi);
|
||||
#else
|
||||
qemu_build_not_reached();
|
||||
#endif
|
||||
}
|
||||
|
||||
TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi)
|
||||
|
||||
static TCGv do_rdtick(DisasContext *dc, TCGv dst)
|
||||
{
|
||||
TCGv_ptr r_tickptr = tcg_temp_new_ptr();
|
||||
|
||||
tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
|
||||
if (translator_io_start(&dc->base)) {
|
||||
dc->base.is_jmp = DISAS_EXIT;
|
||||
}
|
||||
gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
|
||||
tcg_constant_i32(dc->mem_idx));
|
||||
return dst;
|
||||
}
|
||||
|
||||
/* TODO: non-priv access only allowed when enabled. */
|
||||
TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick)
|
||||
|
||||
static TCGv do_rdpc(DisasContext *dc, TCGv dst)
|
||||
{
|
||||
return tcg_constant_tl(address_mask_i(dc, dc->pc));
|
||||
}
|
||||
|
||||
TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc)
|
||||
|
||||
static TCGv do_rdfprs(DisasContext *dc, TCGv dst)
|
||||
{
|
||||
tcg_gen_ext_i32_tl(dst, cpu_fprs);
|
||||
return dst;
|
||||
}
|
||||
|
||||
TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs)
|
||||
|
||||
static TCGv do_rdgsr(DisasContext *dc, TCGv dst)
|
||||
{
|
||||
gen_trap_ifnofpu(dc);
|
||||
return cpu_gsr;
|
||||
}
|
||||
|
||||
TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr)
|
||||
|
||||
static TCGv do_rdsoftint(DisasContext *dc, TCGv dst)
|
||||
{
|
||||
tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint));
|
||||
return dst;
|
||||
}
|
||||
|
||||
TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint)
|
||||
|
||||
static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst)
|
||||
{
|
||||
return cpu_tick_cmpr;
|
||||
}
|
||||
|
||||
/* TODO: non-priv access only allowed when enabled. */
|
||||
TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr)
|
||||
|
||||
static TCGv do_rdstick(DisasContext *dc, TCGv dst)
|
||||
{
|
||||
TCGv_ptr r_tickptr = tcg_temp_new_ptr();
|
||||
|
||||
tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
|
||||
if (translator_io_start(&dc->base)) {
|
||||
dc->base.is_jmp = DISAS_EXIT;
|
||||
}
|
||||
gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
|
||||
tcg_constant_i32(dc->mem_idx));
|
||||
return dst;
|
||||
}
|
||||
|
||||
/* TODO: non-priv access only allowed when enabled. */
|
||||
TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick)
|
||||
|
||||
static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst)
|
||||
{
|
||||
return cpu_stick_cmpr;
|
||||
}
|
||||
|
||||
/* TODO: supervisor access only allowed when enabled by hypervisor. */
|
||||
TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr)
|
||||
|
||||
/*
|
||||
* UltraSPARC-T1 Strand status.
|
||||
* HYPV check maybe not enough, UA2005 & UA2007 describe
|
||||
* this ASR as impl. dep
|
||||
*/
|
||||
static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst)
|
||||
{
|
||||
return tcg_constant_tl(1);
|
||||
}
|
||||
|
||||
TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status)
|
||||
|
||||
#define CHECK_IU_FEATURE(dc, FEATURE) \
|
||||
if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
|
||||
goto illegal_insn;
|
||||
|
@ -3143,134 +3346,12 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
|
|||
g_assert_not_reached(); /* in decodetree */
|
||||
case 2: /* FPU & Logical Operations */
|
||||
{
|
||||
unsigned int xop = GET_FIELD(insn, 7, 12);
|
||||
TCGv cpu_dst = tcg_temp_new();
|
||||
TCGv cpu_tmp0;
|
||||
unsigned int xop __attribute__((unused)) = GET_FIELD(insn, 7, 12);
|
||||
TCGv cpu_dst __attribute__((unused)) = tcg_temp_new();
|
||||
TCGv cpu_tmp0 __attribute__((unused));
|
||||
|
||||
if (xop == 0x28) {
|
||||
rs1 = GET_FIELD(insn, 13, 17);
|
||||
switch(rs1) {
|
||||
case 0: /* rdy */
|
||||
#ifndef TARGET_SPARC64
|
||||
case 0x01 ... 0x0e: /* undefined in the SPARCv8
|
||||
manual, rdy on the microSPARC
|
||||
II */
|
||||
case 0x0f: /* stbar in the SPARCv8 manual,
|
||||
rdy on the microSPARC II */
|
||||
case 0x10 ... 0x1f: /* implementation-dependent in the
|
||||
SPARCv8 manual, rdy on the
|
||||
microSPARC II */
|
||||
/* Read Asr17 */
|
||||
if (rs1 == 0x11 && dc->def->features & CPU_FEATURE_ASR17) {
|
||||
TCGv t = gen_dest_gpr(dc, rd);
|
||||
/* Read Asr17 for a Leon3 monoprocessor */
|
||||
tcg_gen_movi_tl(t, (1 << 8) | (dc->def->nwindows - 1));
|
||||
gen_store_gpr(dc, rd, t);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
gen_store_gpr(dc, rd, cpu_y);
|
||||
break;
|
||||
#ifdef TARGET_SPARC64
|
||||
case 0x2: /* V9 rdccr */
|
||||
update_psr(dc);
|
||||
gen_helper_rdccr(cpu_dst, tcg_env);
|
||||
gen_store_gpr(dc, rd, cpu_dst);
|
||||
break;
|
||||
case 0x3: /* V9 rdasi */
|
||||
tcg_gen_movi_tl(cpu_dst, dc->asi);
|
||||
gen_store_gpr(dc, rd, cpu_dst);
|
||||
break;
|
||||
case 0x4: /* V9 rdtick */
|
||||
{
|
||||
TCGv_ptr r_tickptr;
|
||||
TCGv_i32 r_const;
|
||||
|
||||
r_tickptr = tcg_temp_new_ptr();
|
||||
r_const = tcg_constant_i32(dc->mem_idx);
|
||||
tcg_gen_ld_ptr(r_tickptr, tcg_env,
|
||||
offsetof(CPUSPARCState, tick));
|
||||
if (translator_io_start(&dc->base)) {
|
||||
dc->base.is_jmp = DISAS_EXIT;
|
||||
}
|
||||
gen_helper_tick_get_count(cpu_dst, tcg_env, r_tickptr,
|
||||
r_const);
|
||||
gen_store_gpr(dc, rd, cpu_dst);
|
||||
}
|
||||
break;
|
||||
case 0x5: /* V9 rdpc */
|
||||
{
|
||||
TCGv t = gen_dest_gpr(dc, rd);
|
||||
if (unlikely(AM_CHECK(dc))) {
|
||||
tcg_gen_movi_tl(t, dc->pc & 0xffffffffULL);
|
||||
} else {
|
||||
tcg_gen_movi_tl(t, dc->pc);
|
||||
}
|
||||
gen_store_gpr(dc, rd, t);
|
||||
}
|
||||
break;
|
||||
case 0x6: /* V9 rdfprs */
|
||||
tcg_gen_ext_i32_tl(cpu_dst, cpu_fprs);
|
||||
gen_store_gpr(dc, rd, cpu_dst);
|
||||
break;
|
||||
case 0xf: /* V9 membar */
|
||||
break; /* no effect */
|
||||
case 0x13: /* Graphics Status */
|
||||
if (gen_trap_ifnofpu(dc)) {
|
||||
goto jmp_insn;
|
||||
}
|
||||
gen_store_gpr(dc, rd, cpu_gsr);
|
||||
break;
|
||||
case 0x16: /* Softint */
|
||||
tcg_gen_ld32s_tl(cpu_dst, tcg_env,
|
||||
offsetof(CPUSPARCState, softint));
|
||||
gen_store_gpr(dc, rd, cpu_dst);
|
||||
break;
|
||||
case 0x17: /* Tick compare */
|
||||
gen_store_gpr(dc, rd, cpu_tick_cmpr);
|
||||
break;
|
||||
case 0x18: /* System tick */
|
||||
{
|
||||
TCGv_ptr r_tickptr;
|
||||
TCGv_i32 r_const;
|
||||
|
||||
r_tickptr = tcg_temp_new_ptr();
|
||||
r_const = tcg_constant_i32(dc->mem_idx);
|
||||
tcg_gen_ld_ptr(r_tickptr, tcg_env,
|
||||
offsetof(CPUSPARCState, stick));
|
||||
if (translator_io_start(&dc->base)) {
|
||||
dc->base.is_jmp = DISAS_EXIT;
|
||||
}
|
||||
gen_helper_tick_get_count(cpu_dst, tcg_env, r_tickptr,
|
||||
r_const);
|
||||
gen_store_gpr(dc, rd, cpu_dst);
|
||||
}
|
||||
break;
|
||||
case 0x19: /* System tick compare */
|
||||
gen_store_gpr(dc, rd, cpu_stick_cmpr);
|
||||
break;
|
||||
case 0x1a: /* UltraSPARC-T1 Strand status */
|
||||
/* XXX HYPV check maybe not enough, UA2005 & UA2007 describe
|
||||
* this ASR as impl. dep
|
||||
*/
|
||||
CHECK_IU_FEATURE(dc, HYPV);
|
||||
{
|
||||
TCGv t = gen_dest_gpr(dc, rd);
|
||||
tcg_gen_movi_tl(t, 1UL);
|
||||
gen_store_gpr(dc, rd, t);
|
||||
}
|
||||
break;
|
||||
case 0x10: /* Performance Control */
|
||||
case 0x11: /* Performance Instrumentation Counter */
|
||||
case 0x12: /* Dispatch Control */
|
||||
case 0x14: /* Softint set, WO */
|
||||
case 0x15: /* Softint clear, WO */
|
||||
#endif
|
||||
default:
|
||||
goto illegal_insn;
|
||||
}
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
} else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
|
||||
if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */
|
||||
#ifndef TARGET_SPARC64
|
||||
if (!supervisor(dc)) {
|
||||
goto priv_insn;
|
||||
|
@ -3308,7 +3389,8 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
|
|||
#endif
|
||||
gen_store_gpr(dc, rd, cpu_dst);
|
||||
break;
|
||||
} else if (xop == 0x2a) { /* rdwim / V9 rdpr */
|
||||
}
|
||||
if (xop == 0x2a) { /* rdwim / V9 rdpr */
|
||||
if (!supervisor(dc)) {
|
||||
goto priv_insn;
|
||||
}
|
||||
|
@ -3432,9 +3514,10 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
|
|||
#endif
|
||||
gen_store_gpr(dc, rd, cpu_tmp0);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)
|
||||
} else if (xop == 0x2b) { /* rdtbr / V9 flushw */
|
||||
if (xop == 0x2b) { /* rdtbr / V9 flushw */
|
||||
#ifdef TARGET_SPARC64
|
||||
gen_helper_flushw(tcg_env);
|
||||
#else
|
||||
|
@ -3443,8 +3526,9 @@ static void disas_sparc_legacy(DisasContext *dc, unsigned int insn)
|
|||
gen_store_gpr(dc, rd, cpu_tbr);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
} else if (xop == 0x34) { /* FPU Operations */
|
||||
if (xop == 0x34) { /* FPU Operations */
|
||||
if (gen_trap_ifnofpu(dc)) {
|
||||
goto jmp_insn;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue