target: e2k: Add getsp instr.
This commit is contained in:
parent
5c48cf014b
commit
7c4f2f0a3c
|
@ -45,6 +45,9 @@ static void e2k_cpu_reset(DeviceState *dev)
|
||||||
memset(env, 0, offsetof(CPUE2KState, end_reset_fields));
|
memset(env, 0, offsetof(CPUE2KState, end_reset_fields));
|
||||||
|
|
||||||
env->win_ptr = env->wregs;
|
env->win_ptr = env->wregs;
|
||||||
|
|
||||||
|
env->usd_hi = 0x2088000000000UL;
|
||||||
|
env->usd_lo = 0x1800c2dfffffe880UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SOFTMMU
|
#ifdef CONFIG_SOFTMMU
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
#include "translate.h"
|
#include "translate.h"
|
||||||
|
|
||||||
static TCGv_i64 get_src1(DisasContext *dc, unsigned int als)
|
static TCGv_i64 get_src1(DisasContext *dc, uint32_t als)
|
||||||
{
|
{
|
||||||
unsigned int src1 = GET_FIELD(als, 16, 27);
|
unsigned int src1 = GET_FIELD(als, 16, 27);
|
||||||
if (IS_BASED(src1)) {
|
if (IS_BASED(src1)) {
|
||||||
|
@ -23,7 +23,7 @@ static TCGv_i64 get_src1(DisasContext *dc, unsigned int als)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static TCGv_i64 get_src2(DisasContext *dc, unsigned int als)
|
static TCGv_i64 get_src2(DisasContext *dc, uint32_t als)
|
||||||
{
|
{
|
||||||
unsigned int src2 = GET_FIELD(als, 8, 15);
|
unsigned int src2 = GET_FIELD(als, 8, 15);
|
||||||
if (IS_BASED(src2)) {
|
if (IS_BASED(src2)) {
|
||||||
|
@ -44,9 +44,9 @@ static TCGv_i64 get_src2(DisasContext *dc, unsigned int als)
|
||||||
// TODO: exception
|
// TODO: exception
|
||||||
assert(dc->bundle.lts_present[i]);
|
assert(dc->bundle.lts_present[i]);
|
||||||
if (IS_LIT16_LO(src2) && i < 2) {
|
if (IS_LIT16_LO(src2) && i < 2) {
|
||||||
lit &= 0xffff;
|
lit = ((int64_t) lit & 0xffff) << 48 >> 48;
|
||||||
} else if (IS_LIT16_HI(src2) && i < 2) {
|
} else if (IS_LIT16_HI(src2) && i < 2) {
|
||||||
lit >>= 16;
|
lit = ((int64_t) lit >> 16) << 48 >> 48;
|
||||||
} else if (IS_LIT32(src2)) {
|
} else if (IS_LIT32(src2)) {
|
||||||
// nop
|
// nop
|
||||||
} else if (IS_LIT64(src2) && i < 3) {
|
} else if (IS_LIT64(src2) && i < 3) {
|
||||||
|
@ -257,18 +257,14 @@ static inline void gen_mrgc_i32(DisasContext *dc, int chan, TCGv_i32 ret)
|
||||||
tcg_temp_free(t0);
|
tcg_temp_free(t0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void gen_rwd(DisasContext *dc, int chan)
|
static inline void gen_rr_i64(TCGv_i64 ret, uint8_t state_reg)
|
||||||
{
|
{
|
||||||
uint32_t als = dc->bundle.als[chan];
|
|
||||||
TCGv_i64 src2 = get_src2(dc, als);
|
|
||||||
uint8_t state_reg = als;
|
|
||||||
|
|
||||||
switch (state_reg) {
|
switch (state_reg) {
|
||||||
case 0x2c: /* %usd.hi */
|
case 0x2c: /* %usd.hi */
|
||||||
tcg_gen_mov_i64(e2k_cs.usd_hi, src2);
|
tcg_gen_mov_i64(ret, e2k_cs.usd_hi);
|
||||||
break;
|
break;
|
||||||
case 0x2d: /* %usd.lo */
|
case 0x2d: /* %usd.lo */
|
||||||
tcg_gen_mov_i64(e2k_cs.usd_lo, src2);
|
tcg_gen_mov_i64(ret, e2k_cs.usd_lo);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* TODO: exception */
|
/* TODO: exception */
|
||||||
|
@ -283,20 +279,78 @@ static inline void gen_rrd(DisasContext *dc, int chan)
|
||||||
uint8_t state_reg = GET_FIELD(als, 16, 23);
|
uint8_t state_reg = GET_FIELD(als, 16, 23);
|
||||||
TCGv_i64 ret = e2k_get_temp_i64(dc);
|
TCGv_i64 ret = e2k_get_temp_i64(dc);
|
||||||
|
|
||||||
|
gen_rr_i64(ret, state_reg);
|
||||||
|
store_reg_alc_result(dc, chan, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void gen_rrs(DisasContext *dc, int chan)
|
||||||
|
{
|
||||||
|
uint32_t als = dc->bundle.als[chan];
|
||||||
|
uint8_t state_reg = GET_FIELD(als, 16, 23);
|
||||||
|
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||||
|
TCGv_i64 t1 = e2k_get_temp_i64(dc);
|
||||||
|
|
||||||
|
gen_rr_i64(t0, state_reg);
|
||||||
|
gen_movehl_i64(t1, t0, get_dst(dc, als));
|
||||||
|
store_reg_alc_result(dc, chan, t1);
|
||||||
|
|
||||||
|
tcg_temp_free_i64(t0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void gen_rw_i64(uint8_t state_reg, TCGv_i64 val)
|
||||||
|
{
|
||||||
switch (state_reg) {
|
switch (state_reg) {
|
||||||
case 0x2c: /* %usd.hi */
|
case 0x2c: /* %usd.hi */
|
||||||
tcg_gen_mov_i64(ret, e2k_cs.usd_hi);
|
/* FIXME: user cannot write */
|
||||||
|
tcg_gen_mov_i64(e2k_cs.usd_hi, val);
|
||||||
break;
|
break;
|
||||||
case 0x2d: /* %usd.lo */
|
case 0x2d: /* %usd.lo */
|
||||||
tcg_gen_mov_i64(ret, e2k_cs.usd_lo);
|
/* FIXME: user cannot write */
|
||||||
|
tcg_gen_mov_i64(e2k_cs.usd_lo, val);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* TODO: exception */
|
/* TODO: exception */
|
||||||
abort();
|
abort();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
store_reg_alc_result(dc, chan, ret);
|
static inline void gen_rwd(DisasContext *dc, int chan)
|
||||||
|
{
|
||||||
|
uint32_t als = dc->bundle.als[chan];
|
||||||
|
TCGv_i64 src2 = get_src2(dc, als);
|
||||||
|
gen_rw_i64(als & 0xff, src2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void gen_rws(DisasContext *dc, int chan)
|
||||||
|
{
|
||||||
|
uint32_t als = dc->bundle.als[chan];
|
||||||
|
uint8_t state_reg = als & 0xff;
|
||||||
|
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||||
|
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||||
|
|
||||||
|
gen_rr_i64(t0, state_reg);
|
||||||
|
gen_movehl_i64(t1, get_src2(dc, als), t0);
|
||||||
|
gen_rw_i64(state_reg, t1);
|
||||||
|
|
||||||
|
tcg_temp_free_i64(t1);
|
||||||
|
tcg_temp_free_i64(t0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gen_getsp(DisasContext *dc, int chan)
|
||||||
|
{
|
||||||
|
uint32_t als = dc->bundle.als[chan];
|
||||||
|
TCGv_i64 src2 = get_src2(dc, als);
|
||||||
|
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||||
|
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||||
|
|
||||||
|
/* TODO: exception stack overflow */
|
||||||
|
tcg_gen_extract_i64(t0, e2k_cs.usd_lo, 0, 48);
|
||||||
|
tcg_gen_add_i64(t1, t0, src2);
|
||||||
|
tcg_gen_deposit_i64(e2k_cs.usd_lo, e2k_cs.usd_lo, t1, 0, 48);
|
||||||
|
|
||||||
|
tcg_temp_free_i64(t1);
|
||||||
|
tcg_temp_free_i64(t0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_op2_i32(TCGv_i64 ret, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 dst,
|
static void gen_op2_i32(TCGv_i64 ret, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 dst,
|
||||||
|
@ -373,13 +427,8 @@ static void gen_alopf_simple(DisasContext *dc, int chan)
|
||||||
uint32_t als = dc->bundle.als[chan];
|
uint32_t als = dc->bundle.als[chan];
|
||||||
int opc = GET_FIELD(als, 24, 30);
|
int opc = GET_FIELD(als, 24, 30);
|
||||||
int sm = GET_BIT(als, 31);
|
int sm = GET_BIT(als, 31);
|
||||||
bool is_cmp = false;
|
|
||||||
Result res = { 0 };
|
Result res = { 0 };
|
||||||
|
|
||||||
TCGv_i64 cpu_src1 = get_src1(dc, als);
|
|
||||||
TCGv_i64 cpu_src2 = get_src2(dc, als);
|
|
||||||
TCGv_i64 tmp_dst = e2k_get_temp_i64(dc);
|
|
||||||
|
|
||||||
switch(opc) {
|
switch(opc) {
|
||||||
case 0x00: /* ands */ gen_alopf1_i32(dc, chan, tcg_gen_and_i32); break;
|
case 0x00: /* ands */ gen_alopf1_i32(dc, chan, tcg_gen_and_i32); break;
|
||||||
case 0x01: /* andd */ gen_alopf1_i64(dc, chan, tcg_gen_and_i64); break;
|
case 0x01: /* andd */ gen_alopf1_i64(dc, chan, tcg_gen_and_i64); break;
|
||||||
|
@ -413,7 +462,10 @@ static void gen_alopf_simple(DisasContext *dc, int chan)
|
||||||
case 0x1e: /* TODO: getfs */ abort(); break;
|
case 0x1e: /* TODO: getfs */ abort(); break;
|
||||||
case 0x1f: /* TODO: getfd */ abort(); break;
|
case 0x1f: /* TODO: getfd */ abort(); break;
|
||||||
case 0x21: { // cmp{op}sd
|
case 0x21: { // cmp{op}sd
|
||||||
is_cmp = true;
|
TCGv_i64 cpu_src1 = get_src1(dc, als);
|
||||||
|
TCGv_i64 cpu_src2 = get_src2(dc, als);
|
||||||
|
TCGv_i64 tmp_dst = e2k_get_temp_i64(dc);
|
||||||
|
|
||||||
unsigned int cmp_op = GET_FIELD(als, 5, 7);
|
unsigned int cmp_op = GET_FIELD(als, 5, 7);
|
||||||
// TODO: move to separate function
|
// TODO: move to separate function
|
||||||
switch(cmp_op) {
|
switch(cmp_op) {
|
||||||
|
@ -427,6 +479,12 @@ static void gen_alopf_simple(DisasContext *dc, int chan)
|
||||||
abort();
|
abort();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res.tag = RESULT_PREG;
|
||||||
|
res.u.reg.i = als & 0x1f;
|
||||||
|
res.u.reg.v = tmp_dst;
|
||||||
|
dc->alc[chan] = res;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x40: // TODO: udivs used as temporary UD
|
case 0x40: // TODO: udivs used as temporary UD
|
||||||
|
@ -436,13 +494,6 @@ static void gen_alopf_simple(DisasContext *dc, int chan)
|
||||||
qemu_log_mask(LOG_UNIMP, "gen_alc: undefined instruction 0x%x %s\n", opc, sm ? "(speculative)" : "");
|
qemu_log_mask(LOG_UNIMP, "gen_alc: undefined instruction 0x%x %s\n", opc, sm ? "(speculative)" : "");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_cmp) {
|
|
||||||
res.tag = RESULT_PREG;
|
|
||||||
res.u.reg.i = als & 0x1f;
|
|
||||||
res.u.reg.v = tmp_dst;
|
|
||||||
dc->alc[chan] = res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_ext1(DisasContext *dc, int chan)
|
static void gen_ext1(DisasContext *dc, int chan)
|
||||||
|
@ -450,13 +501,19 @@ static void gen_ext1(DisasContext *dc, int chan)
|
||||||
uint8_t opc = GET_FIELD(dc->bundle.als[chan], 24, 30);
|
uint8_t opc = GET_FIELD(dc->bundle.als[chan], 24, 30);
|
||||||
|
|
||||||
switch (opc) {
|
switch (opc) {
|
||||||
case 0x3c: /* rws */ break; /* TODO: only channel 1 */
|
case 0x58: {
|
||||||
|
if (chan == 0 || chan == 3) {
|
||||||
|
gen_getsp(dc, chan);
|
||||||
|
}
|
||||||
|
/* TODO: exception */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0x3c: /* rws */ gen_rws(dc, chan); break; /* TODO: only channel 1 */
|
||||||
case 0x3d: /* rwd */ gen_rwd(dc, chan); break; /* TODO: only channel 1 */
|
case 0x3d: /* rwd */ gen_rwd(dc, chan); break; /* TODO: only channel 1 */
|
||||||
case 0x3e: /* rrs */ break; /* TODO: only channel 1 */
|
case 0x3e: /* rrs */ gen_rrs(dc, chan); break; /* TODO: only channel 1 */
|
||||||
case 0x3f: /* rrd */ gen_rrd(dc, chan); break; /* TODO: only channel 1 */
|
case 0x3f: /* rrd */ gen_rrd(dc, chan); break; /* TODO: only channel 1 */
|
||||||
default:
|
default:
|
||||||
/* TODO: exception */
|
/* TODO: exception */
|
||||||
abort();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -473,8 +530,7 @@ static void gen_channel(DisasContext *dc, int chan)
|
||||||
abort();
|
abort();
|
||||||
break;
|
break;
|
||||||
case ALES_PRESENT: {
|
case ALES_PRESENT: {
|
||||||
uint16_t ales = bundle->ales[chan];
|
uint8_t opc = GET_FIELD(bundle->ales[chan], 8, 15);
|
||||||
uint8_t opc = ales >> 8;
|
|
||||||
switch (opc) {
|
switch (opc) {
|
||||||
case 0x01:
|
case 0x01:
|
||||||
gen_ext1(dc, chan);
|
gen_ext1(dc, chan);
|
||||||
|
@ -500,6 +556,7 @@ void e2k_alc_gen(DisasContext *dc)
|
||||||
if (!dc->bundle.als_present[i]) {
|
if (!dc->bundle.als_present[i]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
dc->alc[i].tag = RESULT_NONE;
|
||||||
gen_channel(dc, i);
|
gen_channel(dc, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue