target: e2k: Add mova stubs.

This commit is contained in:
Denis Drakhnia 2020-12-05 13:01:46 +02:00 committed by Denis Drakhnia
parent 250a648edf
commit 7ff1f54b8f
5 changed files with 216 additions and 107 deletions

View File

@ -3,15 +3,16 @@ e2k_ss.add(files(
'cpu.c',
'gdbstub.c',
'helper.c',
'helper_aau.c',
'helper_int.c',
'helper_sm.c',
'helper_vec.c',
'helper_aau.c',
'translate.c',
'translate/state.c',
'translate/control.c',
'translate/alc.c',
'translate/aau.c',
'translate/control.c',
'translate/plu.c',
'translate/state.c',
))
# no softmmu support yet

View File

@ -282,6 +282,8 @@ static inline void do_execute(DisasContext *ctx)
e2k_alc_execute(ctx, i);
}
}
e2k_aau_execute(ctx);
}
/*
@ -295,6 +297,7 @@ static inline void do_execute(DisasContext *ctx)
static inline void do_commit(DisasContext *ctx)
{
e2k_alc_commit(ctx);
e2k_aau_commit(ctx);
e2k_plu_commit(ctx);
e2k_commit_stubs(ctx);
}

View File

@ -132,6 +132,21 @@ typedef struct {
};
} AlResult;
typedef enum {
AAU_RESULT_NONE,
AAU_RESULT_REG32,
AAU_RESULT_REG64,
} AauResultType;
typedef struct {
AauResultType type;
TCGv_i32 index;
union {
TCGv_i32 v32;
TCGv_i64 v64;
};
} AauResult;
typedef struct {
bool is_set;
TCGv_i64 value;
@ -183,10 +198,25 @@ typedef struct DisasContext {
TCGv_i64 cond[6];
AlResult al_results[6];
AlCond al_cond[6];
AauResult aau_results[4];
PlResult pl_results[3];
ControlTransfer ct;
} DisasContext;
/* exception generated in translation time */
void e2k_tr_gen_exception(DisasContext *dc, int which);
/* exception generated in runtime */
static inline void e2k_gen_exception(int excp)
{
TCGv_i32 t0 = tcg_const_i32(excp);
// TODO: check if need to save state
gen_helper_raise_exception(cpu_env, t0);
tcg_temp_free_i32(t0);
}
static inline void e2k_gen_mask_i64(TCGv_i64 ret, TCGv_i64 len)
{
TCGv_i64 one = tcg_const_i64(1);
@ -306,44 +336,6 @@ static inline void e2k_gen_lcntex(TCGv_i32 ret)
tcg_temp_free_i32(t0);
}
static inline bool is_load_chan(int chan)
{
switch(chan) {
case 0:
case 2:
case 3:
case 5:
return true;
}
return false;
}
static inline bool is_store_chan(int chan)
{
switch(chan) {
case 2:
case 5:
return true;
}
return false;
}
static inline bool is_cmp_chan(int chan)
{
switch(chan) {
case 0:
case 1:
case 3:
case 4:
return true;
}
return false;
}
static inline bool is_div_chan(int chan) {
return chan == 5;
}
void e2k_gen_store_preg(int idx, TCGv_i64 val);
void e2k_gen_reg_tag_read_i64(TCGv_i32 ret, TCGv_i32 idx);
@ -381,6 +373,18 @@ void e2k_gen_reg_tag_check_i32(TCGv_i32 ret, TCGv_i32 tag);
void e2k_gen_reg_index_from_wregi(TCGv_i32 ret, int idx);
void e2k_gen_reg_index_from_bregi(TCGv_i32 ret, int idx);
void e2k_gen_reg_index_from_gregi(TCGv_i32 ret, int idx);
static inline void e2k_gen_reg_index(TCGv_i32 ret, uint8_t arg)
{
if (IS_BASED(arg)) {
e2k_gen_reg_index_from_bregi(ret, GET_BASED(arg));
} else if (IS_REGULAR(arg)) {
e2k_gen_reg_index_from_wregi(ret, GET_REGULAR(arg));
} else if (IS_GLOBAL(arg)) {
e2k_gen_reg_index_from_gregi(ret, GET_GLOBAL(arg));
} else {
e2k_gen_exception(E2K_EXCP_ILLOPN);
}
}
void e2k_gen_reg_read_i64(TCGv_i64 ret, TCGv_i32 idx);
void e2k_gen_reg_read_i32(TCGv_i32 ret, TCGv_i32 idx);
@ -402,25 +406,14 @@ static inline void e2k_gen_cond_i64(DisasContext *ctx, TCGv_i64 ret,
tcg_temp_free_i32(t0);
}
/* exception generated in translation time */
void e2k_tr_gen_exception(DisasContext *dc, int which);
/* exception generated in runtime */
static inline void e2k_gen_exception(int excp)
{
TCGv_i32 t0 = tcg_const_i32(excp);
// TODO: check if need to save state
gen_helper_raise_exception(cpu_env, t0);
tcg_temp_free_i32(t0);
}
void e2k_control_gen(DisasContext *dc);
void e2k_alc_execute(DisasContext *ctx, int index);
void e2k_alc_commit(DisasContext *dc);
void e2k_aau_execute(DisasContext *ctx);
void e2k_aau_commit(DisasContext *ctx);
void e2k_plu_execute(DisasContext *ctx);
void e2k_plu_commit(DisasContext *ctx);

