target: e2k: Return aligned pointer from getsp.

This commit is contained in:
Denis Drakhnia 2020-12-11 09:37:23 +02:00 committed by Denis Drakhnia
parent 83e2503867
commit 381868f71a
7 changed files with 57 additions and 34 deletions

View File

@ -120,8 +120,8 @@ void target_cpu_copy_regs(CPUE2KState *env, struct target_pt_regs *regs)
env->ip = regs->ip;
env->pcsp = regs->pcsp;
env->psp = regs->psp;
env->usd_lo = regs->usd_lo;
env->usd_hi = regs->usd_hi;
env->usd.lo = regs->usd_lo;
env->usd.hi = regs->usd_hi;
env->sbr = regs->sbr;
e2k_break_save_state(env);

View File

@ -7,9 +7,11 @@ static inline void cpu_clone_regs_child(CPUE2KState *env, target_ulong newsp,
unsigned flags)
{
if (newsp) {
uint64_t size = 0x20000UL;
env->usd_hi = size << 32;
env->usd_lo = (0x1800UL << 48) | newsp;
// FIXME: what size must be?
env->usd.size = 0x20000;
env->usd.base = newsp;
env->usd.read = 1;
env->usd.write = 1;
}
}
@ -34,7 +36,7 @@ static inline target_ulong cpu_get_tls(CPUE2KState *env)
static inline abi_ulong get_sp_from_cpustate(CPUE2KState *env)
{
return extract64(env->usd_lo, 0, 48);
return env->usd.base;
}
#endif /* E2K_TARGET_CPU_H */

View File

@ -164,8 +164,8 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
qemu_fprintf(f, " pcsp_hi = 0x%016lx\n", e2k_state_pcsp_hi(env));
qemu_fprintf(f, " psp_lo = 0x%016lx\n", e2k_state_psp_lo(env));
qemu_fprintf(f, " psp_hi = 0x%016lx\n", e2k_state_psp_hi(env));
qemu_fprintf(f, " usd_lo = 0x%016lx\n", env->usd_lo);
qemu_fprintf(f, " usd_hi = 0x%016lx\n", env->usd_hi);
qemu_fprintf(f, " usd_lo = 0x%016lx\n", env->usd.lo);
qemu_fprintf(f, " usd_hi = 0x%016lx\n", env->usd.hi);
qemu_fprintf(f, " lsr = 0x%016lx\n", env->lsr);
cpu_dump_state_br(env, f, flags);

View File

@ -452,6 +452,26 @@ typedef union {
} E2KCtpr;
typedef struct {
union {
uint64_t lo;
struct {
uint64_t base: 48;
uint64_t unused1: 10;
uint64_t protected: 1;
uint64_t read: 1;
uint64_t write: 1;
uint64_t unsued2: 3;
};
};
union {
uint64_t hi;
struct {
uint64_t curptr: 32;
uint64_t size: 32;
};
};
} E2KUserStackDesc;
typedef struct CPUArchState {
/* register file */
uint64_t regs[E2K_REG_COUNT]; /* registers */
@ -460,6 +480,14 @@ typedef struct CPUArchState {
uint64_t *rptr; /* pointer to regs */
uint64_t *tptr; /* pointer to tags */
union {
uint64_t pregs; /* predicate file */
uint64_t cr0_lo;
};
union {
target_ulong ip; /* instruction address */
uint64_t cr0_hi;
};
E2KCr1State cr1;
/* Procedure chain info = cr0_lo, cr0_hi, cr1_lo, cr1_hi */
@ -477,21 +505,11 @@ typedef struct CPUArchState {
uint64_t lsr; /* loop status register */
uint64_t sbr;
uint64_t usd_lo;
uint64_t usd_hi;
E2KUserStackDesc usd;
/* control registers */
E2KCtpr ctprs[3]; // Control Transfer Preparation Register (CTPR)
target_ulong ct_cond;
union {
uint64_t pregs; /* predicate file */
uint64_t cr0_lo;
};
union {
target_ulong ip; /* instruction address */
uint64_t cr0_hi;
};
target_ulong nip; /* next instruction address */

View File

@ -55,8 +55,8 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
case 44: return gdb_get_reg64(mem_buf, 0); // fpcr
case 45: return gdb_get_reg64(mem_buf, 0); // fpsr
case 46: return gdb_get_reg64(mem_buf, 0); // usbr
case 47: return gdb_get_reg64(mem_buf, env->usd_lo); // usd_lo
case 48: return gdb_get_reg64(mem_buf, env->usd_hi); // usd_hi
case 47: return gdb_get_reg64(mem_buf, env->usd.lo); // usd_lo
case 48: return gdb_get_reg64(mem_buf, env->usd.hi); // usd_hi
case 49: return gdb_get_reg64(mem_buf, e2k_state_psp_lo(env)); // psp_lo
case 50: return gdb_get_reg64(mem_buf, e2k_state_psp_hi(env)); // psp_hi
case 51: return gdb_get_reg64(mem_buf, e2k_state_pshtp(env)); // pshtp

View File

@ -47,16 +47,16 @@ static inline uint64_t stack_pop(CPUE2KState *env, E2KStackState *s)
/* FIXME: I don't know how exactly it should works. */
static inline void sbr_push(CPUE2KState *env)
{
cpu_stq_le_data(env, env->sbr, env->usd_lo);
cpu_stq_le_data(env, env->sbr + 8, env->usd_hi);
cpu_stq_le_data(env, env->sbr, env->usd.lo);
cpu_stq_le_data(env, env->sbr + 8, env->usd.hi);
env->sbr += 16;
}
static inline void sbr_pop(CPUE2KState *env)
{
env->sbr -= 16;
env->usd_hi = cpu_ldq_le_data(env, env->sbr + 8);
env->usd_lo = cpu_ldq_le_data(env, env->sbr);
env->usd.hi = cpu_ldq_le_data(env, env->sbr + 8);
env->usd.lo = cpu_ldq_le_data(env, env->sbr);
}
static void proc_chain_save(CPUE2KState *env, int wbs)

View File

@ -34,9 +34,9 @@ static uint64_t* state_reg_ptr(CPUE2KState *env, int idx)
{
switch (idx) {
/* FIXME: user cannot write */
case 0x2c: return &env->usd_hi; /* %usd.hi */
case 0x2c: return &env->usd.hi; /* %usd.hi */
/* FIXME: user cannot write */
case 0x2d: return &env->usd_lo; /* %usd.lo */
case 0x2d: return &env->usd.lo; /* %usd.lo */
case 0x51: return &env->ip; /* %cr1.hi */
case 0x53: return &env->pregs; /* %cr1.lo */
case 0x80: return &env->upsr; /* %upsr */
@ -108,14 +108,17 @@ void helper_state_reg_write_i32(CPUE2KState *env, int idx, uint32_t val)
}
}
uint64_t helper_getsp(CPUE2KState *env, uint32_t src2) {
uint64_t base = GET_FIELD(env->usd_lo, USD_LO_BASE_OFF, USD_LO_BASE_LEN);
uint64_t helper_getsp(CPUE2KState *env, uint32_t src2)
{
int32_t s2 = src2 & ~0xf;
uint32_t size = s2 >= 0 ? s2 : -s2;
base += (int32_t) src2;
if (size > env->usd.size) {
helper_raise_exception(env, E2K_EXCP_MAPERR);
}
/* TODO: stack overflow */
env->usd_lo = SET_FIELD(env->usd_lo, base, USD_LO_BASE_OFF,
USD_LO_BASE_LEN);
env->usd.base += s2;
env->usd.size -= size;
return base;
return env->usd.base;
}