target-xtensa: add PS register and access control
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
8ffc2d0d97
commit
f0a548b93d
|
@ -108,8 +108,27 @@ enum {
|
||||||
enum {
|
enum {
|
||||||
SAR = 3,
|
SAR = 3,
|
||||||
SCOMPARE1 = 12,
|
SCOMPARE1 = 12,
|
||||||
|
PS = 230,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define PS_INTLEVEL 0xf
|
||||||
|
#define PS_INTLEVEL_SHIFT 0
|
||||||
|
|
||||||
|
#define PS_EXCM 0x10
|
||||||
|
#define PS_UM 0x20
|
||||||
|
|
||||||
|
#define PS_RING 0xc0
|
||||||
|
#define PS_RING_SHIFT 6
|
||||||
|
|
||||||
|
#define PS_OWB 0xf00
|
||||||
|
#define PS_OWB_SHIFT 8
|
||||||
|
|
||||||
|
#define PS_CALLINC 0x30000
|
||||||
|
#define PS_CALLINC_SHIFT 16
|
||||||
|
#define PS_CALLINC_LEN 2
|
||||||
|
|
||||||
|
#define PS_WOE 0x40000
|
||||||
|
|
||||||
typedef struct XtensaConfig {
|
typedef struct XtensaConfig {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint64_t options;
|
uint64_t options;
|
||||||
|
@ -145,17 +164,49 @@ static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
|
||||||
return (config->options & XTENSA_OPTION_BIT(opt)) != 0;
|
return (config->options & XTENSA_OPTION_BIT(opt)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int xtensa_get_ring(const CPUState *env)
|
||||||
|
{
|
||||||
|
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
|
||||||
|
return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int xtensa_get_cring(const CPUState *env)
|
||||||
|
{
|
||||||
|
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) &&
|
||||||
|
(env->sregs[PS] & PS_EXCM) == 0) {
|
||||||
|
return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MMU modes definitions */
|
||||||
|
#define MMU_MODE0_SUFFIX _ring0
|
||||||
|
#define MMU_MODE1_SUFFIX _ring1
|
||||||
|
#define MMU_MODE2_SUFFIX _ring2
|
||||||
|
#define MMU_MODE3_SUFFIX _ring3
|
||||||
|
|
||||||
static inline int cpu_mmu_index(CPUState *env)
|
static inline int cpu_mmu_index(CPUState *env)
|
||||||
{
|
{
|
||||||
return 0;
|
return xtensa_get_cring(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define XTENSA_TBFLAG_RING_MASK 0x3
|
||||||
|
#define XTENSA_TBFLAG_EXCM 0x4
|
||||||
|
|
||||||
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
|
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
|
||||||
target_ulong *cs_base, int *flags)
|
target_ulong *cs_base, int *flags)
|
||||||
{
|
{
|
||||||
*pc = env->pc;
|
*pc = env->pc;
|
||||||
*cs_base = 0;
|
*cs_base = 0;
|
||||||
*flags = 0;
|
*flags = 0;
|
||||||
|
*flags |= xtensa_get_ring(env);
|
||||||
|
if (env->sregs[PS] & PS_EXCM) {
|
||||||
|
*flags |= XTENSA_TBFLAG_EXCM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "cpu-all.h"
|
#include "cpu-all.h"
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
void cpu_reset(CPUXtensaState *env)
|
void cpu_reset(CPUXtensaState *env)
|
||||||
{
|
{
|
||||||
env->pc = 0;
|
env->pc = 0;
|
||||||
|
env->sregs[PS] = 0x1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const XtensaConfig core_config[] = {
|
static const XtensaConfig core_config[] = {
|
||||||
|
|
|
@ -45,6 +45,8 @@ typedef struct DisasContext {
|
||||||
TranslationBlock *tb;
|
TranslationBlock *tb;
|
||||||
uint32_t pc;
|
uint32_t pc;
|
||||||
uint32_t next_pc;
|
uint32_t next_pc;
|
||||||
|
int cring;
|
||||||
|
int ring;
|
||||||
int is_jmp;
|
int is_jmp;
|
||||||
int singlestep_enabled;
|
int singlestep_enabled;
|
||||||
|
|
||||||
|
@ -65,6 +67,7 @@ static TCGv_i32 cpu_UR[256];
|
||||||
static const char * const sregnames[256] = {
|
static const char * const sregnames[256] = {
|
||||||
[SAR] = "SAR",
|
[SAR] = "SAR",
|
||||||
[SCOMPARE1] = "SCOMPARE1",
|
[SCOMPARE1] = "SCOMPARE1",
|
||||||
|
[PS] = "PS",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const uregnames[256] = {
|
static const char * const uregnames[256] = {
|
||||||
|
@ -239,11 +242,25 @@ static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
|
||||||
dc->sar_m32_5bit = false;
|
dc->sar_m32_5bit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
|
||||||
|
{
|
||||||
|
uint32_t mask = PS_WOE | PS_CALLINC | PS_OWB |
|
||||||
|
PS_UM | PS_EXCM | PS_INTLEVEL;
|
||||||
|
|
||||||
|
if (option_enabled(dc, XTENSA_OPTION_MMU)) {
|
||||||
|
mask |= PS_RING;
|
||||||
|
}
|
||||||
|
tcg_gen_andi_i32(cpu_SR[sr], v, mask);
|
||||||
|
/* This can change mmu index, so exit tb */
|
||||||
|
gen_jumpi(dc, dc->next_pc, -1);
|
||||||
|
}
|
||||||
|
|
||||||
static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
|
static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
|
||||||
{
|
{
|
||||||
static void (* const wsr_handler[256])(DisasContext *dc,
|
static void (* const wsr_handler[256])(DisasContext *dc,
|
||||||
uint32_t sr, TCGv_i32 v) = {
|
uint32_t sr, TCGv_i32 v) = {
|
||||||
[SAR] = gen_wsr_sar,
|
[SAR] = gen_wsr_sar,
|
||||||
|
[PS] = gen_wsr_ps,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sregnames[sr]) {
|
if (sregnames[sr]) {
|
||||||
|
@ -973,7 +990,7 @@ static void disas_xtensa_insn(DisasContext *dc)
|
||||||
|
|
||||||
/* no ext L32R */
|
/* no ext L32R */
|
||||||
|
|
||||||
tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, 0);
|
tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, dc->cring);
|
||||||
tcg_temp_free(tmp);
|
tcg_temp_free(tmp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -982,7 +999,7 @@ static void disas_xtensa_insn(DisasContext *dc)
|
||||||
#define gen_load_store(type, shift) do { \
|
#define gen_load_store(type, shift) do { \
|
||||||
TCGv_i32 addr = tcg_temp_new_i32(); \
|
TCGv_i32 addr = tcg_temp_new_i32(); \
|
||||||
tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
|
tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
|
||||||
tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, 0); \
|
tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
|
||||||
tcg_temp_free(addr); \
|
tcg_temp_free(addr); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1140,11 +1157,11 @@ static void disas_xtensa_insn(DisasContext *dc)
|
||||||
|
|
||||||
tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);
|
tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);
|
||||||
tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
|
tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
|
||||||
tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, 0);
|
tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring);
|
||||||
tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],
|
tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],
|
||||||
cpu_SR[SCOMPARE1], label);
|
cpu_SR[SCOMPARE1], label);
|
||||||
|
|
||||||
tcg_gen_qemu_st32(tmp, addr, 0);
|
tcg_gen_qemu_st32(tmp, addr, dc->cring);
|
||||||
|
|
||||||
gen_set_label(label);
|
gen_set_label(label);
|
||||||
tcg_temp_free(addr);
|
tcg_temp_free(addr);
|
||||||
|
@ -1345,7 +1362,7 @@ static void disas_xtensa_insn(DisasContext *dc)
|
||||||
#define gen_narrow_load_store(type) do { \
|
#define gen_narrow_load_store(type) do { \
|
||||||
TCGv_i32 addr = tcg_temp_new_i32(); \
|
TCGv_i32 addr = tcg_temp_new_i32(); \
|
||||||
tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
|
tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
|
||||||
tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, 0); \
|
tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, dc->cring); \
|
||||||
tcg_temp_free(addr); \
|
tcg_temp_free(addr); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1468,6 +1485,8 @@ static void gen_intermediate_code_internal(
|
||||||
dc.singlestep_enabled = env->singlestep_enabled;
|
dc.singlestep_enabled = env->singlestep_enabled;
|
||||||
dc.tb = tb;
|
dc.tb = tb;
|
||||||
dc.pc = pc_start;
|
dc.pc = pc_start;
|
||||||
|
dc.ring = tb->flags & XTENSA_TBFLAG_RING_MASK;
|
||||||
|
dc.cring = (tb->flags & XTENSA_TBFLAG_EXCM) ? 0 : dc.ring;
|
||||||
dc.is_jmp = DISAS_NEXT;
|
dc.is_jmp = DISAS_NEXT;
|
||||||
|
|
||||||
init_sar_tracker(&dc);
|
init_sar_tracker(&dc);
|
||||||
|
|
Reference in New Issue