e2k: Add tags and force_save_alc_dst properties.

Signed-off-by: Denis Drakhnya <numas13@gmail.com>
This commit is contained in:
Denis Drakhnia 2021-03-25 11:48:23 +02:00 committed by Denis Drakhnia
parent d84636d73a
commit c8ed74f626
4 changed files with 86 additions and 72 deletions

View File

@ -277,6 +277,12 @@ static struct TCGCPUOps e2k_tcg_ops = {
#endif
};
static Property e2k_cpu_properties[] = {
DEFINE_PROP_BOOL("force_save_alc_dst", E2KCPU, env.force_save_alc_dst, false),
DEFINE_PROP_BOOL("tags", E2KCPU, env.enable_tags, false),
DEFINE_PROP_END_OF_LIST()
};
static void e2k_cpu_class_init(ObjectClass *oc, void *data)
{
E2KCPUClass *ecc = E2K_CPU_CLASS(oc);
@ -285,7 +291,7 @@ static void e2k_cpu_class_init(ObjectClass *oc, void *data)
device_class_set_parent_realize(dc, e2k_cpu_realizefn,
&ecc->parent_realize);
device_class_set_props(dc, e2k_cpu_properties);
device_class_set_parent_reset(dc, e2k_cpu_reset, &ecc->parent_reset);
cc->has_work = e2k_cpu_has_work;
@ -348,6 +354,8 @@ type_init(e2k_cpu_register_types)
void e2k_cpu_list(void)
{
unsigned int i;
Property* prop;
size_t len = 0;
for (i = 0; i < ARRAY_SIZE(e2k_defs); i++) {
qemu_printf("%6s (%-30s) ISA version: v%d\n",
@ -356,4 +364,16 @@ void e2k_cpu_list(void)
e2k_defs[i].isa_version
);
}
qemu_printf("\nFeatures:\n");
for (prop = e2k_cpu_properties; prop->name != 0; prop++) {
size_t l = strlen(prop->name) + 1;
if (len + l >= 75) {
qemu_printf("\n");
len = 0;
}
qemu_printf("%s%s", len ? " " : " ", prop->name);
len += l;
}
qemu_printf("\n");
}

View File

@ -28,8 +28,6 @@ void e2k_tcg_initialize(void);
*/
#define E2K_FORCE_FX true
//#define E2K_TAGS_ENABLE
#define GEN_MASK(start, len) (((1UL << (len)) - 1) << (start))
#define GET_BIT(v, index) (((v) >> (index)) & 1)
@ -785,6 +783,12 @@ typedef struct CPUArchState {
struct {} end_reset_fields;
uint32_t version;
/* Force alop to preserve the destination register before writing to it.
* Default: false */
bool force_save_alc_dst;
/* Enable tags handling.
* Default: false */
bool enable_tags;
struct e2k_def_t def;

View File

@ -21,9 +21,9 @@ static inline void ps_push(CPUE2KState *env, uint64_t value, uint8_t tag)
#endif
cpu_stq_le_data(env, env->psp.base + env->psp.index, value);
#ifdef E2K_TAGS_ENABLE
cpu_stb_data(env, env->psp.base_tag + env->psp.index / 8, tag);
#endif
if (env->enable_tags) {
cpu_stb_data(env, env->psp.base_tag + env->psp.index / 8, tag);
}
env->psp.index += 8;
}
@ -34,11 +34,12 @@ static inline uint64_t ps_pop(CPUE2KState *env, uint8_t *ret_tag)
}
env->psp.index -= 8;
if (ret_tag != NULL) {
#ifdef E2K_TAGS_ENABLE
*ret_tag = cpu_ldub_data(env, env->psp.base_tag + env->psp.index / 8);
#else
*ret_tag = 0;
#endif
if (env->enable_tags) {
abi_ptr ptr = env->psp.base_tag + env->psp.index / 8;
*ret_tag = cpu_ldub_data(env, ptr);
} else {
*ret_tag = 0;
}
}
return cpu_ldq_le_data(env, env->psp.base + env->psp.index);
}
@ -97,9 +98,9 @@ static void ps_fill(CPUE2KState *env, int n, bool fx)
static void move_regs(CPUE2KState *env, int dst, int src, int n)
{
memmove(&env->regs[dst], &env->regs[src], n * sizeof(env->regs[0]));
#ifdef E2K_TAGS_ENABLE
memmove(&env->tags[dst], &env->tags[src], n * sizeof(env->tags[0]));
#endif
if (env->enable_tags) {
memmove(&env->tags[dst], &env->tags[src], n * sizeof(env->tags[0]));
}
}
static void callee_window(CPUE2KState *env, int base, int size, bool fx)
@ -317,9 +318,9 @@ void HELPER(setwd)(CPUE2KState *env, int wsz, int nfx, int dbl)
#if 0
memset(&env->regs[env->wd.size], 0, diff * sizeof(env->regs[0]));
#endif
#ifdef E2K_TAGS_ENABLE
memset(&env->tags[env->wd.size], E2K_TAG_NON_NUMBER128, diff);
#endif
if (env->enable_tags) {
memset(&env->tags[env->wd.size], E2K_TAG_NON_NUMBER128, diff);
}
}
env->wd.size = size;