118
target/e2k/translate/aau.c Normal file
View File

@ -0,0 +1,118 @@
#include "qemu/osdep.h"
#include "qemu.h"
#include "exec/log.h"
#include "translate.h"
typedef struct {
union {
struct {
uint16_t am: 1;
uint16_t ind: 5;
uint16_t area: 6;
uint16_t opc: 3;
uint16_t be: 1;
};
uint16_t aas;
};
uint8_t dst;
} Instr;
void e2k_aau_execute(DisasContext *ctx)
{
const UnpackedBundle *bundle = &ctx->bundle;
unsigned int i;
for (i = 0; i < 4; i++) {
Instr instr = { 0 };
AauResult *res = &ctx->aau_results[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) {
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();
}
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;
}
}
}
void e2k_aau_commit(DisasContext *ctx)
{
unsigned int i;
for (i = 0; i < 4; i++) {
AauResult *res = &ctx->aau_results[i];
TCGv_i32 zero = tcg_const_i32(0);
// TODO: aau.tags
switch(res->type) {
case AAU_RESULT_REG32:
e2k_gen_reg_tag_write_i32(zero, res->index);
e2k_gen_reg_write_i32(res->v32, res->index);
break;
case AAU_RESULT_REG64:
e2k_gen_reg_tag_write_i64(zero, res->index);
e2k_gen_reg_write_i64(res->v64, res->index);
break;
default:
break;
}
tcg_temp_free_i32(zero);
}
}

View File

