mirror of https://github.com/xqemu/xqemu.git
target-xtensa: implement extended L32R
See ISA, 4.3.3 for details. TB flag XTENSA_TBFLAG_LITBASE is used to track enable bit of LITBASE SR. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
797d780b13
commit
6ad6dbf791
|
@ -110,6 +110,7 @@ enum {
|
||||||
LEND = 1,
|
LEND = 1,
|
||||||
LCOUNT = 2,
|
LCOUNT = 2,
|
||||||
SAR = 3,
|
SAR = 3,
|
||||||
|
LITBASE = 5,
|
||||||
SCOMPARE1 = 12,
|
SCOMPARE1 = 12,
|
||||||
WINDOW_BASE = 72,
|
WINDOW_BASE = 72,
|
||||||
WINDOW_START = 73,
|
WINDOW_START = 73,
|
||||||
|
@ -274,6 +275,7 @@ static inline int cpu_mmu_index(CPUState *env)
|
||||||
|
|
||||||
#define XTENSA_TBFLAG_RING_MASK 0x3
|
#define XTENSA_TBFLAG_RING_MASK 0x3
|
||||||
#define XTENSA_TBFLAG_EXCM 0x4
|
#define XTENSA_TBFLAG_EXCM 0x4
|
||||||
|
#define XTENSA_TBFLAG_LITBASE 0x8
|
||||||
|
|
||||||
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)
|
||||||
|
@ -285,6 +287,10 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
|
||||||
if (env->sregs[PS] & PS_EXCM) {
|
if (env->sregs[PS] & PS_EXCM) {
|
||||||
*flags |= XTENSA_TBFLAG_EXCM;
|
*flags |= XTENSA_TBFLAG_EXCM;
|
||||||
}
|
}
|
||||||
|
if (xtensa_option_enabled(env->config, XTENSA_OPTION_EXTENDED_L32R) &&
|
||||||
|
(env->sregs[LITBASE] & 1)) {
|
||||||
|
*flags |= XTENSA_TBFLAG_LITBASE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "cpu-all.h"
|
#include "cpu-all.h"
|
||||||
|
|
|
@ -38,6 +38,7 @@ void cpu_reset(CPUXtensaState *env)
|
||||||
{
|
{
|
||||||
env->exception_taken = 0;
|
env->exception_taken = 0;
|
||||||
env->pc = env->config->exception_vector[EXC_RESET];
|
env->pc = env->config->exception_vector[EXC_RESET];
|
||||||
|
env->sregs[LITBASE] &= ~1;
|
||||||
env->sregs[PS] = 0x1f;
|
env->sregs[PS] = 0x1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ typedef struct DisasContext {
|
||||||
int ring;
|
int ring;
|
||||||
uint32_t lbeg;
|
uint32_t lbeg;
|
||||||
uint32_t lend;
|
uint32_t lend;
|
||||||
|
TCGv_i32 litbase;
|
||||||
int is_jmp;
|
int is_jmp;
|
||||||
int singlestep_enabled;
|
int singlestep_enabled;
|
||||||
|
|
||||||
|
@ -71,6 +72,7 @@ static const char * const sregnames[256] = {
|
||||||
[LEND] = "LEND",
|
[LEND] = "LEND",
|
||||||
[LCOUNT] = "LCOUNT",
|
[LCOUNT] = "LCOUNT",
|
||||||
[SAR] = "SAR",
|
[SAR] = "SAR",
|
||||||
|
[LITBASE] = "LITBASE",
|
||||||
[SCOMPARE1] = "SCOMPARE1",
|
[SCOMPARE1] = "SCOMPARE1",
|
||||||
[WINDOW_BASE] = "WINDOW_BASE",
|
[WINDOW_BASE] = "WINDOW_BASE",
|
||||||
[WINDOW_START] = "WINDOW_START",
|
[WINDOW_START] = "WINDOW_START",
|
||||||
|
@ -132,6 +134,21 @@ static inline bool option_enabled(DisasContext *dc, int opt)
|
||||||
return xtensa_option_enabled(dc->config, opt);
|
return xtensa_option_enabled(dc->config, opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void init_litbase(DisasContext *dc)
|
||||||
|
{
|
||||||
|
if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
|
||||||
|
dc->litbase = tcg_temp_local_new_i32();
|
||||||
|
tcg_gen_andi_i32(dc->litbase, cpu_SR[LITBASE], 0xfffff000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_litbase(DisasContext *dc)
|
||||||
|
{
|
||||||
|
if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
|
||||||
|
tcg_temp_free(dc->litbase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void init_sar_tracker(DisasContext *dc)
|
static void init_sar_tracker(DisasContext *dc)
|
||||||
{
|
{
|
||||||
dc->sar_5bit = false;
|
dc->sar_5bit = false;
|
||||||
|
@ -332,6 +349,13 @@ 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_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s)
|
||||||
|
{
|
||||||
|
tcg_gen_andi_i32(cpu_SR[sr], s, 0xfffff001);
|
||||||
|
/* This can change tb->flags, so exit tb */
|
||||||
|
gen_jumpi_check_loop_end(dc, -1);
|
||||||
|
}
|
||||||
|
|
||||||
static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
|
static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
|
||||||
{
|
{
|
||||||
gen_helper_wsr_windowbase(v);
|
gen_helper_wsr_windowbase(v);
|
||||||
|
@ -357,6 +381,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
|
||||||
[LBEG] = gen_wsr_lbeg,
|
[LBEG] = gen_wsr_lbeg,
|
||||||
[LEND] = gen_wsr_lend,
|
[LEND] = gen_wsr_lend,
|
||||||
[SAR] = gen_wsr_sar,
|
[SAR] = gen_wsr_sar,
|
||||||
|
[LITBASE] = gen_wsr_litbase,
|
||||||
[WINDOW_BASE] = gen_wsr_windowbase,
|
[WINDOW_BASE] = gen_wsr_windowbase,
|
||||||
[PS] = gen_wsr_ps,
|
[PS] = gen_wsr_ps,
|
||||||
};
|
};
|
||||||
|
@ -1298,11 +1323,13 @@ static void disas_xtensa_insn(DisasContext *dc)
|
||||||
case 1: /*L32R*/
|
case 1: /*L32R*/
|
||||||
{
|
{
|
||||||
TCGv_i32 tmp = tcg_const_i32(
|
TCGv_i32 tmp = tcg_const_i32(
|
||||||
(0xfffc0000 | (RI16_IMM16 << 2)) +
|
((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ?
|
||||||
((dc->pc + 3) & ~3));
|
0 : ((dc->pc + 3) & ~3)) +
|
||||||
|
(0xfffc0000 | (RI16_IMM16 << 2)));
|
||||||
/* no ext L32R */
|
|
||||||
|
|
||||||
|
if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
|
||||||
|
tcg_gen_add_i32(tmp, tmp, dc->litbase);
|
||||||
|
}
|
||||||
tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, dc->cring);
|
tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, dc->cring);
|
||||||
tcg_temp_free(tmp);
|
tcg_temp_free(tmp);
|
||||||
}
|
}
|
||||||
|
@ -1834,6 +1861,7 @@ static void gen_intermediate_code_internal(
|
||||||
dc.lend = env->sregs[LEND];
|
dc.lend = env->sregs[LEND];
|
||||||
dc.is_jmp = DISAS_NEXT;
|
dc.is_jmp = DISAS_NEXT;
|
||||||
|
|
||||||
|
init_litbase(&dc);
|
||||||
init_sar_tracker(&dc);
|
init_sar_tracker(&dc);
|
||||||
|
|
||||||
gen_icount_start();
|
gen_icount_start();
|
||||||
|
@ -1876,6 +1904,7 @@ static void gen_intermediate_code_internal(
|
||||||
dc.pc < next_page_start &&
|
dc.pc < next_page_start &&
|
||||||
gen_opc_ptr < gen_opc_end);
|
gen_opc_ptr < gen_opc_end);
|
||||||
|
|
||||||
|
reset_litbase(&dc);
|
||||||
reset_sar_tracker(&dc);
|
reset_sar_tracker(&dc);
|
||||||
|
|
||||||
if (dc.is_jmp == DISAS_NEXT) {
|
if (dc.is_jmp == DISAS_NEXT) {
|
||||||
|
|
Loading…
Reference in New Issue