target: e2k: Read NR in gdb.

This commit is contained in:
Denis Drakhnia 2020-11-23 08:14:26 +02:00 committed by Alibek Omarov
parent 47905d5d35
commit 5b828e999f
8 changed files with 198 additions and 124 deletions

View File

@ -45,7 +45,7 @@ void cpu_loop(CPUE2KState *env)
queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
break;
case E2K_EXCP_SYSCALL: {
int wbs = e2k_state_wbs_get(env);
int wbs = e2k_state_cr1_wbs_get(env);
int offset = wbs * 2;
uint64_t *regs = env->wregs;
abi_ulong ret = do_syscall(env,

View File

@ -43,9 +43,17 @@ static void e2k_cpu_reset(DeviceState *dev)
memset(env, 0, offsetof(CPUE2KState, end_reset_fields));
env->wptr = &env->wregs[0];
// FIXME: testing
env->cr1_lo = 0x4dUL << 56; // FIXME: some flags for testing
env->cr1_lo = SET_FIELD(env->cr1_lo, 4, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_LEN);
env->cr1_lo = SET_FIELD(env->cr1_lo, 4, CR1_LO_WBS_OFF, CR1_LO_WBS_LEN);
env->wd_base = 0;
env->wd_size = 8;
env->wd_psize = 8;
env->boff = 8;
env->bsize = 8;
env->bcur = 0;
}
static bool e2k_cpu_exec_interrupt(CPUState *cs, int interrupt_request)

View File

@ -57,7 +57,7 @@ void e2k_tcg_initialize(void);
#define WD_PSIZE_END 42
#define WD_PSIZE_LEN (WD_PSIZE_END - WD_PSIZE_OFF + 1)
#define WD_FX_OFF 48
#define WD_FX_BIT (1 << WD_FX_OFF)
#define WD_FX_BIT (1UL << WD_FX_OFF)
#define PCSP_HI_IND_OFF 0 /* index for SPILL */
#define PCSP_HI_IND_END 31
@ -210,16 +210,12 @@ typedef struct {
uint64_t gregs[GREGS_SIZE]; /* global registers */
uint64_t wregs[WREGS_SIZE]; /* window registers */
uint64_t *wptr;
uint64_t pf; /* predicate file */
/* Procedure chain info = cr0_lo, cr0_hi, cr1_lo, cr1_hi */
uint64_t pcsp_lo;
uint64_t pcsp_hi;
/* cr0_lo == pf */
/* cr0_hi == ip */
uint64_t cr1_lo;
uint64_t cr1_hi;
uint64_t pcshtp;
uint32_t br;
/* Procedure stack pointer (for regs) */
uint64_t psp_lo;
@ -244,8 +240,22 @@ typedef struct {
target_ulong ctprs[3]; // Control Transfer Preparation Register (CTPR)
target_ulong ct_cond;
/* special registers */
target_ulong ip; /* instruction address */
union {
struct {
union {
uint64_t pf; /* predicate file */
uint64_t cr0_lo;
};
union {
target_ulong ip; /* instruction address */
uint64_t cr0_hi;
};
uint64_t cr1_lo;
uint64_t cr1_hi;
};
uint64_t proc_chain[4];
};
target_ulong nip; /* next instruction address */
uint32_t pfpfr; // Packed Floating Point Flag Register (PFPFR)
@ -253,6 +263,7 @@ typedef struct {
uint32_t fpsr; // Floating point state register (FPSR)
int interrupt_index;
uint32_t is_bp; /* breakpoint flag */
/* Fields up to this point are cleared by a CPU reset */
struct {} end_reset_fields;
@ -340,26 +351,35 @@ static inline void e2k_state_ps_ind_set(CPUE2KState *env, size_t ind)
env->psp_hi = SET_FIELD(env->psp_hi, ind, PSP_HI_IND_OFF, PSP_HI_IND_LEN);
}
static inline int e2k_state_wbs_get(CPUE2KState *env)
static inline int e2k_state_cr1_wbs_get(CPUE2KState *env)
{
return GET_FIELD(env->cr1_lo, CR1_LO_WBS_OFF, CR1_LO_WBS_END);
}
static inline void e2k_state_wbs_set(CPUE2KState *env, int wbs)
static inline void e2k_state_cr1_wbs_set(CPUE2KState *env, int wbs)
{
env->cr1_lo = SET_FIELD(env->cr1_lo, wbs,
CR1_LO_WBS_OFF, CR1_LO_WBS_LEN);
env->cr1_lo = SET_FIELD(env->cr1_lo, wbs, CR1_LO_WBS_OFF, CR1_LO_WBS_LEN);
}
static inline int e2k_state_wpsz_get(CPUE2KState *env)
static inline int e2k_state_cr1_wpsz_get(CPUE2KState *env)
{
return GET_FIELD(env->cr1_lo, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_END);
}
static inline void e2k_state_wpsz_set(CPUE2KState *env, int wsz)
static inline void e2k_state_cr1_wpsz_set(CPUE2KState *env, int wpsz)
{
env->cr1_lo = SET_FIELD(env->cr1_lo, wsz,
CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_LEN);
env->cr1_lo = SET_FIELD(env->cr1_lo, wpsz, CR1_LO_WPSZ_OFF,
CR1_LO_WPSZ_LEN);
}
static inline uint32_t e2k_state_cr1_br_get(CPUE2KState *env)
{
return GET_FIELD(env->cr1_hi, CR1_HI_BR_OFF, CR1_HI_BR_END);
}
static inline void e2k_state_cr1_br_set(CPUE2KState *env, uint32_t br)
{
env->cr1_hi = SET_FIELD(env->cr1_hi, br, CR1_HI_BR_OFF, CR1_HI_BR_LEN);
}
typedef CPUE2KState CPUArchState;

View File

@ -27,11 +27,14 @@
int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
{
E2KCPU *cpu = E2K_CPU(cs);
CPUClass *cc = CPU_GET_CLASS(cs);
// CPUClass *cc = CPU_GET_CLASS(cs);
CPUE2KState *env = &cpu->env;
if (n < 3) {
return gdb_get_reg64(mem_buf, 0); // unk
switch (n) {
case 0: return gdb_get_reg64(mem_buf, 0); // unk
case 1: return gdb_get_reg64(mem_buf, 0); // b0
case 2: return gdb_get_reg64(mem_buf, 0); // b1
default: break;
}
if (3 <= n && n < 35) {
@ -56,14 +59,14 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
case 49: return gdb_get_reg64(mem_buf, env->psp_lo); // psp_lo
case 50: return gdb_get_reg64(mem_buf, env->psp_hi); // psp_hi
case 51: return gdb_get_reg64(mem_buf, env->pshtp); // pshtp
case 52: return gdb_get_reg64(mem_buf, 0); // unk
case 53: return gdb_get_reg64(mem_buf, env->ip); // ip
case 54: return gdb_get_reg64(mem_buf, 0); // TODO: something associated with wd
case 55: return gdb_get_reg64(mem_buf, 0); // br
case 52: return gdb_get_reg64(mem_buf, env->cr0_lo); // cr0_lo
case 53: return gdb_get_reg64(mem_buf, env->cr0_hi); // cr0_hi
case 54: return gdb_get_reg64(mem_buf, env->cr1_lo); // cr1_lo
case 55: return gdb_get_reg64(mem_buf, env->cr1_hi); // cr1_hi
case 56: return gdb_get_reg64(mem_buf, 0); // cwd
case 57: return gdb_get_reg64(mem_buf, env->pcsp_lo); // pcsp_lo
case 58: return gdb_get_reg64(mem_buf, env->pcsp_hi); // pcsp_hi
case 59: return gdb_get_reg64(mem_buf, 0); // pcshtp
case 59: return gdb_get_reg64(mem_buf, env->pcshtp); // pcshtp
case 60: return gdb_get_reg64(mem_buf, 0); // cud_lo
case 61: return gdb_get_reg64(mem_buf, 0); // cud_hi
case 62: return gdb_get_reg64(mem_buf, 0); // gd_lo
@ -152,20 +155,29 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
case 331: return gdb_get_reg64(mem_buf, 0); // dtcr
case 332: return gdb_get_reg64(mem_buf, 0); // dtarf
case 333: return gdb_get_reg64(mem_buf, 0); // dtart
case 334: return gdb_get_reg64(mem_buf, 0); // unk
case 334: {
uint64_t wd = 0;
wd = SET_FIELD(wd, env->wd_base * 8, WD_BASE_OFF, WD_BASE_LEN);
wd = SET_FIELD(wd, env->wd_size * 8, WD_SIZE_OFF, WD_SIZE_LEN);
wd = SET_FIELD(wd, env->wd_psize * 8, WD_PSIZE_OFF, WD_PSIZE_LEN);
wd &= ~WD_FX_BIT; // TODO: wd.fx
return gdb_get_reg64(mem_buf, wd); // wd
}
case 335: return gdb_get_reg64(mem_buf, 0); // unk
case 336: return gdb_get_reg64(mem_buf, 0); // bgr
case 337: return gdb_get_reg64(mem_buf, 0); // unk
case 338: return gdb_get_reg64(mem_buf, env->nip); // nip
case 339: return gdb_get_reg64(mem_buf, 0); // ctpr1
case 340: return gdb_get_reg64(mem_buf, 0); // ctpr2
case 341: return gdb_get_reg64(mem_buf, 0); // ctpr3
case 338: return gdb_get_reg64(mem_buf, 0); // nip
case 339: return gdb_get_reg64(mem_buf, env->ctprs[0]); // ctpr1
case 340: return gdb_get_reg64(mem_buf, env->ctprs[1]); // ctpr2
case 341: return gdb_get_reg64(mem_buf, env->ctprs[2]); // ctpr3
case 342: return gdb_get_reg64(mem_buf, 0); // eir
case 343: return gdb_get_reg64(mem_buf, 0); // tr
case 344: return gdb_get_reg64(mem_buf, 0); // cutd
case 345: return gdb_get_reg64(mem_buf, 0); // cuir
case 346: return gdb_get_reg64(mem_buf, 0); // tsd
case 347: return gdb_get_reg64(mem_buf, 0); // lsr
case 347: return gdb_get_reg64(mem_buf, env->lsr); // lsr
case 348: return gdb_get_reg64(mem_buf, 0); // ilcr
default:
break;
@ -250,9 +262,9 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
int e2k_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
{
E2KCPU *cpu = E2K_CPU(cs);
CPUClass *cc = CPU_GET_CLASS(cs);
CPUE2KState *env = &cpu->env;
// E2KCPU *cpu = E2K_CPU(cs);
// CPUClass *cc = CPU_GET_CLASS(cs);
// CPUE2KState *env = &cpu->env;
fprintf(stderr, "%s: unknown register %d\n", __FUNCTION__, n);

View File

@ -16,41 +16,37 @@ static inline void reset_ctprs(CPUE2KState *env)
}
}
void helper_save_cpu_state(CPUE2KState *env)
static inline void save_br_state(CPUE2KState *env)
{
uint32_t br = 0;
int rbs, rsz, rcur;
br = SET_FIELD(br, env->boff / 2, BR_RBS_OFF, BR_RBS_LEN);
br = SET_FIELD(br, (env->bsize - 2) / 2, BR_RSZ_OFF, BR_RSZ_LEN);
br = SET_FIELD(br, env->bcur / 2, BR_RCUR_OFF, BR_RCUR_LEN);
br = SET_FIELD(br, env->psize, BR_PSZ_OFF, BR_PSZ_LEN);
br = SET_FIELD(br, env->pcur, BR_PCUR_OFF, BR_PCUR_LEN);
rbs = env->boff / 2;
rsz = (env->bsize - 2) / 2;
rcur = env->bcur / 2;
env->cr1_hi = SET_FIELD(env->cr1_hi, br, CR1_HI_BR_OFF + BR_BN_OFF,
BR_BN_LEN);
env->br = SET_FIELD(env->br, rbs, BR_RBS_OFF, BR_RBS_LEN);
env->br = SET_FIELD(env->br, rsz, BR_RSZ_OFF, BR_RSZ_LEN);
env->br = SET_FIELD(env->br, rcur, BR_RCUR_OFF, BR_RCUR_LEN);
env->br = SET_FIELD(env->br, env->psize, BR_PSZ_OFF, BR_PSZ_LEN);
env->br = SET_FIELD(env->br, env->pcur, BR_PCUR_OFF, BR_PCUR_LEN);
env->cr1_lo = SET_FIELD(env->cr1_lo, env->wd_psize / 2,
CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_LEN);
e2k_state_cr1_br_set(env, env->br);
}
static inline void restore_br_state(CPUE2KState *env)
{
uint32_t br;
int rbs, rsz, rcur, psz, pcur;
int rbs, rsz, rcur;
// FIXME: cr1_hi.br does not modified after return, find a way to restore it
br = GET_FIELD(env->cr1_hi, CR1_HI_BR_OFF, CR1_HI_BR_LEN);
rbs = GET_FIELD(br, BR_RBS_OFF, BR_RBS_END);
rsz = GET_FIELD(br, BR_RSZ_OFF, BR_RSZ_END);
rcur = GET_FIELD(br, BR_RCUR_OFF, BR_RCUR_END);
psz = GET_FIELD(br, BR_PSZ_OFF, BR_PSZ_END);
pcur = GET_FIELD(br, BR_PCUR_OFF, BR_PCUR_END);
env->br = e2k_state_cr1_br_get(env);
rbs = GET_FIELD(env->br, BR_RBS_OFF, BR_RBS_END);
rsz = GET_FIELD(env->br, BR_RSZ_OFF, BR_RSZ_END);
rcur = GET_FIELD(env->br, BR_RCUR_OFF, BR_RCUR_END);
env->boff = rbs * 2;
env->bsize = rsz * 2 + 2;
env->bcur = rcur * 2;
env->psize = psz;
env->pcur = pcur;
env->psize = GET_FIELD(env->br, BR_PSZ_OFF, BR_PSZ_END);
env->pcur = GET_FIELD(env->br, BR_PCUR_OFF, BR_PCUR_END);
}
void helper_unimpl(CPUE2KState *env)
@ -61,63 +57,45 @@ void helper_unimpl(CPUE2KState *env)
cpu_loop_exit(cs);
}
void helper_raise_exception(CPUE2KState *env, int tt)
{
CPUState *cs = env_cpu(env);
helper_save_cpu_state(env);
cs->exception_index = tt;
cpu_loop_exit(cs);
}
void helper_debug(CPUE2KState *env)
{
CPUState *cs = env_cpu(env);
helper_save_cpu_state(env);
cs->exception_index = EXCP_DEBUG;
cpu_loop_exit(cs);
}
static void pcs_push(CPUE2KState *env)
static void pcs_push(CPUE2KState *env, int wbs)
{
size_t size = e2k_state_pcs_size_get(env);
size_t offset = e2k_state_pcs_index_get(env);
uint64_t *pcsp = (uint64_t *) (e2k_state_pcs_base_get(env) + offset);
void *pcsp = (void*) e2k_state_pcs_base_get(env) + offset;
if (offset + 32 > size) {
/* TODO: allocate more memory */
abort();
}
memcpy(pcsp, &env->pf, 8);
memcpy(pcsp + 1, &env->nip, 8);
memcpy(pcsp + 2, &env->cr1_lo, 8);
memcpy(pcsp + 3, &env->cr1_hi, 8);
save_br_state(env);
e2k_state_cr1_wpsz_set(env, env->wd_psize / 2);
memcpy(pcsp, env->proc_chain, 32);
e2k_state_cr1_wbs_set(env, wbs);
e2k_state_pcs_index_set(env, offset + 32);
}
static uint64_t pcs_pop(CPUE2KState *env)
static void pcs_pop(CPUE2KState *env)
{
size_t offset = e2k_state_pcs_index_get(env);
uint64_t *pcsp = (uint64_t *) (e2k_state_pcs_base_get(env) + offset - 32);
uint64_t tgt;
void *pcsp = (void*) e2k_state_pcs_base_get(env) + offset - 32;
if (offset < 32) {
/* TODO: SIGKILL */
abort();
}
memcpy(&env->pf, pcsp, 8);
memcpy(&tgt, pcsp + 1, 8);
memcpy(&env->cr1_lo, pcsp + 2, 8);
memcpy(&env->cr1_hi, pcsp + 3, 8);
memcpy(&env->proc_chain, pcsp, 32);
// TODO: restore wbs (after pshtp implemented)
env->wd_psize = e2k_state_cr1_wpsz_get(env) * 2;
restore_br_state(env);
e2k_state_pcs_index_set(env, offset - 32);
return tgt;
}
static void ps_push(CPUE2KState *env, unsigned int wbs, size_t len)
static void ps_push(CPUE2KState *env, unsigned int wd_base, size_t len)
{
unsigned int i;
size_t index = e2k_state_ps_ind_get(env);
@ -127,14 +105,14 @@ static void ps_push(CPUE2KState *env, unsigned int wbs, size_t len)
/* TODO: stack overflow */
for (i = 0; i < len; i++) {
uint64_t reg = env->wregs[(wbs + i) % WREGS_SIZE];
uint64_t reg = env->wregs[(wd_base + i) % WREGS_SIZE];
memcpy(p + i, &reg, sizeof(uint64_t));
}
e2k_state_ps_ind_set(env, index + len * sizeof(uint64_t));
}
static void ps_pop(CPUE2KState *env, unsigned int wbs, size_t len)
static void ps_pop(CPUE2KState *env, unsigned int wd_base, size_t len)
{
unsigned int i;
size_t index = e2k_state_ps_ind_get(env) - len * sizeof(uint64_t);
@ -144,7 +122,7 @@ static void ps_pop(CPUE2KState *env, unsigned int wbs, size_t len)
/* TODO: stack overflow */
for (i = 0; i < len; i++) {
uint64_t *reg = &env->wregs[(wbs + i) % WREGS_SIZE];
uint64_t *reg = &env->wregs[(wd_base + i) % WREGS_SIZE];
memcpy(reg, p + i, sizeof(uint64_t));
}
@ -155,23 +133,21 @@ static inline void do_call(CPUE2KState *env, int call_wbs)
{
int call_wpsz = env->wd_size / 2 - call_wbs;
helper_save_cpu_state(env);
pcs_push(env);
env->ip = env->nip;
pcs_push(env, call_wbs);
ps_push(env, env->wd_base, call_wbs * 2);
e2k_state_wbs_set(env, call_wbs);
env->wd_base = (env->wd_base + call_wbs * 2) % WREGS_SIZE;
env->wd_size = env->wd_psize = call_wpsz * 2;
reset_ctprs(env);
}
target_ulong helper_return(CPUE2KState *env)
void helper_return(CPUE2KState *env)
{
int new_wd_size, new_wd_base, wbs;
target_ulong tgt;
uint32_t new_wd_size, new_wd_base, wbs;
wbs = GET_FIELD(env->cr1_lo, CR1_LO_WBS_OFF, CR1_LO_WBS_END);
wbs = e2k_state_cr1_wbs_get(env);
new_wd_size = env->wd_psize + wbs * 2;
new_wd_base = (env->wd_base - wbs * 2) % WREGS_SIZE;
@ -179,18 +155,13 @@ target_ulong helper_return(CPUE2KState *env)
env->wd_base += WREGS_SIZE;
}
tgt = pcs_pop(env);
ps_pop(env, new_wd_base, env->wd_base - new_wd_base);
pcs_pop(env);
env->wd_base = new_wd_base;
env->wd_size = new_wd_size;
env->wd_psize = GET_FIELD(env->cr1_lo, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_END) * 2;
restore_br_state(env);
reset_ctprs(env);
return tgt;
}
static inline void do_syscall(CPUE2KState *env, int call_wbs)
@ -206,21 +177,83 @@ target_ulong helper_call(CPUE2KState *env, uint64_t ctpr,
{
int ctpr_tag = GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END);
helper_save_cpu_state(env);
switch (ctpr_tag) {
case CTPR_TAG_DISP:
do_call(env, call_wbs);
return GET_FIELD(ctpr, CTPR_BASE_OFF, CTPR_BASE_END);
case CTPR_TAG_SDISP:
do_syscall(env, call_wbs);
return env->nip;
return env->ip;
default:
helper_raise_exception(env, E2K_EXCP_UNIMPL);
return env->nip;
return env->ip;
}
}
void helper_raise_exception(CPUE2KState *env, int tt)
{
CPUState *cs = env_cpu(env);
save_br_state(env);
cs->exception_index = tt;
cpu_loop_exit(cs);
}
static void break_save_ps(CPUE2KState *env)
{
unsigned int i;
unsigned int wd_base = env->wd_base;
unsigned int len = env->wd_size;
size_t index = e2k_state_ps_ind_get(env);
uint64_t *p = (uint64_t*) (e2k_state_ps_base_get(env) + index);
/* TODO: stack overflow */
for (i = 0; i < len; i += 2) {
uint64_t t[2] = { 0 };
uint64_t *reg = &env->wregs[(wd_base + i) % WREGS_SIZE];
memcpy(p + i * 2, reg, 2 * sizeof(uint64_t));
memcpy(p + i * 2 + 2, t, 2 * sizeof(uint64_t)); // TODO: fx part
}
e2k_state_ps_ind_set(env, index + len * 2 * sizeof(uint64_t));
}
static void break_save_state(CPUE2KState *env)
{
break_save_ps(env);
pcs_push(env, env->wd_size / 2);
env->wd_base = (env->wd_base + env->wd_size) % WREGS_SIZE;
env->wd_size = 0;
env->wd_psize = 0;
env->is_bp = true;
}
void helper_break_restore_state(CPUE2KState *env)
{
size_t index;
int wbs;
wbs = e2k_state_cr1_wbs_get(env);
pcs_pop(env);
env->wd_size = wbs * 2;
env->wd_base = (env->wd_base - env->wd_size) % WREGS_SIZE;
index = e2k_state_ps_ind_get(env);
e2k_state_ps_ind_set(env, index - env->wd_size * 2 * sizeof(uint64_t));
env->is_bp = false;
}
void helper_debug(CPUE2KState *env)
{
CPUState *cs = env_cpu(env);
break_save_state(env);
cs->exception_index = EXCP_DEBUG;
cpu_loop_exit(cs);
}
uint64_t helper_sxt(uint64_t x, uint64_t y)
{
int size;
@ -288,8 +321,7 @@ void helper_state_reg_set(CPUE2KState *env, int reg, uint64_t val)
env->lsr = val;
break;
default:
/* TODO: exception */
abort();
helper_raise_exception(env, E2K_EXCP_ILLOPC);
break;
}
}

View File

@ -1,8 +1,7 @@
DEF_HELPER_1(save_cpu_state, void, env)
DEF_HELPER_1(unimpl, noreturn, env)
DEF_HELPER_2(raise_exception, noreturn, env, int)
DEF_HELPER_1(debug, void, env)
DEF_HELPER_1(return, tl, env)
DEF_HELPER_1(return, void, env)
DEF_HELPER_3(call, tl, env, i64, int)
DEF_HELPER_2(sxt, i64, i64, i64)
DEF_HELPER_1(debug_i32, void, i32)
@ -11,3 +10,4 @@ DEF_HELPER_2(state_reg_get, i64, env, int)
DEF_HELPER_3(state_reg_set, void, env, int, i64)
DEF_HELPER_2(getsp, i64, env, i64) /* FIXME: return tl? */
DEF_HELPER_4(cur_dec, i32, env, i32, i32, i32)
DEF_HELPER_1(break_restore_state, void, env)

View File

@ -199,7 +199,6 @@ static inline void gen_save_cpu_state(DisasContext *ctx)
{
gen_save_pc(ctx->pc);
gen_save_npc(ctx->npc);
gen_helper_save_cpu_state(cpu_env);
}
static inline bool use_goto_tb(DisasContext *s, target_ulong pc,
@ -353,18 +352,18 @@ static inline void do_branch(DisasContext *ctx)
switch(ctx->ct.type) {
case CT_IBRANCH:
// TODO: goto_tb
gen_goto_tb(ctx, 0, ctx->pc, ctx->ct.u.target);
break;
case CT_JUMP: {
TCGLabel *l0 = gen_new_label();
TCGLabel *l1 = gen_new_label();
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t0 = tcg_temp_local_new_i64();
gen_ctpr_tag(t0, ctx->ct.u.ctpr);
tcg_gen_brcondi_i64(TCG_COND_EQ, t0, CTPR_TAG_DISP, l0);
gen_ctpr_tag(t0, ctx->ct.u.ctpr);
tcg_gen_brcondi_i64(TCG_COND_EQ, t0, CTPR_TAG_RETURN, l1);
tcg_temp_free_i64(t0);
// TODO: ldisp, sdisp
e2k_gen_exception(ctx, E2K_EXCP_UNIMPL);
@ -372,16 +371,13 @@ static inline void do_branch(DisasContext *ctx)
gen_goto_ctpr_disp(ctx->ct.u.ctpr);
gen_set_label(l1);
gen_save_cpu_state(ctx);
gen_helper_return(e2k_cs.pc, cpu_env);
gen_helper_return(cpu_env);
tcg_gen_lookup_and_goto_ptr();
tcg_temp_free_i64(t0);
break;
}
case CT_CALL: {
TCGv_i32 wbs = tcg_const_i32(ctx->ct.wbs);
gen_save_cpu_state(ctx);
gen_save_npc(ctx->npc);
gen_helper_call(e2k_cs.pc, cpu_env, ctx->ct.u.ctpr, wbs);
tcg_temp_free_i32(wbs);
tcg_gen_lookup_and_goto_ptr();
@ -423,7 +419,7 @@ static bool e2k_tr_breakpoint_check(DisasContextBase *db, CPUState *cs,
static void e2k_tr_tb_start(DisasContextBase *db, CPUState *cs)
{
DisasContext *ctx = container_of(db, DisasContext, base);
// DisasContext *ctx = container_of(db, DisasContext, base);
tcg_gen_movi_tl(e2k_cs.ct_cond, 1);
}
@ -437,6 +433,11 @@ static void e2k_tr_insn_start(DisasContextBase *db, CPUState *cs)
static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs)
{
DisasContext *ctx = container_of(db, DisasContext, base);
TCGLabel *l0 = gen_new_label();
tcg_gen_brcondi_i32(TCG_COND_EQ, e2k_cs.is_bp, 0, l0);
gen_helper_break_restore_state(cpu_env);
gen_set_label(l0);
do_decode(ctx, cs);
do_execute(ctx);
@ -464,7 +465,6 @@ static void e2k_tr_tb_stop(DisasContextBase *db, CPUState *cs)
switch(ctx->base.is_jmp) {
case DISAS_NEXT:
case DISAS_TOO_MANY:
gen_helper_save_cpu_state(cpu_env);
gen_goto_tb(ctx, 0, ctx->pc, ctx->npc);
break;
case DISAS_NORETURN:
@ -520,6 +520,7 @@ void e2k_tcg_initialize(void) {
{ &e2k_cs.bcur, offsetof(CPUE2KState, bcur), "bcur" },
{ &e2k_cs.psize, offsetof(CPUE2KState, psize), "psize" },
{ &e2k_cs.pcur, offsetof(CPUE2KState, pcur), "pcur" },
{ &e2k_cs.is_bp, offsetof(CPUE2KState, is_bp), "is_bp" },
};
static const struct { TCGv_i64 *ptr; int off; const char *name; } r64[] = {

View File

@ -60,6 +60,7 @@ typedef struct CPUE2KStateTCG {
TCGv npc;
TCGv ctprs[3];
TCGv ct_cond;
TCGv_i32 is_bp; /* breakpoint flag */
TCGv_i64 lsr;
TCGv_i64 wregs[WREGS_SIZE];
TCGv_i64 gregs[GREGS_SIZE];