target: e2k: Add basic mova{b,h,w,d} impl.

This commit is contained in:
Denis Drakhnia 2020-12-08 18:57:28 +02:00
parent 261326898d
commit 74d4fbcc36
6 changed files with 287 additions and 70 deletions

View File

@ -58,6 +58,17 @@ typedef enum {
#define CTPR_IPD_END 60
#define CTPR_IPD_LEN (CTPR_IPD_END - CTPR_IPD_OFF + 1)
typedef enum {
CTPR_TAG_NONE = 0x0,
CTPR_TAG_RETURN = 0x2,
CTPR_TAG_DISP = 0x3,
CTPR_TAG_SDISP = 0x5,
} CtprTag;
typedef enum {
CTPR_OPC_LDISP = 0x1,
} CtprOpc;
#define WD_BASE_OFF 0
#define WD_BASE_END 10
#define WD_BASE_LEN (WD_BASE_END - WD_BASE_OFF + 1)
@ -360,6 +371,56 @@ typedef union {
uint8_t raw;
} E2KAalda;
/* AAU prefetch instruction */
typedef union {
struct {
union {
struct {
uint32_t abs: 5;
uint32_t asz: 3;
/* version >= 2 || si == 0 */
uint32_t ind: 4;
uint32_t incr: 3;
uint32_t aad: 5;
uint32_t mrng: 5;
uint32_t fmt: 3;
uint32_t dcd: 2;
uint32_t si: 1;
uint32_t ct: 1;
};
struct {
uint32_t unused1: 8;
/* version <= 1 && si == 1 */
uint32_t area: 5;
uint32_t am: 1;
uint32_t be: 1;
uint32_t unused2: 16;
uint32_t dpl: 1;
};
uint32_t lo;
};
union {
uint32_t disp;
uint32_t hi;
};
};
uint64_t raw;
} E2KAauPrefInstr;
typedef struct {
E2KAauPrefInstr pi; /* prefetch instr */
uint32_t cdi; /* current data index */
uint32_t ldi; /* loaded data index */
} E2KAauAreaState;
typedef struct {
E2KAauAreaState area[32];
} E2KAauPrefState;
typedef struct {
E2KAasr sr;
uint32_t fstr;
@ -372,9 +433,8 @@ typedef struct {
uint32_t inds[16];
uint32_t ind_tags;
E2KAad ds[32];
uint32_t ldi[64];
E2KAalda lda[64];
uint64_t pib[64];
E2KAauPrefState pl, pr;
} E2KAauState;
typedef union {

View File

@ -104,8 +104,12 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
return gdb_get_reg64(mem_buf, env->aau.incrs[n - 156]); // aaincrN
}
if (164 <= n && n < 228) {
return gdb_get_reg64(mem_buf, env->aau.ldi[n - 164]); // aaldiN
if (164 <= n && n < 196) {
return gdb_get_reg64(mem_buf, env->aau.pl.area[n - 164].ldi); // aaldiN
}
if (196 <= n && n < 228) {
return gdb_get_reg64(mem_buf, env->aau.pr.area[n - 196].ldi); // aaldiN
}
if (n == 228) {

View File

@ -18,3 +18,6 @@ DEF_HELPER_2(probe_read_access, int, env, tl)
DEF_HELPER_2(probe_write_access, int, env, tl)
DEF_HELPER_3(packed_shuffle_i64, i64, i64, i64, i64)
DEF_HELPER_2(pcmpeqb, i64, i64, i64)
DEF_HELPER_1(aau_load_program, void, env)
DEF_HELPER_3(mova_ptr, tl, env, int, int)
DEF_HELPER_3(aau_am, void, env, int, int)

View File

@ -4,3 +4,69 @@
#include "exec/exec-all.h"
#include "qemu/host-utils.h"
#include "exec/helper-proto.h"
static inline void init_prefetch_area(E2KAauAreaState *s, E2KAauPrefInstr pi,
uint32_t *inds)
{
if (pi.fmt != 0) {
s->pi = pi;
s->ldi = 0;
s->cdi = inds[pi.ind] & ~((1 << pi.fmt) - 1);
} else {
s->pi.raw = 0;
s->ldi = 0;
s->cdi = 0;
}
}
void HELPER(aau_load_program)(CPUE2KState *env)
{
unsigned int i;
E2KCtpr ctpr = env->ctprs[1];
if (ctpr.tag != CTPR_TAG_DISP || ctpr.opc != CTPR_OPC_LDISP) {
helper_raise_exception(env, E2K_EXCP_ILLOPC);
return;
}
for (i = 0; i < 32; i++) {
E2KAauPrefInstr l, r;
size_t offset = i * 16;
l.raw = cpu_ldq_le_data(env, ctpr.base + offset);
r.raw = cpu_ldq_le_data(env, ctpr.base + offset + 8);
init_prefetch_area(&env->aau.pl.area[i], l, env->aau.inds);
init_prefetch_area(&env->aau.pr.area[i], r, env->aau.inds);
if (l.ct || r.ct) {
break;
}
}
}
target_ulong HELPER(mova_ptr)(CPUE2KState *env, int chan, int area)
{
E2KAauPrefState *ps = chan < 2 ? &env->aau.pl : &env->aau.pr;
E2KAauAreaState *as = &ps->area[area];
E2KAauPrefInstr instr = as->pi;
E2KAad aad = env->aau.ds[instr.aad];
return aad.base + as->cdi;
}
void HELPER(aau_am)(CPUE2KState *env, int chan, int area)
{
E2KAauPrefState *ps = chan < 2 ? &env->aau.pl : &env->aau.pr;
E2KAauAreaState *as = &ps->area[area];
E2KAauPrefInstr instr = as->pi;
uint32_t incr = env->aau.incrs[instr.incr];
int size;
if (instr.fmt == 0) {
return;
}
size = 1 << (instr.fmt - 1);
as->cdi += size * incr;
}

View File

@ -37,24 +37,17 @@
#define GET_LIT(i) ((i) & 0x03)
#define GET_GLOBAL(i) ((i) & 0x1f)
typedef enum {
CTPR_TAG_NONE = 0x0,
CTPR_TAG_RETURN = 0x2,
CTPR_TAG_DISP = 0x3,
CTPR_TAG_LDISP = 0x3,
CTPR_TAG_SDISP = 0x5,
} CtprTag;
typedef enum {
CTPR_OPC_LDISP = 0x1,
} CtprOpc;
typedef enum {
ALES_NONE = 0x00,
ALES_PRESENT = 0x01,
ALES_ALLOCATED = 0x02,
} AlesFlag;
typedef struct {
TCGv_i32 cdi[32];
TCGv_i64 pib[32];
} CPUE2KAauPrefStateTCG;
typedef struct CPUE2KStateTCG {
TCGv pc;
TCGv npc;
@ -83,6 +76,7 @@ typedef struct CPUE2KStateTCG {
TCGv_i32 aaincr_tags;
TCGv_i64 aad_lo[32];
TCGv_i64 aad_hi[32];
CPUE2KAauPrefStateTCG aapl, aapr;
} CPUE2KStateTCG;
extern struct CPUE2KStateTCG e2k_cs;
@ -150,6 +144,7 @@ typedef enum {
typedef struct {
AauResultType type;
uint8_t dst;
TCGv_i32 index;
union {
TCGv_i32 v32;
@ -209,6 +204,7 @@ typedef struct DisasContext {
AlResult al_results[6];
AlCond al_cond[6];
AauResult aau_results[4];
int aau_am[4];
PlResult pl_results[3];
ControlTransfer ct;
} DisasContext;

View File

@ -4,6 +4,7 @@
#include "translate.h"
typedef struct {
int chan;
union {
struct {
uint16_t am: 1;
@ -17,6 +18,121 @@ typedef struct {
uint8_t dst;
} Instr;
static void gen_load_prefetch_program(DisasContext *ctx)
{
gen_helper_aau_load_program(cpu_env);
}
static void gen_aau_result_reg64(DisasContext *ctx, Instr *instr, TCGv_i64 dst)
{
AauResult *res = &ctx->aau_results[instr->chan];
res->type = AAU_RESULT_REG64;
res->dst = instr->dst;
res->index = e2k_get_temp_i32(ctx);
res->v64 = dst;
if (IS_REGULAR(instr->dst)) {
res->dst = instr->dst;
} else {
res->dst = 0;
e2k_gen_reg_index(res->index, instr->dst);
}
}
static void gen_aau_result_reg32(DisasContext *ctx, Instr *instr, TCGv_i32 dst)
{
AauResult *res = &ctx->aau_results[instr->chan];
res->type = AAU_RESULT_REG32;
res->dst = instr->dst;
res->index = e2k_get_temp_i32(ctx);
res->v32 = dst;
if (IS_REGULAR(instr->dst)) {
res->dst = instr->dst;
} else {
res->dst = 0;
e2k_gen_reg_index(res->index, instr->dst);
}
}
static void gen_mova_i32(DisasContext *ctx, Instr *instr, TCGv ptr)
{
MemOp memop = instr->be ? MO_BE : MO_LE;
TCGv_i32 dst = e2k_get_temp_i32(ctx);
switch(instr->opc) {
case 1: memop |= MO_8; break; /* movab */
case 2: memop |= MO_16; break; /* movah */
case 3: memop |= MO_32; break; /* movaw */
default:
g_assert_not_reached();
break;
}
tcg_gen_qemu_ld_i32(dst, ptr, 0, memop);
gen_aau_result_reg32(ctx, instr, dst);
}
static void gen_mova_i64(DisasContext *ctx, Instr *instr, TCGv ptr)
{
TCGv_i64 dst = e2k_get_temp_i64(ctx);
tcg_gen_qemu_ld_i64(dst, ptr, 0, instr->be ? MO_BEQ : MO_LEQ);
gen_aau_result_reg64(ctx, instr, dst);
}
static inline void gen_mova_ptr(TCGv ret, Instr *instr)
{
TCGv_i32 t0 = tcg_const_i32(instr->chan);
TCGv_i32 t1 = tcg_const_i32(instr->area);
TCGv t2 = tcg_temp_new();
gen_helper_mova_ptr(t2, cpu_env, t0, t1);
tcg_gen_addi_tl(ret, t2, instr->ind);
tcg_temp_free(t2);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
}
static void gen_mova(DisasContext *ctx, Instr *instr)
{
TCGv t5 = tcg_temp_new();
ctx->aau_am[instr->chan] = instr->am ? instr->area : -1;
// TODO: check ind
gen_mova_ptr(t5, instr);
switch(instr->opc) {
case 1: /* movab */
case 2: /* movah */
case 3: /* movaw */
gen_mova_i32(ctx, instr, t5);
break;
case 4: /* movad */
gen_mova_i64(ctx, instr, t5);
break;
case 5: /* movaq */
abort();
break;
case 7: /* movaqp */
abort();
break;
default:
e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC);
break;
}
tcg_temp_free(t5);
}
static inline void gen_aau_am(DisasContext *ctx, int chan, int area)
{
TCGv_i32 t0 = tcg_const_i32(chan);
TCGv_i32 t1 = tcg_const_i32(area);
gen_helper_aau_am(cpu_env, t0, t1);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
}
void e2k_aau_execute(DisasContext *ctx)
{
const UnpackedBundle *bundle = &ctx->bundle;
@ -26,68 +142,22 @@ void e2k_aau_execute(DisasContext *ctx)
Instr instr = { 0 };
AauResult *res = &ctx->aau_results[i];
instr.chan = i;
instr.aas = bundle->aas[i + 2];
instr.dst = extract16(bundle->aas[i / 2], ((i & 1) ^ 1) * 8, 8);
if (!bundle->aas_present[i + 2] || instr.opc == 0) {
ctx->aau_am[i] = -1;
res->type = AAU_RESULT_NONE;
continue;
}
if (instr.be) {
// TODO: aas.be
qemu_log_mask(LOG_UNIMP, "0x%lx: aas.be is not implemented\n",
ctx->pc);
abort();
}
gen_mova(ctx, &instr);
}
if (instr.am) {
// TODO: aas.am
qemu_log_mask(LOG_UNIMP, "0x%lx: aas.be is not implemented\n",
ctx->pc);
abort();
}
switch(instr.opc) {
case 1:
// TODO: movab
qemu_log_mask(LOG_UNIMP, "0x%lx: movab is not implemented\n",
ctx->pc);
abort();
break;
case 2:
// TODO: movah
qemu_log_mask(LOG_UNIMP, "0x%lx: movah is not implemented\n",
ctx->pc);
abort();
break;
case 3:
// TODO: movaw
qemu_log_mask(LOG_UNIMP, "0x%lx: movaw is not implemented\n",
ctx->pc);
abort();
break;
case 4:
// TODO: movad
qemu_log_mask(LOG_UNIMP, "0x%lx: movad is not implemented\n",
ctx->pc);
abort();
break;
case 5:
// TODO: movaq
qemu_log_mask(LOG_UNIMP, "0x%lx: movaq is not implemented\n",
ctx->pc);
abort();
break;
case 7:
// TODO: movaqp
qemu_log_mask(LOG_UNIMP, "0x%lx: movaqp is not implemented\n",
ctx->pc);
abort();
break;
default:
e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC);
return;
}
/* bap */
if (ctx->bundle.ss & (1 << 28)) {
gen_load_prefetch_program(ctx);
}
}
@ -95,6 +165,16 @@ void e2k_aau_commit(DisasContext *ctx)
{
unsigned int i;
for (i = 0; i < 4; i++) {
AauResult *res = &ctx->aau_results[i];
if (res->type == AAU_RESULT_REG32 || res->type == AAU_RESULT_REG64) {
if (IS_REGULAR(res->dst)) {
e2k_gen_reg_index_from_wregi(res->index, GET_REGULAR(res->dst));
}
}
}
for (i = 0; i < 4; i++) {
AauResult *res = &ctx->aau_results[i];
TCGv_i32 zero = tcg_const_i32(0);
@ -115,4 +195,12 @@ void e2k_aau_commit(DisasContext *ctx)
tcg_temp_free_i32(zero);
}
for (i = 0; i < 4; i++) {
int area = ctx->aau_am[i];
if (area == -1 || ((i == 1 || i == 3) && ctx->aau_am[i - 1] == area)) {
continue;
}
gen_aau_am(ctx, i, area);
}
}