target: e2k: Add basic mova{b,h,w,d} impl.
This commit is contained in:
parent
261326898d
commit
74d4fbcc36
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue