e2k: cpu always spill/fill 32 bytes for every 2 regs

This commit is contained in:
Denis Drakhnia 2024-01-02 12:06:41 +02:00
parent e381e6d3f5
commit 5afa8efc6e
5 changed files with 54 additions and 53 deletions

View File

@ -43,7 +43,7 @@ static inline void cpu_clone_regs_child(CPUE2KState *env, target_ulong newsp,
return;
}
frame_size = crs.cr1.wbs * (crs.cr1.wfx || E2K_FORCE_FX ? 32 : 16);
frame_size = crs.cr1.wbs * 32;
ps_base -= frame_size;
ps.index += frame_size;
ps_old = lock_user(VERIFY_READ, ps_base, frame_size, 1);

View File

@ -7074,8 +7074,7 @@ static abi_long do_e2k_longjmp2(CPUE2KState *env, struct target_jmp_info *jmp_in
return ret;
}
psize = crs.cr1.wpsz * 2;
ps_index -= crs.cr1.wbs * E2K_REG_LEN *
(crs.cr1.wfx || E2K_FORCE_FX ? 4 : 2);
ps_index -= crs.cr1.wbs * E2K_REG_LEN * 4;
pcsp -= CRS_SIZE;
}

View File

@ -20,14 +20,6 @@ void e2k_tcg_initialize(void);
/* #define TARGET_E2K_PRECISE_FSQRTID */
/* FIXME: nfx window mode
* numas13: I don't know why elbrus always spill/fill in fx mode.
* If we enable 'nfx' mode It will break "finish" command in gdb because
* it will try to read registers from hell.
*/
#define E2K_FORCE_FX true
#define GEN_MASK(start, len) (((1ULL << (len)) - 1) << (start))
#define GET_BIT(v, index) (((v) >> (index)) & 1)

View File

@ -3,6 +3,8 @@
#include "qemu/host-utils.h"
#include "exec/helper-proto.h"
#define FRAME_SIZE(NREGS) ((NREGS) * 16)
static inline void reset_ctprs(CPUE2KState *env)
{
unsigned int i;
@ -12,87 +14,97 @@ static inline void reset_ctprs(CPUE2KState *env)
}
}
static inline void ps_push(CPUE2KState *env, uint64_t value, uint8_t tag)
static inline void ps_write(CPUE2KState *env, uint64_t value, uint8_t tag, int32_t index)
{
#ifndef CONFIG_USER_ONLY
if ((env->psp.index + 8) > env->psp.size) {
raise_exception(env, E2K_EXCP_PROC_STACK_BOUNDS);
}
#endif
cpu_stq_le_data(env, env->psp.base + index, value);
cpu_stq_le_data(env, env->psp.base + env->psp.index, value);
if (env->enable_tags) {
cpu_stb_data(env, env->psp.base_tag + env->psp.index / 8, tag);
cpu_stb_data(env, env->psp.base_tag + index / 8, tag);
}
env->psp.index += 8;
}
static inline uint64_t ps_pop(CPUE2KState *env, uint8_t *ret_tag)
static inline uint64_t ps_read(CPUE2KState *env, uint8_t *ret_tag, int32_t index)
{
if (env->psp.index < 8) {
raise_exception(env, E2K_EXCP_PROC_STACK_BOUNDS);
}
env->psp.index -= 8;
if (ret_tag != NULL) {
if (env->enable_tags) {
abi_ptr ptr = env->psp.base_tag + env->psp.index / 8;
*ret_tag = cpu_ldub_data(env, ptr);
*ret_tag = cpu_ldub_data(env, env->psp.base_tag + index / 8);
} else {
*ret_tag = 0;
}
}
return cpu_ldq_le_data(env, env->psp.base + env->psp.index);
}
return cpu_ldq_le_data(env, env->psp.base + index);
}
static void ps_spill(CPUE2KState *env, int n, bool fx)
{
int i;
int32_t index = env->psp.index;
// XXX: psp.size is set to some random value and does not show real stack size
#ifndef CONFIG_USER_ONLY
if (env->psp.index + FRAME_SIZE(n) > env->psp.size) {
raise_exception(env, E2K_EXCP_PROC_STACK_BOUNDS);
}
#endif
if (env->version >= 5) {
for (i = 0; i < n; i++) {
ps_push(env, env->regs[i].lo, env->tags[i]);
if (fx || E2K_FORCE_FX) {
ps_push(env, env->regs[i].hi, 0);
for (int i = 0; i < n; i++, index += 16) {
ps_write(env, env->regs[i].lo, env->tags[i], index);
if (fx) {
ps_write(env, env->regs[i].hi, 0, index + 8);
}
}
} else{
for (i = 0; i < n; i += 2) {
for (int i = 0; i < n; i += 2, index += 32) {
E2KReg r0 = env->regs[i + 0];
E2KReg r1 = env->regs[i + 1];
ps_push(env, r0.lo, env->tags[i]);
ps_push(env, r1.lo, env->tags[i + 1]);
if (fx || E2K_FORCE_FX) {
ps_push(env, r0.hi, 0);
ps_push(env, r1.hi, 0);
ps_write(env, r0.lo, env->tags[i], index);
ps_write(env, r1.lo, env->tags[i + 1], index + 8);
if (fx) {
ps_write(env, r0.hi, 0, index + 16);
ps_write(env, r1.hi, 0, index + 24);
}
}
}
env->psp.index = index;
}
static void ps_fill(CPUE2KState *env, int n, bool fx)
{
int i;
int32_t index = env->psp.index, frame_size = FRAME_SIZE(n);
if (index < frame_size) {
raise_exception(env, E2K_EXCP_PROC_STACK_BOUNDS);
}
if (env->version >= 5) {
for (i = n; i-- > 0;) {
if (fx || E2K_FORCE_FX) {
env->regs[i].hi = ps_pop(env, NULL);
for (int i = n; i-- > 0; index -= 16) {
if (fx) {
env->regs[i].hi = ps_read(env, NULL, index - 8);
}
env->regs[i].lo = ps_pop(env, &env->tags[i]);
env->regs[i].lo = ps_read(env, &env->tags[i], index - 16);
}
} else {
for (i = n; i > 0; i -= 2) {
for (int i = n; i > 0; i -= 2, index -= 32) {
E2KReg *r0 = &env->regs[i - 1];
E2KReg *r1 = &env->regs[i - 2];
if (fx || E2K_FORCE_FX) {
r0->hi = ps_pop(env, NULL);
r1->hi = ps_pop(env, NULL);
if (fx) {
r0->hi = ps_read(env, NULL, index - 8);
r1->hi = ps_read(env, NULL, index - 16);
}
r0->lo = ps_pop(env, &env->tags[i - 1]);
r1->lo = ps_pop(env, &env->tags[i - 2]);
r0->lo = ps_read(env, &env->tags[i - 1], index - 24);
r1->lo = ps_read(env, &env->tags[i - 2], index - 32);
}
}
env->psp.index = index;
}
static void move_regs(CPUE2KState *env, int dst, int src, int n)

View File

@ -94,7 +94,6 @@ typedef enum {
} AlesFlag;
static TCGv cpu_pc;
static TCGv cpu_npc;
static TCGv_i64 cpu_ctprs[3];
static TCGv_i32 cpu_ct_cond;
static TCGv_i32 cpu_boff; /* holds rbs * 2 */
@ -7550,7 +7549,6 @@ void e2k_tcg_initialize(void) {
static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
{ &cpu_pc, offsetof(CPUE2KState, ip), "pc" },
{ &cpu_npc, offsetof(CPUE2KState, nip), "npc" },
};
unsigned int i;