target: e2k: Add basic call (without saving regs).

This commit is contained in:
Denis Drakhnia 2020-11-15 17:05:27 +02:00
parent aca6a33344
commit d495f0ffb3
11 changed files with 559 additions and 354 deletions

View File

@ -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;
}

View File

@ -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");
}

View File

@ -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);

View File

@ -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;

View File

@ -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
);
}

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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);
}