@ -81,24 +81,11 @@ static inline bool is_chan_0235(int c)
return is_chan_03(c) || is_chan_25(c);
}
static inline void gen_reg_index(TCGv_i32 ret, uint8_t arg)
{
if (IS_BASED(arg)) {
e2k_gen_reg_index_from_bregi(ret, GET_BASED(arg));
} else if (IS_REGULAR(arg)) {
e2k_gen_reg_index_from_wregi(ret, GET_REGULAR(arg));
} else if (IS_GLOBAL(arg)) {
e2k_gen_reg_index_from_gregi(ret, GET_GLOBAL(arg));
} else {
e2k_gen_exception(E2K_EXCP_ILLOPN);
}
}
static inline void gen_reg_i64(DisasContext *ctx, Src64 *ret, uint8_t arg)
{
TCGv_i32 t0 = tcg_temp_new_i32();
gen_reg_index(t0, arg);
e2k_gen_reg_index(t0, arg);
ret->tag = e2k_get_temp_i32(ctx);
ret->value = e2k_get_temp_i64(ctx);
e2k_gen_reg_tag_read_i64(ret->tag, t0);
@ -111,7 +98,7 @@ static inline void gen_reg_i32(DisasContext *ctx, Src32 *ret, uint8_t arg)
{
TCGv_i32 t0 = tcg_temp_new_i32();
gen_reg_index(t0, arg);
e2k_gen_reg_index(t0, arg);
ret->tag = e2k_get_temp_i32(ctx);
ret->value = e2k_get_temp_i32(ctx);
e2k_gen_reg_tag_read_i32(ret->tag, t0);
@ -373,7 +360,7 @@ static inline void set_al_result_reg64_tag(DisasContext *ctx, int chan,
res->reg.v64 = value;
res->reg.tag = tag;
res->reg.index = e2k_get_temp_i32(ctx);
gen_reg_index(res->reg.index, arg);
e2k_gen_reg_index(res->reg.index, arg);
}
}
@ -405,7 +392,7 @@ static inline void set_al_result_reg32_tag(DisasContext *ctx, int chan,
res->reg.v32 = value;
res->reg.tag = tag;
res->reg.index = e2k_get_temp_i32(ctx);
gen_reg_index(res->reg.index, arg);
e2k_gen_reg_index(res->reg.index, arg);
}
}
@ -1166,10 +1153,12 @@ static MemOp gen_mas(DisasContext *ctx, int chan, MemOp memop, TCGv_i64 addr)
uint8_t mas = ctx->mas[chan];
if ((mas & 0x7) == 7) {
int opc = mas >> 3;
// TODO: special mas
// e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC);
qemu_log_mask(LOG_UNIMP, "0x%lx: mas=0x%x is not implemented!\n",
ctx->pc, mas);
qemu_log_mask(LOG_UNIMP, "0x%lx: mas=%#x, opc=%#x is not implemented!\n",
ctx->pc, mas, opc);
return 0;
} else if (mas) {
int mod = extract8(mas, 0, 3);
// int dc = extract8(mas, 5, 2);
@ -1177,8 +1166,8 @@ static MemOp gen_mas(DisasContext *ctx, int chan, MemOp memop, TCGv_i64 addr)
if (mod != 0) {
// TODO: mas modes
// e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC);
qemu_log_mask(LOG_UNIMP, "0x%lx: mas=0x%x is not implemented!\n",
ctx->pc, mas);
qemu_log_mask(LOG_UNIMP, "0x%lx: mas=%#x, mod=%#x is not implemented!\n",
ctx->pc, mas, mod);
}
memop |= GET_BIT(mas, 3) ? MO_BE : MO_LE;
@ -1224,6 +1213,39 @@ static void gen_ld(DisasContext *ctx, int chan, MemOp memop)
tcg_temp_free_i64(t0);
}
static void gen_st(DisasContext *ctx, int chan, MemOp memop)
{
bool sm = GET_BIT(ctx->bundle.als[chan], 31);
TCGLabel *l0 = gen_new_label();
Src64 s1 = get_src1_i64(ctx, chan);
Src64 s2 = get_src2_i64(ctx, chan);
Src64 s4 = get_src4_i64(ctx, chan);
TCGv_i64 t0 = tcg_temp_local_new_i64();
gen_tag_check(ctx, sm, s1.tag);
gen_tag_check(ctx, sm, s2.tag);
gen_tag_check(ctx, sm, s4.tag);
tcg_gen_add_i64(t0, s1.value, s2.value);
memop = gen_mas(ctx, chan, memop, t0);
if (memop == 0) {
// TODO: memop is zero after gen_mas
tcg_gen_br(l0);
}
if (sm) {
TCGv_i32 t1 = tcg_temp_new_i32();
gen_helper_probe_write_access(t1, cpu_env, t0);
tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0);
tcg_temp_free_i32(t1);
}
tcg_gen_qemu_st_i64(s4.value, t0, ctx->mmuidx, memop);
gen_set_label(l0);
tcg_temp_free_i64(t0);
}
static void gen_staa_i64(DisasContext *ctx, int chan)
{
uint32_t als = ctx->bundle.als[chan];
@ -1327,34 +1349,6 @@ static void gen_staa_i32(DisasContext *ctx, int chan)
tcg_temp_free_i32(t0);
}
static void gen_st(DisasContext *ctx, int chan, MemOp memop)
{
bool sm = GET_BIT(ctx->bundle.als[chan], 31);
TCGLabel *l0 = gen_new_label();
Src64 s1 = get_src1_i64(ctx, chan);
Src64 s2 = get_src2_i64(ctx, chan);
Src64 s4 = get_src4_i64(ctx, chan);
TCGv_i64 t0 = tcg_temp_local_new_i64();
gen_tag_check(ctx, sm, s1.tag);
gen_tag_check(ctx, sm, s2.tag);
gen_tag_check(ctx, sm, s4.tag);
tcg_gen_add_i64(t0, s1.value, s2.value);
memop = gen_mas(ctx, chan, memop, t0);
if (sm) {
TCGv_i32 t1 = tcg_temp_new_i32();
gen_helper_probe_write_access(t1, cpu_env, t0);
tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0);
tcg_temp_free_i32(t1);
}
tcg_gen_qemu_st_i64(s4.value, t0, ctx->mmuidx, memop);
gen_set_label(l0);
tcg_temp_free_i64(t0);
}
static void gen_alopf1_i64(DisasContext *ctx, int chan,
void (*op)(TCGv_i64, TCGv_i64, TCGv_i64))
{
@ -2236,14 +2230,14 @@ static void execute_ext_0b(DisasContext *ctx, Instr *instr)
{
switch(instr->opc1) {
case 0x6c:
if (is_cmp_chan(instr->chan) && ctx->version >= 4) {
if (is_chan_0134(instr->chan) && ctx->version >= 4) {
/* insfs */
gen_alopf21_i32(ctx, instr, gen_insert_field_i32);
return;
}
break;
case 0x6d:
if (is_cmp_chan(instr->chan) && ctx->version>= 4) {
if (is_chan_0134(instr->chan) && ctx->version>= 4) {
/* insfd */
gen_alopf21_i64(ctx, instr, gen_insert_field_i64);
return;
@ -2259,7 +2253,7 @@ static void execute_ext_0f(DisasContext *ctx, Instr *instr)
{
switch(instr->opc1) {
case 0x4d:
if (is_cmp_chan(instr->chan) && ctx->version >= 2) {
if (is_chan_0134(instr->chan) && ctx->version >= 2) {
/* pshufb */
gen_alopf21_i64(ctx, instr, gen_helper_packed_shuffle_i64);
return;