target: e2k: Add basic call (without saving regs).
This commit is contained in:
parent
aca6a33344
commit
d495f0ffb3
|
@ -39,7 +39,8 @@ void cpu_loop(CPUE2KState *env)
|
|||
switch (trapnr) {
|
||||
case E2K_EXCP_SYSCALL: {
|
||||
/* TODO: wrap register indices */
|
||||
int offset = (env->wbs + env->syscall_wbs) * 2;
|
||||
int wbs = e2k_state_wbs_get(env);
|
||||
int offset = (wbs + env->call_wbs) * 2;
|
||||
uint64_t *regs = &env->wregs[offset];
|
||||
abi_ulong ret = do_syscall(env, regs[0],
|
||||
regs[1], regs[2], regs[3], regs[4],
|
||||
|
@ -68,6 +69,10 @@ void cpu_loop(CPUE2KState *env)
|
|||
void target_cpu_copy_regs(CPUE2KState *env, struct target_pt_regs *regs)
|
||||
{
|
||||
env->ip = regs->ip;
|
||||
env->usd_hi = regs->usd_hi;
|
||||
env->pcsp_lo = regs->pcsp_lo;
|
||||
env->pcsp_hi = regs->pcsp_hi;
|
||||
env->psp_lo = regs->psp_lo;
|
||||
env->psp_hi = regs->psp_hi;
|
||||
env->usd_lo = regs->usd_lo;
|
||||
env->usd_hi = regs->usd_hi;
|
||||
}
|
||||
|
|
|
@ -1495,19 +1495,54 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
|
|||
typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
|
||||
#define USE_ELF_CORE_DUMP
|
||||
|
||||
static inline abi_ulong e2k_mmap(abi_ulong size)
|
||||
{
|
||||
abi_ulong addr;
|
||||
abi_ulong guard = TARGET_PAGE_SIZE;
|
||||
|
||||
if (size < TARGET_PAGE_SIZE) {
|
||||
size = TARGET_PAGE_SIZE;
|
||||
}
|
||||
if (guard < qemu_real_host_page_size) {
|
||||
guard = qemu_real_host_page_size;
|
||||
}
|
||||
|
||||
addr = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (addr == -1) {
|
||||
perror("mmap e2k stack");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
target_mprotect(addr + size, guard, PROT_NONE);
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
|
||||
{
|
||||
uint64_t size = infop->start_stack - infop->stack_limit;
|
||||
abi_ulong pcsp;
|
||||
abi_ulong pcs_size = TARGET_PAGE_SIZE;
|
||||
abi_ulong psp;
|
||||
abi_ulong ps_size = TARGET_PAGE_SIZE * 8;
|
||||
abi_ulong stack_size = infop->start_stack - infop->stack_limit;
|
||||
|
||||
regs->ip = infop->entry;
|
||||
regs->usd_hi = size << 32;
|
||||
regs->usd_hi = stack_size << 32;
|
||||
regs->usd_lo = (0x1800UL << 48) | infop->start_stack;
|
||||
// TODO
|
||||
qemu_log_mask(LOG_UNIMP, "init_thread: not implemented\n");
|
||||
|
||||
/* FIXME: mmap to 0xc2e000003000 */
|
||||
pcsp = e2k_mmap(pcs_size);
|
||||
regs->pcsp_lo = (3UL << 59) | pcsp;
|
||||
regs->pcsp_hi = pcs_size << 32;
|
||||
|
||||
psp = e2k_mmap(ps_size);
|
||||
regs->psp_lo = (3UL << 59) | psp;
|
||||
regs->psp_hi = ps_size << 32;
|
||||
}
|
||||
|
||||
static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUE2KState *env)
|
||||
{
|
||||
// TODO
|
||||
/* TODO */
|
||||
qemu_log_mask(LOG_UNIMP, "elf_core_copy_regs: not implemented\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ static void e2k_cpu_reset(DeviceState *dev)
|
|||
|
||||
memset(env, 0, offsetof(CPUE2KState, end_reset_fields));
|
||||
|
||||
env->win_ptr = env->wregs;
|
||||
env->wptr = &env->wregs[0];
|
||||
}
|
||||
|
||||
static bool e2k_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
|
@ -93,12 +93,16 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
|||
unsigned int i;
|
||||
|
||||
qemu_fprintf(f, "ip: " TARGET_FMT_lx "\n", env->ip);
|
||||
qemu_fprintf(f, "pregs: %016lx\n", env->pf);
|
||||
qemu_fprintf(f, "usd_hi: %016lx, usd_lo: %016lx\n",
|
||||
env->usd_hi, env->usd_lo);
|
||||
qemu_fprintf(f, "pcsp_hi: %016lx, pcsp_lo: %016lx\n",
|
||||
env->pcsp_hi, env->pcsp_lo);
|
||||
qemu_fprintf(f, "psp_hi: %016lx, psp_lo: %016lx\n",
|
||||
env->psp_hi, env->psp_lo);
|
||||
qemu_fprintf(f, "PF: %016lx\n", env->pf);
|
||||
qemu_fprintf(f, "cr1_hi: %016lx, cr1_lo: %016lx\n",
|
||||
env->cr1_hi, env->cr1_lo);
|
||||
qemu_fprintf(f, "wbs: %d, wsz: %d\n", (int) env->wbs, (int) env->wsz);
|
||||
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_br(env, f, flags);
|
||||
qemu_fprintf(f, "lsr: %016lx\n", env->lsr);
|
||||
|
||||
|
|
|
@ -8,16 +8,28 @@
|
|||
void e2k_tcg_initialize(void);
|
||||
|
||||
#define GEN_MASK(start, end) \
|
||||
(((1UL << ((end) - (start) + 1)) - 1) << start)
|
||||
GEN_MASK_LEN((start), (end) - (start) + 1)
|
||||
#define GEN_MASK_LEN(start, len) \
|
||||
(((1UL << (len)) - 1) << (start))
|
||||
#define GET_BIT(v, index) (((v) >> (index)) & 1)
|
||||
#define GET_FIELD(v, start, end) \
|
||||
(((v) >> (start)) & ((1UL << ((end) - (start) + 1)) - 1))
|
||||
#define SET_FIELD(v, f, s, l) \
|
||||
( \
|
||||
((v) & ~GEN_MASK_LEN((s), (l))) | \
|
||||
((((typeof(v)) (f)) << (s)) & GEN_MASK_LEN((s), (l))) \
|
||||
)
|
||||
|
||||
#define MMU_USER_IDX 1
|
||||
#define CPU_RESOLVING_TYPE TYPE_E2K_CPU
|
||||
|
||||
#define REG_SIZE (sizeof(uint64_t))
|
||||
#define WREGS_SIZE 192
|
||||
// size of regular reg in bytes
|
||||
#define REG_SIZE (sizeof(target_ulong))
|
||||
#define GREGS_SIZE 32
|
||||
#define WREGS_MAX 64
|
||||
#define BREGS_MAX 128
|
||||
#define GREGS_MAX 24
|
||||
#define BGREGS_MAX 8
|
||||
|
||||
#define CTPR_BASE_OFF 0
|
||||
#define CTPR_BASE_END 47
|
||||
|
@ -43,6 +55,21 @@ void e2k_tcg_initialize(void);
|
|||
#define PCSP_LO_WRITE_OFF 60
|
||||
#define PCSP_LO_WRITE_BIT (1UL << PCSP_LO_WRITE_OFF)
|
||||
|
||||
#define PSP_HI_IND_OFF 0 /* index for SPILL */
|
||||
#define PSP_HI_IND_END 31
|
||||
#define PSP_HI_IND_LEN (PSP_HI_IND_END - PSP_HI_IND_OFF + 1)
|
||||
#define PSP_HI_SIZE_OFF 32
|
||||
#define PSP_HI_SIZE_END 63 /* procedure stack size */
|
||||
#define PSP_HI_SIZE_LEN (PSP_HI_SIZE_END - PSP_HI_SIZE_OFF + 1)
|
||||
|
||||
#define PSP_LO_BASE_OFF 0 /* procedure stack address */
|
||||
#define PSP_LO_BASE_END 47
|
||||
#define PSP_LO_BASE_LEN (PSP_LO_BASE_END - PSP_LO_BASE_OFF + 1)
|
||||
#define PSP_LO_READ_OFF 59
|
||||
#define PSP_LO_READ_BIT (1UL << PSP_LO_READ_OFF)
|
||||
#define PSP_LO_WRITE_OFF 60
|
||||
#define PSP_LO_WRITE_BIT (1UL << PSP_LO_WRITE_OFF)
|
||||
|
||||
#define CR1_HI_BR_OFF 0
|
||||
#define CR1_HI_BR_END 27
|
||||
#define CR1_HI_BR_LEN (CR1_HI_BR_END - CR1_HI_BR_OFF + 1)
|
||||
|
@ -128,38 +155,38 @@ struct e2k_def_t {
|
|||
};
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* register file */
|
||||
target_ulong gregs[32]; // global regs
|
||||
target_ulong wregs[WREGS_SIZE]; // window regs
|
||||
target_ulong *win_ptr;
|
||||
uint64_t gregs[GREGS_SIZE]; /* global registers */
|
||||
uint64_t wregs[WREGS_SIZE]; /* window registers */
|
||||
uint64_t *wptr;
|
||||
uint64_t pf; /* predicate file */
|
||||
|
||||
uint32_t wbs; // window regs offset
|
||||
uint32_t wsz; // window regs size
|
||||
uint32_t nfx; // TODO
|
||||
uint32_t dbl; // TODO
|
||||
|
||||
uint64_t pcsp_hi;
|
||||
/* Procedure chain info = cr0_lo, cr0_hi, cr1_lo, cr1_hi */
|
||||
uint64_t pcsp_lo;
|
||||
uint64_t pcsp_hi;
|
||||
|
||||
/* cr0_hi == ip */
|
||||
/* cr0_lo == pf */
|
||||
uint64_t cr1_hi;
|
||||
/* cr0_hi == ip */
|
||||
uint64_t cr1_lo;
|
||||
uint64_t cr1_hi;
|
||||
|
||||
/* Procedure stack pointer (for regs) */
|
||||
uint64_t psp_lo;
|
||||
uint64_t psp_hi;
|
||||
|
||||
uint64_t lsr; /* loop status register */
|
||||
|
||||
uint32_t syscall_wbs;
|
||||
|
||||
uint32_t call_wbs;
|
||||
|
||||
uint64_t usd_lo;
|
||||
uint64_t usd_hi;
|
||||
|
||||
/* control registers */
|
||||
target_ulong ctprs[3]; // Control Transfer Preparation Register (CTPR)
|
||||
target_ulong ctprs[4]; // Control Transfer Preparation Register (CTPR)
|
||||
|
||||
/* special registers */
|
||||
target_ulong ip; /* instruction address, next instruction address */
|
||||
target_ulong ip; /* instruction address */
|
||||
target_ulong nip; /* next instruction address */
|
||||
|
||||
uint32_t pfpfr; // Packed Floating Point Flag Register (PFPFR)
|
||||
uint32_t fpcr; // Floating point control register (FPCR)
|
||||
|
@ -202,6 +229,28 @@ int e2k_cpu_signal_handler(int host_signum, void *pinfo, void *puc);
|
|||
|
||||
#define cpu_signal_handler e2k_cpu_signal_handler
|
||||
|
||||
static inline int e2k_state_wbs_get(CPUE2KState *env)
|
||||
{
|
||||
return GET_FIELD(env->cr1_lo, CR1_LO_WBS_OFF, CR1_LO_WBS_END);
|
||||
}
|
||||
|
||||
static inline void e2k_state_wbs_set(CPUE2KState *env, int wbs)
|
||||
{
|
||||
env->cr1_lo = SET_FIELD(env->cr1_lo, wbs,
|
||||
CR1_LO_WBS_OFF, CR1_LO_WBS_LEN);
|
||||
}
|
||||
|
||||
static inline int e2k_state_wsz_get(CPUE2KState *env)
|
||||
{
|
||||
return GET_FIELD(env->cr1_lo, CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_END);
|
||||
}
|
||||
|
||||
static inline void e2k_state_wsz_set(CPUE2KState *env, int wsz)
|
||||
{
|
||||
env->cr1_lo = SET_FIELD(env->cr1_lo, wsz,
|
||||
CR1_LO_WPSZ_OFF, CR1_LO_WPSZ_LEN);
|
||||
}
|
||||
|
||||
typedef CPUE2KState CPUArchState;
|
||||
typedef E2KCPU ArchCPU;
|
||||
|
||||
|
|
|
@ -14,21 +14,132 @@ void helper_raise_exception(CPUE2KState *env, int tt)
|
|||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
void helper_call(CPUE2KState *env, target_ulong ctpr, target_ulong cond)
|
||||
static inline void do_call(CPUE2KState *env, target_ulong ctpr)
|
||||
{
|
||||
int tag = GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END);
|
||||
unsigned int offset, wbs, wsz, new_wbs, new_wsz;
|
||||
uint64_t *pcsp = (uint64_t *)
|
||||
GET_FIELD(env->pcsp_lo, PCSP_LO_BASE_OFF, PCSP_LO_BASE_END);
|
||||
|
||||
wbs = e2k_state_wbs_get(env);
|
||||
wsz = e2k_state_wsz_get(env);
|
||||
new_wbs = (wbs + env->call_wbs) % WREGS_SIZE;
|
||||
new_wsz = wsz - env->call_wbs;
|
||||
|
||||
/* save procedure chain */
|
||||
offset = (env->pcsp_hi & GEN_MASK(0, 31)) / 8;
|
||||
pcsp[offset + 0] = env->pf;
|
||||
pcsp[offset + 1] = env->nip;
|
||||
pcsp[offset + 2] = env->cr1_lo;
|
||||
pcsp[offset + 3] = env->cr1_hi;
|
||||
/* TODO: check stack overflow */
|
||||
env->pcsp_hi = env->pcsp_hi + 32;
|
||||
|
||||
/* TODO: check if call_wbs is less or equal then wsz */
|
||||
e2k_state_wbs_set(env, new_wbs);
|
||||
e2k_state_wsz_set(env, new_wsz);
|
||||
/* TODO: check rbs/rsz after call */
|
||||
env->ip = GET_FIELD(ctpr, CTPR_BASE_OFF, CTPR_BASE_END);
|
||||
}
|
||||
|
||||
static void do_return(CPUE2KState *env)
|
||||
{
|
||||
unsigned int offset = env->pcsp_hi & GEN_MASK(0, 31);
|
||||
uint64_t *pcsp = (uint64_t *) (GET_FIELD(env->pcsp_lo, PCSP_LO_BASE_OFF,
|
||||
PCSP_LO_BASE_END) + offset - 32);
|
||||
// uint64_t *psp = (uint64_t *) GET_FIELD(env->psp_lo, PSP_LO_BASE_OFF,
|
||||
// PSP_LO_BASE_END);
|
||||
|
||||
env->pf = pcsp[0];
|
||||
env->ip = pcsp[1];
|
||||
env->nip = env->ip + 8;
|
||||
env->cr1_lo = pcsp[2];
|
||||
env->cr1_hi = pcsp[3];
|
||||
/* TODO: check stack overflow */
|
||||
env->pcsp_hi = env->pcsp_hi - 32;
|
||||
|
||||
// TODO: restore regs
|
||||
}
|
||||
|
||||
void helper_call(CPUE2KState *env, target_ulong cond, target_ulong ctpr)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
if (!cond) {
|
||||
env->ip = env->nip;
|
||||
return;
|
||||
}
|
||||
if (tag == CTPR_TAG_SDISP) {
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
env->ctprs[i] = 0;
|
||||
}
|
||||
|
||||
switch (GET_FIELD(ctpr, CTPR_TAG_OFF, CTPR_TAG_END)) {
|
||||
case CTPR_TAG_SDISP: {
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
env->ip = env->nip;
|
||||
cs->exception_index = E2K_EXCP_SYSCALL;
|
||||
cpu_loop_exit(cs);
|
||||
} else {
|
||||
/* TODO: call */
|
||||
abort();
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
uint64_t helper_sxt(uint64_t x, uint64_t y)
|
||||
|
@ -63,3 +174,63 @@ void helper_debug_i64(uint64_t x)
|
|||
{
|
||||
qemu_log_mask(LOG_UNIMP, "log %#lx\n", x);
|
||||
}
|
||||
|
||||
uint64_t helper_state_reg_get(CPUE2KState *env, int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0x2c: /* %usd.hi */
|
||||
return env->usd_hi;
|
||||
break;
|
||||
case 0x2d: /* %usd.lo */
|
||||
return env->usd_lo;
|
||||
break;
|
||||
case 0x83: /* %lsr */
|
||||
return env->lsr;
|
||||
break;
|
||||
default:
|
||||
/* TODO: exception */
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void helper_state_reg_set(CPUE2KState *env, int reg, uint64_t val)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0x2c: /* %usd.hi */
|
||||
/* FIXME: user cannot write */
|
||||
env->usd_hi = val;
|
||||
break;
|
||||
case 0x2d: /* %usd.lo */
|
||||
/* FIXME: user cannot write */
|
||||
env->usd_lo = val;
|
||||
break;
|
||||
case 0x83: /* %lsr */
|
||||
env->lsr = val;
|
||||
break;
|
||||
default:
|
||||
/* TODO: exception */
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
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(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)
|
||||
|
|
|
@ -188,7 +188,9 @@ static target_ulong unpack_bundle(CPUE2KState *env,
|
|||
static inline void save_state(DisasContext *dc)
|
||||
{
|
||||
tcg_gen_movi_tl(e2k_cs.pc, dc->pc);
|
||||
// tcg_gen_movi_tl(e2k_cs.pc, dc->npc);
|
||||
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)
|
||||
|
@ -231,6 +233,7 @@ static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs)
|
|||
E2KCPU *cpu = E2K_CPU(cs);
|
||||
CPUE2KState *env = &cpu->env;
|
||||
UnpackedBundle *bundle = &dc->bundle;
|
||||
|
||||
dc->pc = dc->base.pc_next;
|
||||
unsigned int bundle_len = unpack_bundle(env, dc->pc, bundle);
|
||||
/* TODO: exception, check bundle_len */
|
||||
|
@ -259,9 +262,29 @@ 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.dest = tcg_const_i64(0);
|
||||
dc->jmp.cond = tcg_const_i64(0);
|
||||
}
|
||||
|
||||
|
@ -274,31 +297,26 @@ static void e2k_tr_tb_stop(DisasContextBase *db, CPUState *cs)
|
|||
case DISAS_NEXT:
|
||||
case DISAS_TOO_MANY:
|
||||
break;
|
||||
case DISAS_CALL: {
|
||||
tcg_gen_movi_tl(e2k_cs.pc, dc->pc);
|
||||
tcg_gen_movi_tl(e2k_cs.pc, dc->npc);
|
||||
gen_helper_call(cpu_env, e2k_cs.ctprs[dc->call_ctpr], dc->jmp.cond);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
}
|
||||
case DISAS_NORETURN: {
|
||||
save_state(dc);
|
||||
/* exception */
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
}
|
||||
case STATIC_JUMP:
|
||||
tcg_gen_mov_tl(e2k_cs.pc, dc->jmp.dest);
|
||||
case DISAS_STATIC_JUMP:
|
||||
save_state(dc);
|
||||
tcg_gen_movi_tl(e2k_cs.pc, dc->jmp.dest);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
case DYNAMIC_JUMP: {
|
||||
TCGv_i64 one = tcg_const_tl(1);
|
||||
TCGv_i64 npc = tcg_const_tl(dc->npc);
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, e2k_cs.pc,
|
||||
dc->jmp.cond, one,
|
||||
dc->jmp.dest, npc
|
||||
);
|
||||
tcg_temp_free(npc);
|
||||
tcg_temp_free(one);
|
||||
case DISAS_DYNAMIC_JUMP: {
|
||||
save_state(dc);
|
||||
gen_helper_jump(cpu_env, dc->jmp.cond, e2k_cs.ctprs[dc->jump_ctpr]);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
}
|
||||
case DISAS_CALL: {
|
||||
save_state(dc);
|
||||
gen_helper_call(cpu_env, dc->jmp.cond, e2k_cs.ctprs[dc->jump_ctpr]);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
break;
|
||||
}
|
||||
|
@ -307,7 +325,14 @@ static void e2k_tr_tb_stop(DisasContextBase *db, CPUState *cs)
|
|||
break;
|
||||
}
|
||||
|
||||
tcg_temp_free(dc->jmp.dest);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -344,29 +369,20 @@ void restore_state_to_opc(CPUE2KState *env, TranslationBlock *tb,
|
|||
}
|
||||
|
||||
void e2k_tcg_initialize(void) {
|
||||
char buf[8] = { 0 };
|
||||
char buf[16] = { 0 };
|
||||
|
||||
static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = {
|
||||
{ &e2k_cs.wbs, offsetof(CPUE2KState, wbs), "wbs" },
|
||||
{ &e2k_cs.wsz, offsetof(CPUE2KState, wsz), "wsz" },
|
||||
{ &e2k_cs.nfx, offsetof(CPUE2KState, nfx), "nfx" },
|
||||
{ &e2k_cs.dbl, offsetof(CPUE2KState, dbl), "dbl" },
|
||||
{ &e2k_cs.syscall_wbs, offsetof(CPUE2KState, syscall_wbs), "syscall_wbs" },
|
||||
{ &e2k_cs.call_wbs, offsetof(CPUE2KState, call_wbs), "call_wbs" },
|
||||
};
|
||||
|
||||
static const struct { TCGv_i64 *ptr; int off; const char *name; } r64[] = {
|
||||
{ &e2k_cs.pregs, offsetof(CPUE2KState, pf), "pregs" },
|
||||
{ &e2k_cs.pcsp_hi, offsetof(CPUE2KState, pcsp_hi), "pcsp_hi" },
|
||||
{ &e2k_cs.pcsp_lo, offsetof(CPUE2KState, pcsp_lo), "pcsp_lo" },
|
||||
{ &e2k_cs.cr1_hi, offsetof(CPUE2KState, cr1_hi), "cr1_hi" },
|
||||
{ &e2k_cs.cr1_lo, offsetof(CPUE2KState, cr1_lo), "cr1_lo" },
|
||||
{ &e2k_cs.usd_hi, offsetof(CPUE2KState, usd_hi), "usd.hi" },
|
||||
{ &e2k_cs.usd_lo, offsetof(CPUE2KState, usd_lo), "usd.lo" },
|
||||
{ &e2k_cs.lsr, offsetof(CPUE2KState, lsr), "lsr" },
|
||||
};
|
||||
|
||||
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" },
|
||||
};
|
||||
|
||||
unsigned int i;
|
||||
|
@ -383,27 +399,24 @@ void e2k_tcg_initialize(void) {
|
|||
*rtl[i].ptr = tcg_global_mem_new(cpu_env, rtl[i].off, rtl[i].name);
|
||||
}
|
||||
|
||||
e2k_cs.win_ptr = tcg_global_mem_new_ptr(cpu_env, offsetof(CPUE2KState, win_ptr), "win_ptr");
|
||||
e2k_cs.wptr = tcg_global_mem_new_ptr(cpu_env,
|
||||
offsetof(CPUE2KState, wptr), "wptr");
|
||||
|
||||
for (i = 0; i < WREGS_SIZE; i++) {
|
||||
snprintf(buf, ARRAY_SIZE(buf), "%%r%d", i);
|
||||
e2k_cs.wregs[i] = tcg_global_mem_new(e2k_cs.win_ptr,
|
||||
i * REG_SIZE,
|
||||
buf);
|
||||
e2k_cs.wregs[i] = tcg_global_mem_new_i64(e2k_cs.wptr,
|
||||
i * REG_SIZE, buf);
|
||||
}
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
for (i = 0; i < GREGS_SIZE; i++) {
|
||||
snprintf(buf, ARRAY_SIZE(buf), "%%g%d", i);
|
||||
e2k_cs.gregs[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUE2KState, gregs[i]),
|
||||
buf);
|
||||
e2k_cs.gregs[i] = tcg_global_mem_new_i64(cpu_env,
|
||||
offsetof(CPUE2KState, gregs[i]), buf);
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
snprintf(buf, ARRAY_SIZE(buf), "%%ctpr%d", i + 1);
|
||||
e2k_cs.ctprs[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUE2KState, ctprs[i]),
|
||||
buf
|
||||
);
|
||||
offsetof(CPUE2KState, ctprs[i]), buf);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#include "tcg/tcg-op.h"
|
||||
#include "exec/translator.h"
|
||||
|
||||
#define STATIC_JUMP DISAS_TARGET_0
|
||||
#define DYNAMIC_JUMP DISAS_TARGET_1
|
||||
#define DISAS_STATIC_JUMP DISAS_TARGET_0
|
||||
#define DISAS_DYNAMIC_JUMP DISAS_TARGET_1
|
||||
#define DISAS_CALL DISAS_TARGET_2
|
||||
|
||||
#define IS_BASED(i) (((i) & 0x80) == 0)
|
||||
|
@ -45,23 +45,21 @@ typedef enum {
|
|||
|
||||
typedef struct CPUE2KStateTCG {
|
||||
TCGv pc;
|
||||
TCGv ctprs[3];
|
||||
TCGv_i32 wbs;
|
||||
TCGv_i32 wsz;
|
||||
TCGv_i32 nfx;
|
||||
TCGv_i32 dbl;
|
||||
TCGv_i64 pcsp_hi;
|
||||
TCGv_i64 pcsp_lo;
|
||||
TCGv_i64 cr1_hi;
|
||||
TCGv_i64 cr1_lo;
|
||||
TCGv npc;
|
||||
TCGv ctprs[4];
|
||||
TCGv_i64 lsr;
|
||||
TCGv_i32 syscall_wbs;
|
||||
TCGv_ptr win_ptr;
|
||||
TCGv_i32 call_wbs;
|
||||
TCGv_i64 wregs[WREGS_SIZE];
|
||||
TCGv_i64 gregs[32];
|
||||
TCGv_i64 gregs[GREGS_SIZE];
|
||||
TCGv_ptr wptr; /* pointer to wregs */
|
||||
TCGv_i32 woff; /* holds wbs * 2 */
|
||||
TCGv_i32 wsize; /* holds wsz * 2 */
|
||||
TCGv_i32 boff; /* holds rbs * 2 */
|
||||
TCGv_i32 bsize; /* holds rsz * 2 + 2 */
|
||||
TCGv_i32 bcur; /* holds rcur * 2 */
|
||||
TCGv_i64 pregs;
|
||||
TCGv_i64 usd_lo;
|
||||
TCGv_i64 usd_hi;
|
||||
TCGv_i32 psize; /* holds psz */
|
||||
TCGv_i32 pcur; /* holds pcur */
|
||||
} CPUE2KStateTCG;
|
||||
|
||||
extern struct CPUE2KStateTCG e2k_cs;
|
||||
|
@ -113,7 +111,7 @@ typedef struct DisasContext {
|
|||
target_ulong pc;
|
||||
target_ulong npc;
|
||||
bool is_call;
|
||||
int call_ctpr;
|
||||
int jump_ctpr;
|
||||
int mmuidx;
|
||||
|
||||
int version;
|
||||
|
@ -131,7 +129,7 @@ typedef struct DisasContext {
|
|||
Result alc[6];
|
||||
/* TODO: move to CPUE2KState */
|
||||
struct {
|
||||
TCGv dest;
|
||||
target_ulong dest; /* ibranch dst */
|
||||
TCGv_i64 cond;
|
||||
} jmp;
|
||||
} DisasContext;
|
||||
|
@ -216,29 +214,6 @@ static inline void e2k_gen_set_field_i64(TCGv_i64 ret, TCGv_i64 val,
|
|||
tcg_temp_free_i64(t0);
|
||||
}
|
||||
|
||||
static inline void e2k_gen_get_br(TCGv_i32 ret)
|
||||
{
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_extract_i64(t0, e2k_cs.cr1_hi, CR1_HI_BR_OFF, CR1_HI_BR_LEN);
|
||||
tcg_gen_extrl_i64_i32(ret, t0);
|
||||
|
||||
tcg_temp_free_i64(t0);
|
||||
}
|
||||
|
||||
static inline void e2k_gen_set_br(TCGv_i32 val)
|
||||
{
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
|
||||
tcg_gen_extu_i32_i64(t0, val);
|
||||
tcg_gen_deposit_i64(t1, e2k_cs.cr1_hi, t0, CR1_HI_BR_OFF, CR1_HI_BR_LEN);
|
||||
tcg_gen_mov_i64(e2k_cs.cr1_hi, t1);
|
||||
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t0);
|
||||
}
|
||||
|
||||
static inline void e2k_gen_lcnt(TCGv_i64 ret)
|
||||
{
|
||||
tcg_gen_andi_i64(ret, e2k_cs.lsr, (1UL << 32) - 1);
|
||||
|
|
|
@ -259,21 +259,11 @@ static inline void gen_mrgc_i32(DisasContext *dc, int chan, TCGv_i32 ret)
|
|||
|
||||
static inline void gen_rr_i64(TCGv_i64 ret, uint8_t state_reg)
|
||||
{
|
||||
switch (state_reg) {
|
||||
case 0x2c: /* %usd.hi */
|
||||
tcg_gen_mov_i64(ret, e2k_cs.usd_hi);
|
||||
break;
|
||||
case 0x2d: /* %usd.lo */
|
||||
tcg_gen_mov_i64(ret, e2k_cs.usd_lo);
|
||||
break;
|
||||
case 0x83: /* %lsr */
|
||||
tcg_gen_mov_i64(ret, e2k_cs.lsr);
|
||||
break;
|
||||
default:
|
||||
/* TODO: exception */
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
TCGv_i32 t0 = tcg_const_i32(state_reg);
|
||||
|
||||
gen_helper_state_reg_get(ret, cpu_env, t0);
|
||||
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
||||
static inline void gen_rrd(DisasContext *dc, int chan)
|
||||
|
@ -302,23 +292,11 @@ static inline void gen_rrs(DisasContext *dc, int chan)
|
|||
|
||||
static inline void gen_rw_i64(uint8_t state_reg, TCGv_i64 val)
|
||||
{
|
||||
switch (state_reg) {
|
||||
case 0x2c: /* %usd.hi */
|
||||
/* FIXME: user cannot write */
|
||||
tcg_gen_mov_i64(e2k_cs.usd_hi, val);
|
||||
break;
|
||||
case 0x2d: /* %usd.lo */
|
||||
/* FIXME: user cannot write */
|
||||
tcg_gen_mov_i64(e2k_cs.usd_lo, val);
|
||||
break;
|
||||
case 0x83: /* %lsr */
|
||||
tcg_gen_mov_i64(e2k_cs.lsr, val);
|
||||
break;
|
||||
default:
|
||||
/* TODO: exception */
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
TCGv_i32 t0 = tcg_const_i32(state_reg);
|
||||
|
||||
gen_helper_state_reg_set(cpu_env, t0, val);
|
||||
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
||||
static inline void gen_rwd(DisasContext *dc, int chan)
|
||||
|
@ -345,18 +323,20 @@ static inline void gen_rws(DisasContext *dc, int chan)
|
|||
|
||||
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();
|
||||
// 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();
|
||||
|
||||
abort();
|
||||
|
||||
/* 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_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);
|
||||
// tcg_temp_free_i64(t1);
|
||||
// tcg_temp_free_i64(t0);
|
||||
}
|
||||
|
||||
/* FIXME: movtd: don't know what it does */
|
||||
|
@ -532,6 +512,7 @@ static void gen_alopf_simple(DisasContext *dc, int chan)
|
|||
res.tag = RESULT_PREG;
|
||||
res.u.reg.i = als & 0x1f;
|
||||
res.u.reg.v = tmp_dst;
|
||||
|
||||
dc->alc[chan] = res;
|
||||
|
||||
break;
|
||||
|
|
|
@ -36,47 +36,31 @@ 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, TCGv_i32 br)
|
||||
static inline void gen_pcur_inc(TCGv_i32 ret)
|
||||
{
|
||||
TCGv_i32 pcur = tcg_temp_new_i32();
|
||||
TCGv_i32 psz = tcg_temp_new_i32();
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
|
||||
tcg_gen_extract_i32(pcur, br, BR_PCUR_OFF, BR_PCUR_LEN);
|
||||
tcg_gen_extract_i32(psz, br, BR_PSZ_OFF, BR_PSZ_LEN);
|
||||
tcg_gen_subi_i32(t0, pcur, 1);
|
||||
tcg_gen_umin_i32(t1, t0, psz);
|
||||
tcg_gen_deposit_i32(ret, br, t1, BR_PCUR_OFF, BR_PCUR_LEN);
|
||||
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(t1);
|
||||
tcg_temp_free_i32(t0);
|
||||
tcg_temp_free_i32(psz);
|
||||
tcg_temp_free_i32(pcur);
|
||||
}
|
||||
|
||||
static inline void gen_rcur_inc(TCGv_i32 ret, TCGv_i32 br)
|
||||
static inline void gen_rcur_inc(TCGv_i32 ret)
|
||||
{
|
||||
TCGv_i32 rcur = tcg_temp_new_i32();
|
||||
TCGv_i32 rsz = tcg_temp_new_i32();
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
TCGv_i32 t2 = tcg_temp_new_i32();
|
||||
|
||||
tcg_gen_extract_i32(rcur, br, BR_RCUR_OFF, BR_RCUR_LEN);
|
||||
tcg_gen_extract_i32(rsz, br, BR_RSZ_OFF, BR_RSZ_LEN);
|
||||
tcg_gen_subi_i32(t0, rcur, 1);
|
||||
tcg_gen_umin_i32(t2, t0, rsz);
|
||||
tcg_gen_deposit_i32(ret, br, t2, BR_RCUR_OFF, BR_RCUR_LEN);
|
||||
tcg_gen_subi_i32(t0, e2k_cs.bcur, 2);
|
||||
tcg_gen_remu_i32(ret, t0, e2k_cs.bsize);
|
||||
|
||||
tcg_temp_free_i32(t2);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t0);
|
||||
tcg_temp_free_i32(rsz);
|
||||
tcg_temp_free_i32(rcur);
|
||||
}
|
||||
|
||||
static inline void gen_movcond_flag_i32(TCGv_i32 ret, int flag, TCGv_i32 cond,
|
||||
__attribute__((noinline))
|
||||
static void gen_movcond_flag_i32(TCGv_i32 ret, int flag, TCGv_i32 cond,
|
||||
TCGv_i32 v1, TCGv_i32 v2)
|
||||
{
|
||||
TCGv_i32 one = tcg_const_i32(1);
|
||||
|
@ -144,6 +128,7 @@ void e2k_win_commit(DisasContext *dc)
|
|||
int alc = GET_FIELD(ss, 16, 17);
|
||||
int abp = GET_FIELD(ss, 18, 19);
|
||||
int abn = GET_FIELD(ss, 21, 22);
|
||||
int abg = GET_FIELD(ss, 23, 24);
|
||||
|
||||
tcg_gen_trunc_tl_i32(cond, dc->jmp.cond);
|
||||
|
||||
|
@ -156,32 +141,38 @@ void e2k_win_commit(DisasContext *dc)
|
|||
tcg_temp_free_i64(t0);
|
||||
}
|
||||
|
||||
if (abp || abn) {
|
||||
TCGv_i32 br = tcg_temp_new_i32();
|
||||
if (abp) {
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
|
||||
e2k_gen_get_br(br);
|
||||
gen_pcur_inc(t0);
|
||||
gen_movcond_flag_i32(e2k_cs.pcur, abp, cond, t0, e2k_cs.pcur);
|
||||
|
||||
if (abp) {
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
||||
gen_pcur_inc(t0, br);
|
||||
gen_movcond_flag_i32(br, abp, cond, t0, br);
|
||||
if (abn) {
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
gen_rcur_inc(t0);
|
||||
gen_movcond_flag_i32(e2k_cs.bcur, abn, cond, t0, e2k_cs.bcur);
|
||||
|
||||
if (abn) {
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
||||
gen_rcur_inc(t0, br);
|
||||
gen_movcond_flag_i32(br, abn, cond, t0, br);
|
||||
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
||||
e2k_gen_set_br(br);
|
||||
|
||||
tcg_temp_free_i32(br);
|
||||
switch(abg) {
|
||||
case 0x00:
|
||||
break;
|
||||
case 0x01:
|
||||
/* TODO */
|
||||
abort();
|
||||
break;
|
||||
case 0x02:
|
||||
/* TODO */
|
||||
abort();
|
||||
break;
|
||||
default:
|
||||
/* FIXME: exception or nop? */
|
||||
break;
|
||||
}
|
||||
|
||||
tcg_temp_free_i32(cond);
|
||||
|
@ -285,8 +276,8 @@ static void gen_cs0(DisasContext *dc)
|
|||
unsigned int disp = (cs0 & 0x0fffffff);
|
||||
/* Calculate a signed displacement in bytes. */
|
||||
int sdisp = ((int) (disp << 4)) >> 1;
|
||||
target_ulong tgt = dc->pc + sdisp;
|
||||
tcg_gen_movi_tl(dc->jmp.dest, tgt);
|
||||
dc->jmp.dest = dc->pc + sdisp;
|
||||
dc->base.is_jmp = DISAS_STATIC_JUMP;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -318,17 +309,21 @@ static void gen_cs0(DisasContext *dc)
|
|||
tcg_gen_movi_tl(e2k_cs.ctprs[ctpr], reg);
|
||||
}
|
||||
|
||||
if (/* Note that RETURN is said to be COPF1. I can't understand what its
|
||||
`CS0.param' is needed for: all of the bits except the three
|
||||
lowermost ones are undefined, while the latter also known as "type"
|
||||
field should be filled in with zeroes. */
|
||||
type == RETURN
|
||||
/* GETTSD has as meaningless `CS0.param' as RETURN. The only
|
||||
difference is that its `CS0.param.type' should be equal to `1'. I
|
||||
wonder if I should check for that and output something like
|
||||
"invalid gettsd" if this turns out not to be the case . . . */
|
||||
|| type == GETTSD)
|
||||
{
|
||||
/* Note that RETURN is said to be COPF1. I can't understand what its
|
||||
`CS0.param' is needed for: all of the bits except the three
|
||||
lowermost ones are undefined, while the latter also known as "type"
|
||||
field should be filled in with zeroes. */
|
||||
if (type == RETURN) {
|
||||
uint64_t reg = ((uint64_t) CTPR_TAG_RETURN << CTPR_TAG_OFF) |
|
||||
((uint64_t) ipd << CTPR_IPD_OFF);
|
||||
tcg_gen_movi_tl(e2k_cs.ctprs[ctpr], reg);
|
||||
}
|
||||
|
||||
/* GETTSD has as meaningless `CS0.param' as RETURN. The only
|
||||
difference is that its `CS0.param.type' should be equal to `1'. I
|
||||
wonder if I should check for that and output something like
|
||||
"invalid gettsd" if this turns out not to be the case . . . */
|
||||
if (type == GETTSD) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
@ -407,36 +402,40 @@ static void gen_cs1(DisasContext *dc)
|
|||
abort();
|
||||
} else {
|
||||
uint32_t lts0 = bundle->lts[0];
|
||||
int wsz = GET_FIELD(lts0, 5, 11);
|
||||
TCGv_i32 t0 = tcg_const_i32(lts0);
|
||||
|
||||
tcg_gen_movi_i32(e2k_cs.wsz, GET_FIELD(lts0, 5, 11));
|
||||
tcg_gen_movi_i32(e2k_cs.nfx, GET_BIT(lts0, 4));
|
||||
gen_helper_setwd(cpu_env, t0);
|
||||
|
||||
if (dc->version >= 3) {
|
||||
tcg_gen_movi_i32(e2k_cs.dbl, GET_BIT(lts0, 3));
|
||||
}
|
||||
tcg_gen_movi_i32(e2k_cs.wsize, wsz * 2);
|
||||
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
}
|
||||
|
||||
if (setbn || setbp) {
|
||||
TCGv_i32 br = tcg_temp_new_i32();
|
||||
if (setbn) {
|
||||
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);
|
||||
|
||||
e2k_gen_get_br(br);
|
||||
/* update state*/
|
||||
gen_helper_setbn(cpu_env, t1);
|
||||
|
||||
if (setbn) {
|
||||
TCGv_i32 bn = tcg_const_i32(GET_FIELD(cs1, BR_BN_OFF, BR_BN_END));
|
||||
tcg_gen_deposit_i32(br, br, bn, BR_BN_OFF, BR_BN_LEN);
|
||||
tcg_temp_free_i32(bn);
|
||||
}
|
||||
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);
|
||||
|
||||
if (setbp) {
|
||||
TCGv_i32 bp = tcg_const_i32(GET_FIELD(cs1, BR_PSZ_OFF, BR_PSZ_END));
|
||||
tcg_gen_deposit_i32(br, br, bp, BR_BP_OFF, BR_BP_LEN);
|
||||
tcg_temp_free_i32(bp);
|
||||
}
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_ptr(t0);
|
||||
}
|
||||
|
||||
e2k_gen_set_br(br);
|
||||
if (setbp) {
|
||||
int psz = GET_FIELD(cs1, BR_PSZ_OFF, BR_PSZ_END);
|
||||
|
||||
tcg_temp_free_i32(br);
|
||||
tcg_gen_movi_i32(e2k_cs.psize, psz);
|
||||
tcg_gen_movi_i32(e2k_cs.pcur, 0);
|
||||
}
|
||||
} else if (opc == SETEI) {
|
||||
/* Verify that CS1.param.sft = CS1.param[27] is equal to zero as required
|
||||
|
@ -487,7 +486,7 @@ static void gen_cs1(DisasContext *dc)
|
|||
|
||||
if (ctop) {
|
||||
dc->is_call = true;
|
||||
tcg_gen_movi_i32(e2k_cs.syscall_wbs, wbs);
|
||||
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);
|
||||
} else {
|
||||
|
@ -549,18 +548,20 @@ static void gen_jmp(DisasContext *dc)
|
|||
unsigned int ctpr = GET_FIELD(dc->bundle.ss, 10, 11);
|
||||
|
||||
if (cond_type == 1) {
|
||||
dc->base.is_jmp = STATIC_JUMP;
|
||||
/* TODO: optimize ibranch with no cond */
|
||||
tcg_gen_movi_tl(dc->jmp.cond, 1);
|
||||
} else {
|
||||
} else if (cond_type > 1){
|
||||
/* TODO: single assign */
|
||||
TCGv cond = tcg_temp_new();
|
||||
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 = DYNAMIC_JUMP;
|
||||
dc->base.is_jmp = DISAS_DYNAMIC_JUMP;
|
||||
|
||||
e2k_gen_preg(preg, psrc);
|
||||
e2k_gen_preg(t0, psrc);
|
||||
tcg_gen_trunc_i64_tl(preg, t0);
|
||||
gen_is_loop_end(loop_end);
|
||||
tcg_gen_setcondi_tl(TCG_COND_NE, not_loop_end, loop_end, 1);
|
||||
|
||||
|
@ -649,6 +650,7 @@ static void gen_jmp(DisasContext *dc)
|
|||
|
||||
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);
|
||||
|
@ -659,14 +661,13 @@ static void gen_jmp(DisasContext *dc)
|
|||
|
||||
/* TODO: different kinds of ct */
|
||||
if (ctpr != 0) {
|
||||
if (dc->is_call) {
|
||||
/* TODO: call save state */
|
||||
dc->call_ctpr = ctpr;
|
||||
dc->base.is_jmp = DISAS_CALL;
|
||||
return;
|
||||
}
|
||||
dc->jump_ctpr = ctpr;
|
||||
|
||||
tcg_gen_andi_tl(dc->jmp.dest, e2k_cs.ctprs[ctpr], GEN_MASK(0, 47));
|
||||
if (dc->is_call) {
|
||||
dc->base.is_jmp = DISAS_CALL;
|
||||
} else {
|
||||
dc->base.is_jmp = DISAS_DYNAMIC_JUMP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,27 +7,18 @@ static void gen_preg_offset(TCGv_i64 ret, int reg)
|
|||
{
|
||||
assert(reg < 32);
|
||||
|
||||
TCGv_i32 br = tcg_temp_new_i32();
|
||||
TCGv_i32 pcur = tcg_temp_new_i32();
|
||||
TCGv_i32 psz = tcg_temp_new_i32();
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
TCGv_i32 t2 = tcg_temp_new_i32();
|
||||
|
||||
e2k_gen_get_br(br);
|
||||
tcg_gen_extract_i32(pcur, br, BR_PCUR_OFF, BR_PCUR_LEN);
|
||||
tcg_gen_extract_i32(psz, br, BR_PSZ_OFF, BR_PSZ_LEN);
|
||||
tcg_gen_addi_i32(t0, pcur, reg);
|
||||
e2k_gen_wrap_i32(t1, t0, psz);
|
||||
tcg_gen_shli_i32(t2, t1, 1);
|
||||
tcg_gen_addi_i32(t0, e2k_cs.pcur, reg);
|
||||
e2k_gen_wrap_i32(t1, t0, e2k_cs.psize);
|
||||
tcg_gen_muli_i32(t2, t1, 2);
|
||||
tcg_gen_extu_i32_i64(ret, t2);
|
||||
|
||||
tcg_temp_free_i32(t2);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t0);
|
||||
tcg_temp_free_i32(psz);
|
||||
tcg_temp_free_i32(pcur);
|
||||
tcg_temp_free_i32(br);
|
||||
}
|
||||
|
||||
static void gen_preg_clear(TCGv_i64 ret, TCGv_i64 offset)
|
||||
|
@ -47,15 +38,20 @@ static void gen_preg_clear(TCGv_i64 ret, TCGv_i64 offset)
|
|||
|
||||
void e2k_gen_preg(TCGv_i64 ret, int reg)
|
||||
{
|
||||
TCGv_i64 one = tcg_const_i64(1);
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
|
||||
gen_preg_offset(t0, reg);
|
||||
tcg_gen_shri_i64(t1, e2k_cs.pregs, reg * 2);
|
||||
tcg_gen_andi_i64(ret, t1, 0x01);
|
||||
tcg_gen_shl_i64(t1, one, t0);
|
||||
tcg_gen_and_i64(t2, e2k_cs.pregs, t1);
|
||||
tcg_gen_setcondi_i64(TCG_COND_NE, ret, t2, 0);
|
||||
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_temp_free_i64(t1);
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free_i64(one);
|
||||
}
|
||||
|
||||
TCGv_i64 e2k_get_preg(DisasContext *dc, int reg)
|
||||
|
@ -69,11 +65,12 @@ void e2k_gen_store_preg(int reg, TCGv_i64 val)
|
|||
{
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2 = tcg_const_i64(1);
|
||||
TCGv_i64 t2 = tcg_temp_new_i64();
|
||||
TCGv_i64 t3 = tcg_temp_new_i64();
|
||||
|
||||
gen_preg_offset(t0, reg);
|
||||
gen_preg_clear(t1, t0);
|
||||
tcg_gen_setcondi_i64(TCG_COND_NE, t2, val, 0);
|
||||
tcg_gen_shl_i64(t3, t2, t0);
|
||||
tcg_gen_or_i64(e2k_cs.pregs, t1, t3);
|
||||
|
||||
|
@ -83,23 +80,15 @@ void e2k_gen_store_preg(int reg, TCGv_i64 val)
|
|||
tcg_temp_free_i64(t0);
|
||||
}
|
||||
|
||||
static inline void gen_wreg_offset(TCGv_i32 ret, int reg)
|
||||
static inline void gen_wreg_index(TCGv_i32 ret, int reg)
|
||||
{
|
||||
assert(reg < 64);
|
||||
// TODO: exception (wsz * 2) <= reg_index
|
||||
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
TCGv_i32 t2 = tcg_temp_new_i32();
|
||||
TCGv_i32 t3 = tcg_const_i32(WREGS_SIZE);
|
||||
TCGv_i32 t1 = tcg_const_i32(WREGS_SIZE);
|
||||
|
||||
tcg_gen_shli_i32(t0, e2k_cs.wbs, 1); // t = wbs * 2
|
||||
tcg_gen_addi_i32(t1, t0, reg); // t = t + reg_index
|
||||
e2k_gen_wrap_i32(t2, t1, t3); // t = t % WIN_REGS_COUNT
|
||||
tcg_gen_muli_i32(ret, t2, REG_SIZE); // t = t * REG_SIZE_IN_BYTES
|
||||
/* TODO: exception if overflow window size */
|
||||
tcg_gen_addi_i32(t0, e2k_cs.woff, reg);
|
||||
tcg_gen_remu_i32(ret, t0, t1);
|
||||
|
||||
tcg_temp_free_i32(t3);
|
||||
tcg_temp_free_i32(t2);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
@ -107,100 +96,76 @@ static inline void gen_wreg_offset(TCGv_i32 ret, int reg)
|
|||
static inline void gen_wreg_ptr(TCGv_ptr ret, int reg)
|
||||
{
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
TCGv_ptr t1 = tcg_temp_new_ptr();
|
||||
gen_wreg_offset(t0, reg);
|
||||
tcg_gen_ext_i32_ptr(t1, t0);
|
||||
tcg_gen_add_ptr(ret, e2k_cs.win_ptr, t1);
|
||||
tcg_temp_free_ptr(t1);
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
TCGv_ptr t2 = tcg_temp_new_ptr();
|
||||
|
||||
gen_wreg_index(t0, reg);
|
||||
tcg_gen_muli_i32(t1, t0, 8);
|
||||
tcg_gen_ext_i32_ptr(t2, t1);
|
||||
tcg_gen_add_ptr(ret, e2k_cs.wptr, t2);
|
||||
|
||||
tcg_temp_free_ptr(t2);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
||||
TCGv_i64 e2k_get_wreg(DisasContext *dc, int reg)
|
||||
{
|
||||
TCGv_i64 ret = e2k_get_temp_i64(dc);
|
||||
TCGv_ptr ptr = tcg_temp_new_ptr();
|
||||
gen_wreg_ptr(ptr, reg);
|
||||
tcg_gen_ld_i64(ret, ptr, 0);
|
||||
tcg_temp_free_ptr(ptr);
|
||||
return ret;
|
||||
TCGv_ptr t0 = tcg_temp_new_ptr();
|
||||
TCGv_i64 t1 = e2k_get_temp_i64(dc);
|
||||
|
||||
gen_wreg_ptr(t0, reg);
|
||||
tcg_gen_ld_i64(t1, t0, 0);
|
||||
|
||||
tcg_temp_free_ptr(t0);
|
||||
|
||||
return t1;
|
||||
}
|
||||
|
||||
void e2k_gen_store_wreg(int reg, TCGv_i64 val)
|
||||
{
|
||||
TCGv_ptr ptr = tcg_temp_new_ptr();
|
||||
gen_wreg_ptr(ptr, reg);
|
||||
tcg_gen_st_i64(val, ptr, 0);
|
||||
tcg_temp_free_ptr(ptr);
|
||||
TCGv_ptr t0 = tcg_temp_new_ptr();
|
||||
|
||||
gen_wreg_ptr(t0, reg);
|
||||
tcg_gen_st_i64(val, t0, 0);
|
||||
|
||||
tcg_temp_free_ptr(t0);
|
||||
}
|
||||
|
||||
static inline void gen_breg_start(TCGv_i32 ret, TCGv_i32 br)
|
||||
static inline void gen_breg_index(TCGv_i32 ret, int reg)
|
||||
{
|
||||
TCGv_i32 rbs = tcg_temp_new_i32();
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
|
||||
tcg_gen_extract_i32(rbs, br, BR_RBS_OFF, BR_RBS_LEN);
|
||||
tcg_gen_add_i32(t0, e2k_cs.wbs, rbs);
|
||||
tcg_gen_shli_i32(ret, t0, 1);
|
||||
|
||||
tcg_temp_free_i32(t0);
|
||||
tcg_temp_free_i32(rbs);
|
||||
}
|
||||
|
||||
static inline void gen_breg_offset(TCGv_i32 ret, int reg)
|
||||
{
|
||||
TCGv_i32 br = tcg_temp_new_i32();
|
||||
TCGv_i32 rcur = tcg_temp_new_i32();
|
||||
TCGv_i32 rsz = tcg_temp_new_i32();
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
TCGv_i32 t2 = tcg_temp_new_i32();
|
||||
TCGv_i32 t3 = tcg_temp_new_i32();
|
||||
TCGv_i32 t4 = tcg_temp_new_i32();
|
||||
TCGv_i32 t5 = tcg_temp_new_i32();
|
||||
TCGv_i32 t6 = tcg_temp_new_i32();
|
||||
TCGv_i32 t7 = tcg_temp_new_i32();
|
||||
TCGv_i32 t4 = tcg_const_i32(WREGS_SIZE);
|
||||
|
||||
e2k_gen_get_br(br);
|
||||
/* TODO: exception: reg > (rsz * 2 + 2) */
|
||||
/* t = (reg + rcur * 2) % (rsz * 2 + 2) */
|
||||
tcg_gen_extract_i32(rcur, br, BR_RCUR_OFF, BR_RCUR_LEN);
|
||||
tcg_gen_extract_i32(rsz, br, BR_RSZ_OFF, BR_RSZ_LEN);
|
||||
tcg_gen_shli_i32(t0, rcur, 1);
|
||||
tcg_gen_addi_i32(t1, t0, reg);
|
||||
tcg_gen_addi_i32(t2, rsz, 1);
|
||||
tcg_gen_shli_i32(t3, t2, 1);
|
||||
e2k_gen_wrap_i32(t4, t1, t3);
|
||||
tcg_gen_addi_i32(t0, e2k_cs.bcur, reg);
|
||||
tcg_gen_remu_i32(t1, t0, e2k_cs.bsize);
|
||||
tcg_gen_add_i32(t2, t1, e2k_cs.boff);
|
||||
tcg_gen_add_i32(t3, t2, e2k_cs.woff);
|
||||
tcg_gen_remu_i32(ret, t3, t4);
|
||||
|
||||
/* TODO: exceptioon: (reg + rbs * 2) > (wsz * 2) */
|
||||
/* t = (t + wbs * 2 + rbs * 2) % 192 */
|
||||
gen_breg_start(t5, br);
|
||||
tcg_gen_add_i32(t6, t4, t5);
|
||||
e2k_gen_wrapi_i32(t7, t6, WREGS_SIZE);
|
||||
|
||||
/* ret = t * 8 */
|
||||
tcg_gen_muli_i32(ret, t7, REG_SIZE);
|
||||
|
||||
tcg_temp_free_i32(t7);
|
||||
tcg_temp_free_i32(t6);
|
||||
tcg_temp_free_i32(t5);
|
||||
tcg_temp_free_i32(t4);
|
||||
tcg_temp_free_i32(t3);
|
||||
tcg_temp_free_i32(t2);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t0);
|
||||
tcg_temp_free_i32(rsz);
|
||||
tcg_temp_free_i32(rcur);
|
||||
tcg_temp_free_i32(br);
|
||||
}
|
||||
|
||||
static inline void gen_breg_ptr(TCGv_ptr ret, int reg)
|
||||
{
|
||||
TCGv_i32 t0 = tcg_temp_new_i32();
|
||||
TCGv_ptr t1 = tcg_temp_new_ptr();
|
||||
gen_breg_offset(t0, reg);
|
||||
tcg_gen_ext_i32_ptr(t1, t0);
|
||||
tcg_gen_add_ptr(ret, e2k_cs.win_ptr, t1);
|
||||
tcg_temp_free_ptr(t1);
|
||||
TCGv_i32 t1 = tcg_temp_new_i32();
|
||||
TCGv_ptr t2 = tcg_temp_new_ptr();
|
||||
|
||||
gen_breg_index(t0, reg);
|
||||
tcg_gen_muli_i32(t1, t0, 8);
|
||||
tcg_gen_ext_i32_ptr(t2, t1);
|
||||
tcg_gen_add_ptr(ret, e2k_cs.wptr, t2);
|
||||
|
||||
tcg_temp_free_ptr(t2);
|
||||
tcg_temp_free_i32(t1);
|
||||
tcg_temp_free_i32(t0);
|
||||
}
|
||||
|
||||
|
@ -224,13 +189,12 @@ void e2k_gen_store_breg(int reg, TCGv_i64 val)
|
|||
|
||||
TCGv_i64 e2k_get_greg(DisasContext *dc, int reg)
|
||||
{
|
||||
// TODO: rotated gregs
|
||||
assert(reg < 32);
|
||||
assert(reg < GREGS_MAX + BGREGS_MAX);
|
||||
return e2k_cs.gregs[reg];
|
||||
}
|
||||
|
||||
void e2k_gen_store_greg(int reg, TCGv_i64 val)
|
||||
{
|
||||
// TODO: rotated gregs
|
||||
assert(reg < GREGS_MAX + BGREGS_MAX);
|
||||
tcg_gen_mov_i64(e2k_cs.gregs[reg], val);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue