diff --git a/linux-user/e2k/cpu_loop.c b/linux-user/e2k/cpu_loop.c index 6fc17e14c9..83db9ff023 100644 --- a/linux-user/e2k/cpu_loop.c +++ b/linux-user/e2k/cpu_loop.c @@ -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; } diff --git a/linux-user/elfload.c b/linux-user/elfload.c index a116101d4e..287fca7c74 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -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"); } diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index 1558762e31..7bc05b3781 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -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); diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index f176459776..17af5f7749 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -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; diff --git a/target/e2k/helper.c b/target/e2k/helper.c index d55783a1a8..1dd8266112 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -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 + ); +} diff --git a/target/e2k/helper.h b/target/e2k/helper.h index 9269f443e9..79a51da74d 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -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) diff --git a/target/e2k/translate.c b/target/e2k/translate.c index 6025c05b75..c1fcbba3e5 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -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); } } diff --git a/target/e2k/translate.h b/target/e2k/translate.h index 6a0cbce1f2..44dfd032b9 100644 --- a/target/e2k/translate.h +++ b/target/e2k/translate.h @@ -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); diff --git a/target/e2k/translate/alc.c b/target/e2k/translate/alc.c index c03937a038..d9a6eda8c7 100644 --- a/target/e2k/translate/alc.c +++ b/target/e2k/translate/alc.c @@ -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; diff --git a/target/e2k/translate/control.c b/target/e2k/translate/control.c index d0be112f28..112bb0a0d8 100644 --- a/target/e2k/translate/control.c +++ b/target/e2k/translate/control.c @@ -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; + } } } diff --git a/target/e2k/translate/state.c b/target/e2k/translate/state.c index 8f44f09981..833ca14344 100644 --- a/target/e2k/translate/state.c +++ b/target/e2k/translate/state.c @@ -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); }