View File

@ -6,7 +6,6 @@
#include "tcg/tcg-op-gvec.h"
//#define FORCE_SAVE_PLU_PREG
//#define FORCE_SAVE_ALC_REG
//#define FORCE_SAVE_ALC_PREG
#define glue3(a, b, c) glue(glue(a, b), c)
@ -504,11 +503,11 @@ typedef struct DisasContext {
/* optional, can be NULL */
TCGv_i32 mlock;
TCGv_i32 loop_end;
#ifdef E2K_TAGS_ENABLE
TCGv_i32 delayed_illop;
#endif
int version;
bool enable_tags;
bool force_save_alc_dst;
/* Force ILLOP for bad instruction format for cases where real CPU
do not generate it. */
bool strict;
@ -1261,7 +1260,6 @@ static void gen_preg_set_i32(int index, TCGv_i32 val)
tcg_temp_free_i64(t0);
}
#ifdef E2K_TAGS_ENABLE
static void gen_reg_tag_ptr(TCGv_ptr ret, TCGv_i32 idx)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
@ -1287,30 +1285,28 @@ static inline bool is_tag_mask_all(DisasContext *ctx, uint8_t mask)
static void gen_reg_tag_mask(DisasContext *ctx, TCGv_i32 ret,
TCGv_i32 index, uint8_t mask)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
if (ctx->enable_tags) {
TCGv_ptr t0 = tcg_temp_new_ptr();
gen_reg_tag_ptr(t0, index);
if (is_tag_mask_all(ctx, mask)) {
tcg_gen_ld8u_i32(ret, t0, 0);
gen_reg_tag_ptr(t0, index);
if (is_tag_mask_all(ctx, mask)) {
tcg_gen_ld8u_i32(ret, t0, 0);
} else {
TCGv_i32 t1 = tcg_temp_new_i32();
tcg_gen_ld8u_i32(t1, t0, 0);
tcg_gen_andi_i32(ret, t1, mask);
tcg_temp_free_i32(t1);
}
tcg_temp_free_ptr(t0);
} else {
TCGv_i32 t1 = tcg_temp_new_i32();
tcg_gen_ld8u_i32(t1, t0, 0);
tcg_gen_andi_i32(ret, t1, mask);
tcg_temp_free_i32(t1);
tcg_gen_movi_i32(ret, 0);
}
tcg_temp_free_ptr(t0);
}
#else
static void gen_reg_tag_mask(DisasContext *ctx, TCGv_i32 ret,
TCGv_i32 index, uint8_t mask)
{
tcg_gen_movi_i32(ret, 0);
}
#endif
#define gen_reg_tag_i32(c, r, i) \
gen_reg_tag_mask(c, r, i, E2K_TAG_MASK_32)
@ -1324,12 +1320,16 @@ static void gen_reg_tag_mask(DisasContext *ctx, TCGv_i32 ret,
#define gen_reg_tag_i128(c, r, i) \
gen_reg_tag_mask(c, r, i, E2K_TAG_MASK_128)
#ifdef E2K_TAGS_ENABLE
static void gen_reg_tag_mask_set(DisasContext *ctx, TCGv_i32 tag,
TCGv_i32 index, uint8_t mask)
{
TCGv_ptr t0 = tcg_temp_new_ptr();
TCGv_ptr t0;
if (!ctx->enable_tags) {
return;
}
t0 = tcg_temp_new_ptr();
gen_reg_tag_ptr(t0, index);
if (mask == E2K_TAG_MASK_128) {
@ -1361,13 +1361,6 @@ static void gen_reg_tag_mask_set(DisasContext *ctx, TCGv_i32 tag,
tcg_temp_free_ptr(t0);
}
#else
static void gen_reg_tag_mask_set(DisasContext *ctx, TCGv_i32 tag,
TCGv_i32 index, uint8_t mask)
{
tcg_gen_discard_i32(tag);
}
#endif
#define gen_reg_tag_set_i32(c, t, i) \
gen_reg_tag_mask_set(c, t, i, E2K_TAG_MASK_32)
@ -1879,7 +1872,6 @@ static bool is_alop_affected_by_dbl(Alop *alop)
return true;
}
#ifdef E2K_TAGS_ENABLE
static bool is_alop_check_tag(Alop *alop)
{
if (alop->format == ALOPF2) {
@ -1900,7 +1892,6 @@ static bool is_alop_check_tag(Alop *alop)
return true;
}
#endif
#if 0
static bool is_alop_poison_result(Alop *alop)
@ -2128,7 +2119,6 @@ static void gen_plu(DisasContext *ctx)
}
}
#ifndef FORCE_SAVE_ALC_REG
static inline ArgSize alop_reg_max_size(uint8_t src1, ArgSize size1,
uint8_t src2, ArgSize size2)
{
@ -2191,7 +2181,6 @@ static ArgSize alop_opn_max_size(Alop *alop, uint8_t src)
return r;
}
#endif
static bool is_reg_saved(DisasContext *ctx, uint8_t dst)
{
@ -2312,8 +2301,7 @@ static void gen_alop_save_dst(Alop *alop)
int chan = alop->chan;
ArgSize size;
#ifndef FORCE_SAVE_ALC_REG
if (IS_REG_SAVE_SAFE(dst)) {
if (!ctx->force_save_alc_dst && IS_REG_SAVE_SAFE(dst)) {
int i;
size = alop_opn_max_size(alop, dst);
@ -2327,9 +2315,6 @@ static void gen_alop_save_dst(Alop *alop)
} else {
size = ctx->version >= 5 ? ARG_SIZE_P : ARG_SIZE_X;
}
#else
size = ctx->version >= 5 ? ARG_SIZE_P : ARG_SIZE_X;
#endif
gen_save_reg(ctx, chan, size, dst);
}
break;
@ -2470,11 +2455,11 @@ static void gen_reg_set_s(DisasContext *ctx, bool is_dbl,
}
}
#ifdef E2K_TAGS_ENABLE
static void gen_delayed_tag_check(DisasContext *ctx, TCGv_i32 tag)
{
TCGv_i32 t0 = tcg_temp_new_i32();
assert(ctx->delayed_illop);
tcg_gen_setcondi_i32(TCG_COND_NE, t0, tag, 0);
tcg_gen_or_i32(ctx->delayed_illop, ctx->delayed_illop, t0);
tcg_temp_free_i32(t0);
@ -2482,15 +2467,10 @@ static void gen_delayed_tag_check(DisasContext *ctx, TCGv_i32 tag)
static inline void gen_delayed_alop_tag_check(Alop *alop, TCGv_i32 tag)
{
if (!alop->als.sm && is_alop_check_tag(alop)) {
if (alop->ctx->enable_tags && !alop->als.sm && is_alop_check_tag(alop)) {
gen_delayed_tag_check(alop->ctx, tag);
}
}
#else
static inline void gen_delayed_alop_tag_check(Alop *alop, TCGv_i32 tag)
{
}
#endif
static void gen_al_result_q(Alop *alop, Tagged_ptr arg)
{
@ -7035,6 +7015,18 @@ static void gen_alc(DisasContext *ctx)
{
int i;
if (ctx->enable_tags) {
for (i = 0; i < 6; i++) {
Alop *alop = &ctx->alops[i];
if (!alop->als.sm && is_alop_check_tag(alop)) {
ctx->delayed_illop = e2k_get_temp_i32(ctx);
tcg_gen_movi_i32(ctx->delayed_illop, 0);
break;
}
}
}
for (i = 0; i < 6; i++) {
gen_alop(&ctx->alops[i]);
}
@ -7804,14 +7796,12 @@ static void do_branch(DisasContext *ctx, target_ulong pc_next)
/* FIXME: save PC only when necessary. */
gen_save_pc(ctx->base.pc_next);
#ifdef E2K_TAGS_ENABLE
{
if (ctx->enable_tags && ctx->delayed_illop) {
TCGLabel *l0 = gen_new_label();
tcg_gen_brcondi_i32(TCG_COND_EQ, ctx->delayed_illop, 0, l0);
gen_excp_illopc();
gen_set_label(l0);
}
#endif
if (ctx->ct.type == CT_NONE) {
return;
@ -7874,6 +7864,8 @@ static void e2k_tr_init_disas_context(DisasContextBase *db, CPUState *cs)
CPUE2KState *env = &cpu->env;
ctx->version = env->version;
ctx->enable_tags = env->enable_tags;
ctx->force_save_alc_dst = env->force_save_alc_dst;
if (version != ctx->version) {
if (version > 0) {
@ -7915,10 +7907,7 @@ static void e2k_tr_insn_start(DisasContextBase *db, CPUState *cs)
ctx->cs0.type = CS0_NONE;
ctx->cs1.type = CS1_NONE;
ctx->mlock = NULL;
#ifdef E2K_TAGS_ENABLE
ctx->delayed_illop = e2k_get_temp_i32(ctx);
tcg_gen_movi_i32(ctx->delayed_illop, 0);
#endif
ctx->delayed_illop = NULL;
ctx->saved_reg_len = 0;
ctx->saved_preg_len = 0;
}