e2k: Add tags and force_save_alc_dst properties.
Signed-off-by: Denis Drakhnya <numas13@gmail.com>
This commit is contained in:
parent
d84636d73a
commit
c8ed74f626
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue