target: e2k: Read NR in gdb.
This commit is contained in:
parent
47905d5d35
commit
5b828e999f
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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, ®, 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in New Issue