target: e2k: Add procedure stack.
This commit is contained in:
parent
88e79dcda9
commit
59bdb69c27
@ -54,6 +54,7 @@ void cpu_loop(CPUE2KState *env)
|
||||
);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
/* TODO: restart syscall */
|
||||
abort();
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
unsigned int i;
|
||||
|
||||
@ -62,6 +63,7 @@ void cpu_loop(CPUE2KState *env)
|
||||
regs[(i + offset) % WREGS_SIZE] = 0;
|
||||
}
|
||||
}
|
||||
env->ip = env->nip;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -69,6 +69,14 @@ static const struct e2k_def_t e2k_defs[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static inline void cpu_dump_state_wd(CPUE2KState *env, FILE *f, int flags)
|
||||
{
|
||||
int wbs = GET_FIELD(env->cr1_lo, CR1_LO_WBS_OFF, CR1_LO_WBS_END);
|
||||
int wsz = GET_FIELD(env->cr1_lo, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_END);
|
||||
|
||||
qemu_fprintf(f, "wbs = %#x, wsz = %#x\n", wbs, wsz);
|
||||
}
|
||||
|
||||
static inline void cpu_dump_state_br(CPUE2KState *env, FILE *f, int flags)
|
||||
{
|
||||
uint32_t br = GET_FIELD(env->cr1_hi, CR1_HI_BR_OFF, CR1_HI_BR_END);
|
||||
@ -102,7 +110,7 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
env->cr1_hi, env->cr1_lo);
|
||||
qemu_fprintf(f, "usd_hi: %016lx, usd_lo: %016lx\n",
|
||||
env->usd_hi, env->usd_lo);
|
||||
/* TODO qemu_fprintf(f, "wbs: %d, wsz: %d\n", (int) env->wbs, (int) env->wsz); */
|
||||
cpu_dump_state_wd(env, f, flags);
|
||||
cpu_dump_state_br(env, f, flags);
|
||||
qemu_fprintf(f, "lsr: %016lx\n", env->lsr);
|
||||
|
||||
|
@ -70,7 +70,34 @@ void e2k_tcg_initialize(void);
|
||||
#define PSP_LO_WRITE_OFF 60
|
||||
#define PSP_LO_WRITE_BIT (1UL << PSP_LO_WRITE_OFF)
|
||||
|
||||
#define PSHTP
|
||||
#define PSHTP_IND_OFF 0
|
||||
#define PSHTP_IND_END 11
|
||||
#define PSHTP_IND_LEN (PSHTP_IND_END - PSHTP_IND_OFF + 1)
|
||||
#define PSHTP_FXIND_OFF 16
|
||||
#define PSHTP_FXIND_END 26
|
||||
#define PSHTP_FXIND_LEN (PSHTP_FXIND_END - PSHTP_FXIND_OFF + 1)
|
||||
#define PSHTP_TIND_OFF 32
|
||||
#define PSHTP_TIND_END 42
|
||||
#define PSHTP_TIND_LEN (PSHTP_TIND_END - PSHTP_TIND_OFF + 1)
|
||||
#define PSHTP_FX_OFF 48
|
||||
#define PSHTP_FX_BIT (1UL << PSHTP_FX_OFF)
|
||||
|
||||
#define USD_LO_BASE_OFF 0
|
||||
#define USD_LO_BASE_END 47
|
||||
#define USD_LO_BASE_LEN (USD_LO_BASE_END - USD_LO_BASE_OFF + 1)
|
||||
#define USD_LO_PROTECTED_OFF 58
|
||||
#define USD_LO_PROTECTED_BIT (1UL << USD_LO_PROTECTED_OFF)
|
||||
#define USD_LO_READ_OFF 59
|
||||
#define USD_LO_READ_BIT (1UL << USD_LO_READ_OFF)
|
||||
#define USD_LO_WRITE_OFF 60
|
||||
#define USD_LO_WRITE_BIT (1UL << USD_LO_WRITE_OFF)
|
||||
|
||||
#define USD_HI_CURPTR_OFF 0
|
||||
#define USD_HI_CURPTR_END 31
|
||||
#define USD_HI_CURPTR_LEN (USD_HI_CURPTR_END - USD_HI_CURPTR_OFF + 1)
|
||||
#define USD_HI_SIZE_OFF 32
|
||||
#define USD_HI_SIZE_END 63
|
||||
#define USD_HI_SIZE_LEN (USD_HI_SIZE_END - USD_HI_SIZE_OFF + 1)
|
||||
|
||||
#define CR1_HI_BR_OFF 0
|
||||
#define CR1_HI_BR_END 27
|
||||
@ -180,6 +207,13 @@ typedef struct {
|
||||
uint64_t lsr; /* loop status register */
|
||||
|
||||
uint32_t call_wbs;
|
||||
uint32_t woff; /* holds wbs * 2 */
|
||||
uint32_t wsize; /* holds wsz * 2 */
|
||||
uint32_t boff; /* holds rbs * 2 */
|
||||
uint32_t bsize; /* holds rsz * 2 + 2 */
|
||||
uint32_t bcur; /* holds rcur * 2 */
|
||||
uint32_t psize; /* holds psz */
|
||||
uint32_t pcur; /* holds pcur */
|
||||
|
||||
uint64_t usd_lo;
|
||||
uint64_t usd_hi;
|
||||
@ -191,6 +225,8 @@ typedef struct {
|
||||
target_ulong ip; /* instruction address */
|
||||
target_ulong nip; /* next instruction address */
|
||||
|
||||
uint32_t cond; /* branch condition */
|
||||
|
||||
uint32_t pfpfr; // Packed Floating Point Flag Register (PFPFR)
|
||||
uint32_t fpcr; // Floating point control register (FPCR)
|
||||
uint32_t fpsr; // Floating point state register (FPSR)
|
||||
@ -265,6 +301,21 @@ static inline void e2k_state_pcs_size_set(CPUE2KState *env, size_t size)
|
||||
PCSP_HI_SIZE_LEN);
|
||||
}
|
||||
|
||||
static inline target_ulong e2k_state_ps_base_get(CPUE2KState *env)
|
||||
{
|
||||
return GET_FIELD(env->psp_lo, PSP_LO_BASE_OFF, PSP_LO_BASE_END);
|
||||
}
|
||||
|
||||
static inline size_t e2k_state_ps_ind_get(CPUE2KState *env)
|
||||
{
|
||||
return GET_FIELD(env->psp_hi, PSP_HI_IND_OFF, PSP_HI_IND_LEN);
|
||||
}
|
||||
|
||||
static inline void e2k_state_ps_ind_set(CPUE2KState *env, size_t ind)
|
||||
{
|
||||
env->psp_hi = SET_FIELD(env->psp_hi, ind, PSP_HI_IND_OFF, PSP_HI_IND_LEN);
|
||||
}
|
||||
|
||||
static inline int e2k_state_wbs_get(CPUE2KState *env)
|
||||
{
|
||||
return GET_FIELD(env->cr1_lo, CR1_LO_WBS_OFF, CR1_LO_WBS_END);
|
||||
|
@ -6,10 +6,52 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "translate.h"
|
||||
|
||||
static inline void save_state(CPUE2KState *env)
|
||||
{
|
||||
uint32_t br = 0;
|
||||
|
||||
br = SET_FIELD(br, env->boff / 2, BR_RBS_OFF, BR_RBS_LEN);
|
||||
br = SET_FIELD(br, (env->bsize - 2) / 2, BR_RSZ_OFF, BR_RSZ_LEN);
|
||||
br = SET_FIELD(br, env->bcur / 2, BR_RCUR_OFF, BR_RCUR_LEN);
|
||||
br = SET_FIELD(br, env->psize, BR_PSZ_OFF, BR_PSZ_LEN);
|
||||
br = SET_FIELD(br, env->pcur, BR_PCUR_OFF, BR_PCUR_LEN);
|
||||
|
||||
env->cr1_hi = SET_FIELD(env->cr1_hi, br, CR1_HI_BR_OFF + BR_BN_OFF,
|
||||
BR_BN_LEN);
|
||||
|
||||
env->cr1_lo = SET_FIELD(env->cr1_lo, env->wsize / 2,
|
||||
CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_LEN);
|
||||
}
|
||||
|
||||
static inline void restore_state(CPUE2KState *env)
|
||||
{
|
||||
uint32_t br;
|
||||
int rbs, rsz, rcur, psz, pcur, wsz, wbs;
|
||||
|
||||
br = GET_FIELD(env->cr1_hi, CR1_HI_BR_OFF, CR1_HI_BR_LEN);
|
||||
rbs = GET_FIELD(br, BR_RBS_OFF, BR_RBS_END);
|
||||
rsz = GET_FIELD(br, BR_RSZ_OFF, BR_RSZ_END);
|
||||
rcur = GET_FIELD(br, BR_RCUR_OFF, BR_RCUR_END);
|
||||
psz = GET_FIELD(br, BR_PSZ_OFF, BR_PSZ_END);
|
||||
pcur = GET_FIELD(br, BR_PCUR_OFF, BR_PCUR_END);
|
||||
|
||||
wbs = GET_FIELD(env->cr1_lo, CR1_LO_WBS_OFF, CR1_LO_WBS_END);
|
||||
wsz = GET_FIELD(env->cr1_lo, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_END);
|
||||
|
||||
env->boff = rbs * 2;
|
||||
env->bsize = rsz * 2 + 2;
|
||||
env->bcur = rcur * 2;
|
||||
env->psize = psz;
|
||||
env->pcur = pcur;
|
||||
|
||||
env->woff = wbs * 2;
|
||||
env->wsize = wsz * 2;
|
||||
}
|
||||
|
||||
void helper_raise_exception(CPUE2KState *env, int tt)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
save_state(env);
|
||||
cs->exception_index = tt;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
@ -33,10 +75,11 @@ static void pcs_push(CPUE2KState *env)
|
||||
e2k_state_pcs_index_set(env, offset + 32);
|
||||
}
|
||||
|
||||
static void pcs_pop(CPUE2KState *env)
|
||||
static uint64_t pcs_pop(CPUE2KState *env)
|
||||
{
|
||||
size_t offset = e2k_state_pcs_index_get(env);
|
||||
uint64_t *pcsp = (uint64_t *) (e2k_state_pcs_base_get(env) + offset - 32);
|
||||
uint64_t tgt;
|
||||
|
||||
if (offset < 32) {
|
||||
/* TODO: SIGKILL */
|
||||
@ -44,11 +87,47 @@ static void pcs_pop(CPUE2KState *env)
|
||||
}
|
||||
|
||||
memcpy(&env->pf, pcsp, 8);
|
||||
memcpy(&env->ip, pcsp + 1, 8);
|
||||
memcpy(&tgt, pcsp + 1, 8);
|
||||
memcpy(&env->cr1_lo, pcsp + 2, 8);
|
||||
memcpy(&env->cr1_hi, pcsp + 3, 8);
|
||||
|
||||
e2k_state_pcs_index_set(env, offset - 32);
|
||||
|
||||
return tgt;
|
||||
}
|
||||
|
||||
static void ps_push(CPUE2KState *env, unsigned int wbs, size_t len)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t index = e2k_state_ps_ind_get(env);
|
||||
uint64_t *p = (uint64_t*) (e2k_state_ps_base_get(env) + index);
|
||||
|
||||
/* TODO: push FX registers */
|
||||
/* TODO: stack overflow */
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
uint64_t reg = env->wregs[(wbs + i) % WREGS_SIZE];
|
||||
memcpy(p + i, ®, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
e2k_state_ps_ind_set(env, index + len * sizeof(uint64_t));
|
||||
}
|
||||
|
||||
static void ps_pop(CPUE2KState *env, unsigned int wbs, size_t len)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t index = e2k_state_ps_ind_get(env) - len * sizeof(uint64_t);
|
||||
uint64_t *p = (uint64_t*) (e2k_state_ps_base_get(env) + index);
|
||||
|
||||
/* TODO: pop FX registers */
|
||||
/* TODO: stack overflow */
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
uint64_t *reg = &env->wregs[(wbs + i) % WREGS_SIZE];
|
||||
memcpy(reg, p + i, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
e2k_state_ps_ind_set(env, index);
|
||||
}
|
||||
|
||||
static inline void do_call(CPUE2KState *env, target_ulong ctpr)
|
||||
@ -57,7 +136,7 @@ static inline void do_call(CPUE2KState *env, target_ulong ctpr)
|
||||
|
||||
wbs = e2k_state_wbs_get(env);
|
||||
wsz = e2k_state_wsz_get(env);
|
||||
new_wbs = (wbs + env->call_wbs) % WREGS_SIZE;
|
||||
new_wbs = (wbs + env->call_wbs) % (WREGS_SIZE / 2);
|
||||
new_wsz = wsz - env->call_wbs;
|
||||
|
||||
if (new_wsz < 0) {
|
||||
@ -67,104 +146,101 @@ static inline void do_call(CPUE2KState *env, target_ulong ctpr)
|
||||
|
||||
/* save procedure chain info */
|
||||
pcs_push(env);
|
||||
/* save regs */
|
||||
ps_push(env, wbs * 2, env->call_wbs * 2);
|
||||
|
||||
e2k_state_wbs_set(env, new_wbs);
|
||||
e2k_state_wsz_set(env, new_wsz);
|
||||
|
||||
env->ip = GET_FIELD(ctpr, CTPR_BASE_OFF, CTPR_BASE_END);
|
||||
/* restore woff, wsize, etc */
|
||||
restore_state(env);
|
||||
}
|
||||
|
||||
static void do_return(CPUE2KState *env)
|
||||
static uint64_t do_return(CPUE2KState *env)
|
||||
{
|
||||
// uint64_t *psp = (uint64_t *) GET_FIELD(env->psp_lo, PSP_LO_BASE_OFF,
|
||||
// PSP_LO_BASE_END);
|
||||
int new_wbs, old_wbs;
|
||||
uint64_t tgt;
|
||||
|
||||
old_wbs = e2k_state_wbs_get(env) * 2;
|
||||
|
||||
/* restore procedure chain info */
|
||||
pcs_pop(env);
|
||||
tgt = pcs_pop(env);
|
||||
|
||||
// TODO: restore regs
|
||||
new_wbs = e2k_state_wbs_get(env) * 2;
|
||||
|
||||
if (old_wbs < new_wbs) {
|
||||
old_wbs += WREGS_SIZE;
|
||||
}
|
||||
|
||||
ps_pop(env, new_wbs, old_wbs - new_wbs);
|
||||
|
||||
/* restore woff, wsize, etc */
|
||||
restore_state(env);
|
||||
|
||||
return tgt;
|
||||
}
|
||||
|
||||
void helper_call(CPUE2KState *env, target_ulong cond, target_ulong ctpr)
|
||||
static inline void reset_ctprs(CPUE2KState *env)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
if (!cond) {
|
||||
env->ip = env->nip;
|
||||
return;
|
||||
}
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
env->ctprs[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END)) {
|
||||
target_ulong helper_jump(CPUE2KState *env, int i)
|
||||
{
|
||||
return helper_branch(env, i, true);
|
||||
}
|
||||
|
||||
target_ulong helper_branch(CPUE2KState *env, int i, target_ulong cond)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
uint64_t ctpr = env->ctprs[i];
|
||||
target_ulong tgt = 0;
|
||||
int ctpr_tag = GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END);
|
||||
|
||||
save_state(env);
|
||||
|
||||
switch (ctpr_tag) {
|
||||
case CTPR_TAG_RETURN:
|
||||
if (cond) {
|
||||
tgt = do_return(env);
|
||||
reset_ctprs(env);
|
||||
}
|
||||
break;
|
||||
case CTPR_TAG_DISP: {
|
||||
/* TODO: ldisp */
|
||||
|
||||
if (env->call_wbs != 0 && cond) {
|
||||
do_call(env, ctpr);
|
||||
reset_ctprs(env);
|
||||
}
|
||||
tgt = GET_FIELD(ctpr, CTPR_BASE_OFF, CTPR_BASE_END);
|
||||
break;
|
||||
}
|
||||
case CTPR_TAG_SDISP: {
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
env->ip = env->nip;
|
||||
cs->exception_index = E2K_EXCP_SYSCALL;
|
||||
if (cond) {
|
||||
if (env->call_wbs != 0) {
|
||||
reset_ctprs(env);
|
||||
cs->exception_index = E2K_EXCP_SYSCALL;
|
||||
cpu_loop_exit(cs);
|
||||
} else {
|
||||
cs->exception_index = E2K_EXCP_UNIMPL;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
cs->exception_index = E2K_EXCP_UNIMPL;
|
||||
cpu_loop_exit(cs);
|
||||
break;
|
||||
}
|
||||
case CTPR_TAG_DISP: {
|
||||
do_call(env, ctpr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* TODO: exception */
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: combine with helper_call? */
|
||||
void helper_jump(CPUE2KState *env, target_ulong cond, target_ulong ctpr)
|
||||
{
|
||||
if (!cond) {
|
||||
env->ip = env->nip;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END)) {
|
||||
case CTPR_TAG_DISP: {
|
||||
env->ip = GET_FIELD(ctpr, CTPR_BASE_OFF, CTPR_BASE_END);
|
||||
break;
|
||||
}
|
||||
case CTPR_TAG_RETURN:
|
||||
do_return(env);
|
||||
break;
|
||||
default:
|
||||
/* TODO: exception */
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void helper_setwd(CPUE2KState *env, uint32_t lts0)
|
||||
{
|
||||
int wsz = GET_FIELD(lts0, 5, 11);
|
||||
/* TODO: store nfx */
|
||||
// int nfx = GET_BIT(lts0, 4);
|
||||
|
||||
/* TODO: push wregs */
|
||||
|
||||
e2k_state_wsz_set(env, wsz);
|
||||
|
||||
if (env->version >= 3) {
|
||||
// int dbl = GET_BIT(lts0, 3);
|
||||
/* TODO: store dbl */
|
||||
}
|
||||
}
|
||||
|
||||
void helper_setbn(CPUE2KState *env, uint32_t cs1)
|
||||
{
|
||||
env->cr1_hi = SET_FIELD(
|
||||
env->cr1_hi,
|
||||
GET_FIELD(cs1, 0, 17),
|
||||
CR1_HI_BR_OFF + BR_BN_OFF,
|
||||
BR_BN_LEN
|
||||
);
|
||||
return tgt;
|
||||
}
|
||||
|
||||
uint64_t helper_sxt(uint64_t x, uint64_t y)
|
||||
@ -240,34 +316,14 @@ void helper_state_reg_set(CPUE2KState *env, int reg, uint64_t val)
|
||||
}
|
||||
}
|
||||
|
||||
void helper_save_rcur(CPUE2KState *env, int rcur)
|
||||
{
|
||||
env->cr1_hi = SET_FIELD(
|
||||
env->cr1_hi,
|
||||
rcur / 2,
|
||||
CR1_HI_BR_OFF + BR_RCUR_OFF,
|
||||
BR_RCUR_LEN
|
||||
);
|
||||
}
|
||||
|
||||
void helper_save_pcur(CPUE2KState *env, int pcur)
|
||||
{
|
||||
env->cr1_hi = SET_FIELD(
|
||||
env->cr1_hi,
|
||||
pcur,
|
||||
CR1_HI_BR_OFF + BR_PCUR_OFF,
|
||||
BR_PCUR_LEN
|
||||
);
|
||||
}
|
||||
|
||||
uint64_t helper_getsp(CPUE2KState *env, uint64_t src2) {
|
||||
uint64_t base = GET_FIELD(env->psp_lo, PSP_LO_BASE_OFF, PSP_LO_BASE_END);
|
||||
uint64_t base = GET_FIELD(env->usd_lo, USD_LO_BASE_OFF, USD_LO_BASE_END);
|
||||
|
||||
base += src2;
|
||||
|
||||
/* TODO: stack overflow */
|
||||
env->psp_lo = SET_FIELD(env->psp_lo, base, PSP_LO_BASE_OFF,
|
||||
PSP_LO_BASE_LEN);
|
||||
env->usd_lo = SET_FIELD(env->usd_lo, base, USD_LO_BASE_OFF,
|
||||
USD_LO_BASE_LEN);
|
||||
|
||||
return base;
|
||||
}
|
||||
|
@ -1,13 +1,9 @@
|
||||
DEF_HELPER_2(raise_exception, noreturn, env, int)
|
||||
DEF_HELPER_3(call, void, env, tl, tl)
|
||||
DEF_HELPER_3(jump, void, env, tl, tl)
|
||||
DEF_HELPER_2(jump, tl, env, int)
|
||||
DEF_HELPER_3(branch, tl, env, int, tl)
|
||||
DEF_HELPER_2(sxt, i64, i64, i64)
|
||||
DEF_HELPER_1(debug_i32, void, i32)
|
||||
DEF_HELPER_1(debug_i64, void, i64)
|
||||
DEF_HELPER_2(setwd, void, env, i32)
|
||||
DEF_HELPER_2(setbn, void, env, i32)
|
||||
DEF_HELPER_2(state_reg_get, i64, env, int)
|
||||
DEF_HELPER_3(state_reg_set, void, env, int, i64)
|
||||
DEF_HELPER_2(save_rcur, void, env, int)
|
||||
DEF_HELPER_2(save_pcur, void, env, int)
|
||||
DEF_HELPER_2(getsp, i64, env, i64) /* FIXME: return tl? */
|
||||
|
@ -189,8 +189,6 @@ static inline void save_state(DisasContext *dc)
|
||||
{
|
||||
tcg_gen_movi_tl(e2k_cs.pc, dc->pc);
|
||||
tcg_gen_movi_tl(e2k_cs.npc, dc->npc);
|
||||
gen_helper_save_rcur(cpu_env, e2k_cs.bcur);
|
||||
gen_helper_save_pcur(cpu_env, e2k_cs.pcur);
|
||||
}
|
||||
|
||||
void e2k_gen_exception(DisasContext *dc, int which)
|
||||
@ -209,7 +207,8 @@ static void e2k_tr_init_disas_context(DisasContextBase *db, CPUState *cs)
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
|
||||
dc->pc = dc->base.pc_first;
|
||||
dc->pc = 0;
|
||||
dc->npc = dc->base.pc_first;
|
||||
dc->version = env->version;
|
||||
}
|
||||
|
||||
@ -233,11 +232,12 @@ static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs)
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
UnpackedBundle *bundle = &dc->bundle;
|
||||
unsigned int bundle_len;
|
||||
|
||||
dc->pc = dc->base.pc_next;
|
||||
unsigned int bundle_len = unpack_bundle(env, dc->pc, bundle);
|
||||
dc->pc = dc->npc;
|
||||
bundle_len = unpack_bundle(env, dc->pc, bundle);
|
||||
/* TODO: exception, check bundle_len */
|
||||
dc->base.pc_next = dc->npc = dc->pc + bundle_len;
|
||||
dc->npc = dc->base.pc_next = dc->pc + bundle_len;
|
||||
|
||||
e2k_alc_gen(dc);
|
||||
e2k_control_gen(dc);
|
||||
@ -261,31 +261,8 @@ static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs)
|
||||
|
||||
static void e2k_tr_tb_start(DisasContextBase *db, CPUState *cs)
|
||||
{
|
||||
DisasContext *dc = container_of(db, DisasContext, base);
|
||||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
uint32_t br;
|
||||
int wbs, wsz, rbs, rsz, rcur, psz, pcur;
|
||||
|
||||
wbs = e2k_state_wbs_get(env);
|
||||
wsz = e2k_state_wsz_get(env);
|
||||
br = GET_FIELD(env->cr1_hi, CR1_HI_BR_OFF, CR1_HI_BR_END);
|
||||
rbs = GET_FIELD(br, BR_RBS_OFF, BR_RBS_END);
|
||||
rsz = GET_FIELD(br, BR_RSZ_OFF, BR_RSZ_END);
|
||||
rcur = GET_FIELD(br, BR_RCUR_OFF, BR_RCUR_END);
|
||||
psz = GET_FIELD(br, BR_PSZ_OFF, BR_PSZ_END);
|
||||
pcur = GET_FIELD(br, BR_PCUR_OFF, BR_PCUR_END);
|
||||
|
||||
e2k_cs.woff = tcg_const_i32(wbs * 2);
|
||||
e2k_cs.wsize = tcg_const_i32(wsz * 2);
|
||||
e2k_cs.boff = tcg_const_i32(rbs * 2);
|
||||
e2k_cs.bsize = tcg_const_i32((rsz + 1) * 2);
|
||||
e2k_cs.bcur = tcg_const_i32(rcur * 2);
|
||||
e2k_cs.psize = tcg_const_i32(psz);
|
||||
e2k_cs.pcur = tcg_const_i32(pcur);
|
||||
|
||||
dc->is_call = false;
|
||||
dc->jmp.cond = tcg_const_i64(0);
|
||||
tcg_gen_movi_tl(e2k_cs.cond, 0);
|
||||
tcg_gen_movi_i32(e2k_cs.call_wbs, 0);
|
||||
}
|
||||
|
||||
static void e2k_tr_tb_stop(DisasContextBase *db, CPUState *cs)
|
||||
@ -298,42 +275,58 @@ static void e2k_tr_tb_stop(DisasContextBase *db, CPUState *cs)
|
||||
case DISAS_TOO_MANY:
|
||||
break;
|
||||
case DISAS_NORETURN: {
|
||||
save_state(dc);
|
||||
/* exception */
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
}
|
||||
case DISAS_STATIC_JUMP:
|
||||
save_state(dc);
|
||||
case DISAS_JUMP_STATIC:
|
||||
tcg_gen_movi_tl(e2k_cs.pc, dc->jmp.dest);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
case DISAS_DYNAMIC_JUMP: {
|
||||
save_state(dc);
|
||||
gen_helper_jump(cpu_env, dc->jmp.cond, e2k_cs.ctprs[dc->jump_ctpr]);
|
||||
case DISAS_BRANCH_STATIC: {
|
||||
TCGv z = tcg_const_tl(0);
|
||||
TCGv t = tcg_const_tl(dc->jmp.dest);
|
||||
TCGv f = tcg_const_tl(dc->npc);
|
||||
|
||||
tcg_gen_movcond_tl(TCG_COND_NE, e2k_cs.pc, e2k_cs.cond, z, t, f);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
|
||||
tcg_temp_free(f);
|
||||
tcg_temp_free(t);
|
||||
tcg_temp_free(z);
|
||||
break;
|
||||
}
|
||||
case DISAS_CALL: {
|
||||
case DISAS_JUMP: {
|
||||
TCGv_i32 ctpr = tcg_const_i32(dc->jump_ctpr);
|
||||
|
||||
save_state(dc);
|
||||
gen_helper_call(cpu_env, dc->jmp.cond, e2k_cs.ctprs[dc->jump_ctpr]);
|
||||
gen_helper_jump(e2k_cs.pc, cpu_env, ctpr);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
|
||||
tcg_temp_free_i32(ctpr);
|
||||
break;
|
||||
}
|
||||
case DISAS_BRANCH: {
|
||||
TCGv_i32 ctpr = tcg_const_i32(dc->jump_ctpr);
|
||||
TCGv z = tcg_const_tl(0);
|
||||
TCGv t = tcg_temp_new();
|
||||
TCGv f = tcg_const_tl(dc->npc);
|
||||
|
||||
save_state(dc);
|
||||
gen_helper_branch(t, cpu_env, ctpr, e2k_cs.cond);
|
||||
tcg_gen_movcond_tl(TCG_COND_NE, e2k_cs.pc, e2k_cs.cond, z, t, f);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
|
||||
tcg_temp_free(f);
|
||||
tcg_temp_free(t);
|
||||
tcg_temp_free(z);
|
||||
tcg_temp_free_i32(ctpr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
|
||||
tcg_temp_free_i32(e2k_cs.woff);
|
||||
tcg_temp_free_i32(e2k_cs.wsize);
|
||||
tcg_temp_free_i32(e2k_cs.boff);
|
||||
tcg_temp_free_i32(e2k_cs.bsize);
|
||||
tcg_temp_free_i32(e2k_cs.bcur);
|
||||
tcg_temp_free_i32(e2k_cs.psize);
|
||||
tcg_temp_free_i32(e2k_cs.pcur);
|
||||
|
||||
tcg_temp_free(dc->jmp.cond);
|
||||
}
|
||||
|
||||
static void e2k_tr_disas_log(const DisasContextBase *db, CPUState *cpu)
|
||||
@ -373,6 +366,13 @@ void e2k_tcg_initialize(void) {
|
||||
|
||||
static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = {
|
||||
{ &e2k_cs.call_wbs, offsetof(CPUE2KState, call_wbs), "call_wbs" },
|
||||
{ &e2k_cs.woff, offsetof(CPUE2KState, woff), "woff" },
|
||||
{ &e2k_cs.wsize, offsetof(CPUE2KState, wsize), "wsize" },
|
||||
{ &e2k_cs.boff, offsetof(CPUE2KState, boff), "boff" },
|
||||
{ &e2k_cs.bsize, offsetof(CPUE2KState, bsize), "bsize" },
|
||||
{ &e2k_cs.bcur, offsetof(CPUE2KState, bcur), "bcur" },
|
||||
{ &e2k_cs.psize, offsetof(CPUE2KState, psize), "psize" },
|
||||
{ &e2k_cs.pcur, offsetof(CPUE2KState, pcur), "pcur" },
|
||||
};
|
||||
|
||||
static const struct { TCGv_i64 *ptr; int off; const char *name; } r64[] = {
|
||||
@ -383,6 +383,7 @@ void e2k_tcg_initialize(void) {
|
||||
static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
|
||||
{ &e2k_cs.pc, offsetof(CPUE2KState, ip), "pc" },
|
||||
{ &e2k_cs.npc, offsetof(CPUE2KState, nip), "npc" },
|
||||
{ &e2k_cs.cond, offsetof(CPUE2KState, cond), "cond" },
|
||||
};
|
||||
|
||||
unsigned int i;
|
||||
|
@ -4,9 +4,20 @@
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "exec/translator.h"
|
||||
|
||||
#define DISAS_STATIC_JUMP DISAS_TARGET_0
|
||||
#define DISAS_DYNAMIC_JUMP DISAS_TARGET_1
|
||||
#define DISAS_CALL DISAS_TARGET_2
|
||||
/* ibranch disp */
|
||||
#define DISAS_JUMP_STATIC DISAS_TARGET_0
|
||||
/* ibranch disp ? cond */
|
||||
#define DISAS_BRANCH_STATIC DISAS_TARGET_1
|
||||
/*
|
||||
* ct %ctprN
|
||||
* call %ctprN, wbs=M
|
||||
* */
|
||||
#define DISAS_JUMP DISAS_TARGET_2
|
||||
/*
|
||||
* ct %ctprN ? cond
|
||||
* call %ctprN, wbs=M ? cond
|
||||
*/
|
||||
#define DISAS_BRANCH DISAS_TARGET_3
|
||||
|
||||
#define IS_BASED(i) (((i) & 0x80) == 0)
|
||||
#define IS_REGULAR(i) (((i) & 0xc0) == 0x80)
|
||||
@ -47,6 +58,7 @@ typedef struct CPUE2KStateTCG {
|
||||
TCGv pc;
|
||||
TCGv npc;
|
||||
TCGv ctprs[4];
|
||||
TCGv cond;
|
||||
TCGv_i64 lsr;
|
||||
TCGv_i32 call_wbs;
|
||||
TCGv_i64 wregs[WREGS_SIZE];
|
||||
@ -110,7 +122,6 @@ typedef struct DisasContext {
|
||||
UnpackedBundle bundle;
|
||||
target_ulong pc;
|
||||
target_ulong npc;
|
||||
bool is_call;
|
||||
int jump_ctpr;
|
||||
int mmuidx;
|
||||
|
||||
@ -130,7 +141,6 @@ typedef struct DisasContext {
|
||||
/* TODO: move to CPUE2KState */
|
||||
struct {
|
||||
target_ulong dest; /* ibranch dst */
|
||||
TCGv_i64 cond;
|
||||
} jmp;
|
||||
} DisasContext;
|
||||
|
||||
|
@ -36,26 +36,20 @@ static inline void gen_lcnt_dec(TCGv_i64 ret, TCGv_i64 lsr)
|
||||
tcg_temp_free_i32(zero);
|
||||
}
|
||||
|
||||
static inline void gen_pcur_inc(TCGv_i32 ret)
|
||||
static inline void gen_dec_cur(TCGv_i32 ret, TCGv_i32 cur, int val,
|
||||
TCGv_i32 size)
|
||||
{
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
TCGv_i32 t2 = tcg_temp_new_i32();
|
||||
|
||||
tcg_gen_subi_i32(t0, e2k_cs.pcur, 1);
|
||||
/* FIXME: terminated by signal SIGFPE (Floating point exception */
|
||||
// tcg_gen_remu_i32(ret, t0, e2k_cs.psize);
|
||||
/* FIXME: temp hack */
|
||||
e2k_gen_wrap_i32(ret, t0, e2k_cs.psize);
|
||||
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
||||
static inline void gen_rcur_inc(TCGv_i32 ret)
|
||||
{
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
|
||||
tcg_gen_subi_i32(t0, e2k_cs.bcur, 2);
|
||||
tcg_gen_remu_i32(ret, t0, e2k_cs.bsize);
|
||||
tcg_gen_addi_i32(t0, size, val);
|
||||
tcg_gen_sub_i32(t1, t0, cur);
|
||||
tcg_gen_remu_i32(t2, t1, size);
|
||||
tcg_gen_sub_i32(ret, size, t2);
|
||||
|
||||
tcg_temp_free_i32(t2);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
||||
@ -130,13 +124,13 @@ void e2k_win_commit(DisasContext *dc)
|
||||
int abn = GET_FIELD(ss, 21, 22);
|
||||
int abg = GET_FIELD(ss, 23, 24);
|
||||
|
||||
tcg_gen_trunc_tl_i32(cond, dc->jmp.cond);
|
||||
tcg_gen_trunc_tl_i32(cond, e2k_cs.cond);
|
||||
|
||||
if (alc) {
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
|
||||
gen_lcnt_dec(t0, e2k_cs.lsr);
|
||||
gen_movcond_flag_i64(e2k_cs.lsr, alc, dc->jmp.cond, t0, e2k_cs.lsr);
|
||||
gen_movcond_flag_i64(e2k_cs.lsr, alc, e2k_cs.cond, t0, e2k_cs.lsr);
|
||||
|
||||
tcg_temp_free_i64(t0);
|
||||
}
|
||||
@ -144,7 +138,7 @@ void e2k_win_commit(DisasContext *dc)
|
||||
if (abp) {
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
|
||||
gen_pcur_inc(t0);
|
||||
gen_dec_cur(t0, e2k_cs.pcur, 1, e2k_cs.psize);
|
||||
gen_movcond_flag_i32(e2k_cs.pcur, abp, cond, t0, e2k_cs.pcur);
|
||||
|
||||
tcg_temp_free_i32(t0);
|
||||
@ -153,7 +147,7 @@ void e2k_win_commit(DisasContext *dc)
|
||||
if (abn) {
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
|
||||
gen_rcur_inc(t0);
|
||||
gen_dec_cur(t0, e2k_cs.bcur, 2, e2k_cs.bsize);
|
||||
gen_movcond_flag_i32(e2k_cs.bcur, abn, cond, t0, e2k_cs.bcur);
|
||||
|
||||
tcg_temp_free_i32(t0);
|
||||
@ -277,7 +271,7 @@ static void gen_cs0(DisasContext *dc)
|
||||
/* Calculate a signed displacement in bytes. */
|
||||
int sdisp = ((int) (disp << 4)) >> 1;
|
||||
dc->jmp.dest = dc->pc + sdisp;
|
||||
dc->base.is_jmp = DISAS_STATIC_JUMP;
|
||||
dc->base.is_jmp = DISAS_JUMP_STATIC;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -405,8 +399,6 @@ static void gen_cs1(DisasContext *dc)
|
||||
int wsz = GET_FIELD(lts0, 5, 11);
|
||||
TCGv_i32 t0 = tcg_const_i32(lts0);
|
||||
|
||||
gen_helper_setwd(cpu_env, t0);
|
||||
|
||||
tcg_gen_movi_i32(e2k_cs.wsize, wsz * 2);
|
||||
|
||||
tcg_temp_free_i32(t0);
|
||||
@ -417,18 +409,10 @@ static void gen_cs1(DisasContext *dc)
|
||||
int rbs = GET_FIELD(cs1, BR_RBS_OFF, BR_RBS_END);
|
||||
int rsz = GET_FIELD(cs1, BR_RSZ_OFF, BR_RSZ_END);
|
||||
int rcur = GET_FIELD(cs1, BR_RCUR_OFF, BR_RCUR_END);
|
||||
TCGv_ptr t0 = tcg_const_ptr(rbs * 2);
|
||||
TCGv_i32 t1 = tcg_const_i32(cs1);
|
||||
|
||||
/* update state*/
|
||||
gen_helper_setbn(cpu_env, t1);
|
||||
|
||||
tcg_gen_movi_i32(e2k_cs.boff, rbs * 2);
|
||||
tcg_gen_movi_i32(e2k_cs.bsize, (rsz + 1) * 2);
|
||||
tcg_gen_movi_i32(e2k_cs.bcur, rcur * 2);
|
||||
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_ptr(t0);
|
||||
}
|
||||
|
||||
if (setbp) {
|
||||
@ -485,7 +469,6 @@ static void gen_cs1(DisasContext *dc)
|
||||
unsigned int wbs = cs1 & 0x7f;
|
||||
|
||||
if (ctop) {
|
||||
dc->is_call = true;
|
||||
tcg_gen_movi_i32(e2k_cs.call_wbs, wbs);
|
||||
// my_printf ("call %%ctpr%d, wbs = 0x%x", ctop, wbs);
|
||||
// print_ctcond (info, instr->ss & 0x1ff);
|
||||
@ -547,19 +530,36 @@ static void gen_jmp(DisasContext *dc)
|
||||
unsigned int cond_type = GET_FIELD(dc->bundle.ss, 5, 8);
|
||||
unsigned int ctpr = GET_FIELD(dc->bundle.ss, 10, 11);
|
||||
|
||||
/* TODO: check CPU behavior if present ibranch and ctpr is not zero */
|
||||
|
||||
/* TODO: different kinds of ct */
|
||||
if (ctpr != 0) {
|
||||
dc->jump_ctpr = ctpr;
|
||||
dc->base.is_jmp = DISAS_JUMP;
|
||||
}
|
||||
|
||||
if (cond_type == 1) {
|
||||
/* TODO: optimize ibranch with no cond */
|
||||
tcg_gen_movi_tl(dc->jmp.cond, 1);
|
||||
} else if (cond_type > 1){
|
||||
tcg_gen_movi_tl(e2k_cs.cond, 1);
|
||||
} else if (cond_type > 1) {
|
||||
switch (dc->base.is_jmp) {
|
||||
case DISAS_JUMP:
|
||||
dc->base.is_jmp = DISAS_BRANCH;
|
||||
break;
|
||||
case DISAS_JUMP_STATIC:
|
||||
dc->base.is_jmp = DISAS_BRANCH_STATIC;
|
||||
break;
|
||||
default:
|
||||
/* FIXME: what action to do? */
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: single assign */
|
||||
TCGv cond = tcg_const_tl(0);
|
||||
TCGv preg = tcg_temp_new();
|
||||
TCGv loop_end = tcg_temp_new();
|
||||
TCGv not_loop_end = tcg_temp_new();
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
|
||||
dc->base.is_jmp = DISAS_DYNAMIC_JUMP;
|
||||
|
||||
e2k_gen_preg(t0, psrc);
|
||||
tcg_gen_trunc_i64_tl(preg, t0);
|
||||
gen_is_loop_end(loop_end);
|
||||
@ -569,12 +569,12 @@ static void gen_jmp(DisasContext *dc)
|
||||
case 0x2:
|
||||
case 0x6:
|
||||
case 0xf:
|
||||
tcg_gen_mov_tl(cond, preg);
|
||||
tcg_gen_mov_tl(e2k_cs.cond, preg);
|
||||
break;
|
||||
case 0x3:
|
||||
case 0x7:
|
||||
case 0xe:
|
||||
tcg_gen_setcondi_tl(TCG_COND_NE, cond, preg, 1);
|
||||
tcg_gen_setcondi_tl(TCG_COND_NE, e2k_cs.cond, preg, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -582,18 +582,18 @@ static void gen_jmp(DisasContext *dc)
|
||||
|
||||
switch (cond_type) {
|
||||
case 0x4:
|
||||
tcg_gen_mov_tl(cond, loop_end);
|
||||
tcg_gen_mov_tl(e2k_cs.cond, loop_end);
|
||||
break;
|
||||
case 0x5:
|
||||
tcg_gen_mov_tl(cond, not_loop_end);
|
||||
tcg_gen_mov_tl(e2k_cs.cond, not_loop_end);
|
||||
break;
|
||||
case 0x6:
|
||||
case 0xe:
|
||||
tcg_gen_or_tl(cond, cond, loop_end);
|
||||
tcg_gen_or_tl(e2k_cs.cond, e2k_cs.cond, loop_end);
|
||||
break;
|
||||
case 0x7:
|
||||
case 0xf:
|
||||
tcg_gen_and_tl(cond, cond, not_loop_end);
|
||||
tcg_gen_and_tl(e2k_cs.cond, e2k_cs.cond, not_loop_end);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -648,26 +648,11 @@ static void gen_jmp(DisasContext *dc)
|
||||
abort();
|
||||
}
|
||||
|
||||
tcg_gen_mov_tl(dc->jmp.cond, cond);
|
||||
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free(not_loop_end);
|
||||
tcg_temp_free(loop_end);
|
||||
tcg_temp_free(preg);
|
||||
tcg_temp_free(cond);
|
||||
}
|
||||
|
||||
/* TODO: check CPU behavior if present ibranch and ctpr is not zero */
|
||||
|
||||
/* TODO: different kinds of ct */
|
||||
if (ctpr != 0) {
|
||||
dc->jump_ctpr = ctpr;
|
||||
|
||||
if (dc->is_call) {
|
||||
dc->base.is_jmp = DISAS_CALL;
|
||||
} else {
|
||||
dc->base.is_jmp = DISAS_DYNAMIC_JUMP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user