From 48290cb80cae28b49ce938957c8de63687a57738 Mon Sep 17 00:00:00 2001 From: Denis Drakhnya Date: Mon, 29 Mar 2021 19:25:50 +0300 Subject: [PATCH] e2k: Update get/set state regs. Signed-off-by: Denis Drakhnya --- linux-user/e2k/cpu_loop.c | 5 +- linux-user/e2k/signal.c | 6 + linux-user/e2k/target_cpu.h | 9 +- linux-user/e2k/target_syscall.h | 4 +- linux-user/elfload.c | 27 +-- linux-user/syscall.c | 2 +- target/e2k/cpu.c | 24 +- target/e2k/cpu.h | 408 ++++++++++++++++++++------------ target/e2k/gdbstub.c | 86 ++++--- target/e2k/helper-tcg.h | 62 ++--- target/e2k/helper.c | 4 + target/e2k/helper.h | 5 +- target/e2k/helper_int.c | 328 ++++++++++++++++++++----- target/e2k/translate.c | 171 +++++++++++-- 14 files changed, 796 insertions(+), 345 deletions(-) diff --git a/linux-user/e2k/cpu_loop.c b/linux-user/e2k/cpu_loop.c index e974c7ed48..8d283ff3ee 100644 --- a/linux-user/e2k/cpu_loop.c +++ b/linux-user/e2k/cpu_loop.c @@ -38,7 +38,7 @@ static void gen_signal(CPUE2KState *env, int signo, int code, abi_ulong addr) queue_signal(env, signo, QEMU_SI_FAULT, &info); } -static void stack_expand(CPUE2KState *env, E2KStackState *s) +static void stack_expand(CPUE2KState *env, E2KPsp *s) { abi_ulong new_size, new_size_tag; abi_long new_base, new_base_tag = 0; @@ -98,6 +98,7 @@ void cpu_loop(CPUE2KState *env) break; } case EXCP_ILLEGAL_OPCODE: + case EXCP_PRIV_ACTION: gen_signal(env, TARGET_SIGILL, TARGET_ILL_ILLOPC, env->ip); break; case EXCP_ILLEGAL_OPERAND: @@ -150,6 +151,8 @@ void target_cpu_copy_regs(CPUE2KState *env, struct target_pt_regs *regs) struct image_info *info = ts->info; uint32_t eflags = info->elf_flags; + env->psr = PSR_NMIE | PSR_SGE | PSR_IE; + env->upsr = UPSR_NMIE | UPSR_IE | UPSR_FE; env->ip = regs->ip; env->pcsp = regs->pcsp; env->psp = regs->psp; diff --git a/linux-user/e2k/signal.c b/linux-user/e2k/signal.c index 511b389d05..f3350bc45d 100644 --- a/linux-user/e2k/signal.c +++ b/linux-user/e2k/signal.c @@ -112,6 +112,8 @@ struct target_sigframe { E2KAauState aau; uint64_t lsr; uint64_t lsr_lcnt; + uint32_t ilcr; + uint64_t ilcr_lcnt; // FIXME: according to ABI only 16-31 must be saved E2KReg gregs[16]; uint8_t gtags[16]; @@ -221,6 +223,8 @@ static void target_setup_frame(int sig, struct target_sigaction *ka, &env->aau, sizeof(env->aau)); __put_user(env_lsr_get(env), &frame->lsr); __put_user(env->lsr_lcnt, &frame->lsr_lcnt); + __put_user(env->ilcr, &frame->ilcr); + __put_user(env->ilcr_lcnt, &frame->ilcr_lcnt); copy_to_user(frame_addr + offsetof(struct target_sigframe, gregs), &env->regs[E2K_NR_COUNT + 16], 16 * sizeof(E2KReg)); copy_to_user(frame_addr + offsetof(struct target_sigframe, gtags), @@ -323,6 +327,8 @@ long do_rt_sigreturn(CPUE2KState *env) + offsetof(struct target_sigframe, aau), sizeof(env->aau)); __get_user(env->lsr, &frame->lsr); __get_user(env->lsr_lcnt, &frame->lsr_lcnt); + __get_user(env->ilcr, &frame->ilcr); + __get_user(env->ilcr_lcnt, &frame->ilcr_lcnt); copy_from_user(&env->regs[E2K_NR_COUNT + 16], frame_addr + offsetof(struct target_sigframe, gregs), 16 * sizeof(E2KReg)); copy_from_user(&env->tags[E2K_NR_COUNT + 16], frame_addr diff --git a/linux-user/e2k/target_cpu.h b/linux-user/e2k/target_cpu.h index 7825349b51..c5e3e3c9d3 100644 --- a/linux-user/e2k/target_cpu.h +++ b/linux-user/e2k/target_cpu.h @@ -18,8 +18,8 @@ static inline void cpu_clone_regs_child(CPUE2KState *env, target_ulong newsp, } if (flags & CLONE_VM) { - E2KPcsState pcs = { 0 }; - E2KPsState ps = { 0 }; + E2KPsp pcs = { 0 }; + E2KPsp ps = { 0 }; E2KCrs crs = { 0 }; uint64_t *ps_old, *ps_new; size_t frame_size; @@ -27,11 +27,10 @@ static inline void cpu_clone_regs_child(CPUE2KState *env, target_ulong newsp, target_ulong ps_base = env->psp.base + env->psp.index; int i; - e2k_pcs_new(&pcs); - e2k_ps_new(&ps); + e2k_psp_new(&pcs, E2K_DEFAULT_PCS_SIZE, false); + e2k_psp_new(&ps, E2K_DEFAULT_PS_SIZE, true); // TODO: size checks and a way to report errors - // TODO: set a chain info to return to kernel pcs.index += sizeof(E2KCrs); diff --git a/linux-user/e2k/target_syscall.h b/linux-user/e2k/target_syscall.h index aa39d55781..7dea45dd58 100644 --- a/linux-user/e2k/target_syscall.h +++ b/linux-user/e2k/target_syscall.h @@ -31,8 +31,8 @@ struct target_pt_regs { // uint64_t tr; // current type register - E2KPcsState pcsp; - E2KPsState psp; + E2KPsp pcsp; + E2KPsp psp; uint32_t psr; // Processor State Register (PSR) uint32_t upsr; // User processor status register (UPSR) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index e6e2acb3e4..273e3da057 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1637,23 +1637,14 @@ static abi_ulong e2k_mmap(abi_ulong size) return addr; } -void e2k_pcs_new(E2KPcsState *pcs) +void e2k_psp_new(E2KPsp *psp, unsigned int size, bool tags) { - pcs->is_readable = true; - pcs->is_writable = true; - pcs->index = 0; - pcs->size = E2K_DEFAULT_PCS_SIZE; - pcs->base = e2k_mmap(pcs->size); -} - -void e2k_ps_new(E2KPsState *ps) -{ - ps->is_readable = true; - ps->is_writable = true; - ps->index = 0; - ps->size = E2K_DEFAULT_PS_SIZE; - ps->base = e2k_mmap(ps->size); - ps->base_tag = e2k_mmap(ps->size / 8); + psp->is_readable = true; + psp->is_writable = true; + psp->index = 0; + psp->size = size; + psp->base = e2k_mmap(size); + psp->base_tag = tags ? e2k_mmap(size / 8) : 0; } static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) @@ -1667,8 +1658,8 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i regs->usd_lo = (0x1800UL << 48) | start_stack; regs->usd_hi = (regs->sbr - start_stack) << 32; - e2k_pcs_new(®s->pcsp); - e2k_ps_new(®s->psp); + e2k_psp_new(®s->pcsp, E2K_DEFAULT_PCS_SIZE, false); + e2k_psp_new(®s->psp, E2K_DEFAULT_PS_SIZE, true); } static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUE2KState *env) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index d776b79e37..2a122bc4ea 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7045,7 +7045,7 @@ abi_long e2k_copy_to_user_crs(abi_ulong target_crs_addr, E2KCrs *crs) static abi_long do_e2k_longjmp2(CPUE2KState *env, struct target_jmp_info *jmp_info) { - E2KPcsState jmp_pcsp; + E2KPsp jmp_pcsp; E2KCrs crs; int level; /* how many CRs need to restore */ int ps_index = env->psp.index; diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index f74644c4c8..9886d095bf 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -31,7 +31,6 @@ //#define DEBUG_FEATURES -void cpu_e2k_set_id(CPUE2KState *env, unsigned int cpu); void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags); static void e2k_cpu_reset(DeviceState *dev) @@ -45,6 +44,8 @@ static void e2k_cpu_reset(DeviceState *dev) memset(env, 0, offsetof(CPUE2KState, end_reset_fields)); + env->psr = PSR_PM; + env->upsr = UPSR_NMIE | UPSR_FE; env->wd.base = 0; env->wd.size = 16; env->wd.psize = 8; @@ -64,6 +65,12 @@ static void e2k_cpu_reset(DeviceState *dev) // FIXME: testing env->idr = 0x3a207; /* mimic 8c */ + + // FIXME: correct values + env->psp.base = 0x810000; + env->psp.size = 0x100000; + env->pcsp.base = 0x910000; + env->pcsp.size = 0xa10000; } #ifdef CONFIG_SOFTMMU @@ -93,13 +100,6 @@ static void cpu_e2k_disas_set_info(CPUState *cs, disassemble_info *info) info->print_insn = print_insn_e2k; } - -void cpu_e2k_set_id(CPUE2KState *env, unsigned int cpu) -{ - // TODO: cpu_e2k_set_id - qemu_log_mask(LOG_UNIMP, "cpu_e2k_set_id: not implemented\n"); -} - /* https://www.altlinux.org/Модели_процессоров_Эльбрус */ #define DEFAULT_CPU_MODEL "e8c" static const struct e2k_def_t e2k_defs[] = { @@ -157,10 +157,10 @@ void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags) qemu_fprintf(f, " ip = " TARGET_FMT_lx "\n", env->ip); qemu_fprintf(f, " pregs = 0x%016lx\n", env->pregs); - qemu_fprintf(f, " pcsp_lo = 0x%016lx\n", env_pcsp_lo_get(env)); - qemu_fprintf(f, " pcsp_hi = 0x%016lx\n", env_pcsp_hi_get(env)); - qemu_fprintf(f, " psp_lo = 0x%016lx\n", env_psp_lo_get(env)); - qemu_fprintf(f, " psp_hi = 0x%016lx\n", env_psp_hi_get(env)); + qemu_fprintf(f, " pcsp_lo = 0x%016lx\n", env->pcsp.lo); + qemu_fprintf(f, " pcsp_hi = 0x%016lx\n", env->pcsp.hi); + qemu_fprintf(f, " psp_lo = 0x%016lx\n", env->psp.lo); + qemu_fprintf(f, " psp_hi = 0x%016lx\n", env->psp.hi); qemu_fprintf(f, " usd_lo = 0x%016lx\n", env->usd.lo); qemu_fprintf(f, " usd_hi = 0x%016lx\n", env->usd.hi); qemu_fprintf(f, " lsr = 0x%016lx\n", env->lsr); diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index a0e17d4837..dc6164b567 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -28,10 +28,13 @@ void e2k_tcg_initialize(void); */ #define E2K_FORCE_FX true -#define GEN_MASK(start, len) (((1UL << (len)) - 1) << (start)) +#define GEN_MASK(start, len) (((1ULL << (len)) - 1) << (start)) #define GET_BIT(v, index) (((v) >> (index)) & 1) #define MMU_USER_IDX 1 +#define E2K_VA_SIZE 48 +#define E2K_VA_MSB (E2K_VA_SIZE - 1) + #define CPU_RESOLVING_TYPE TYPE_E2K_CPU #define E2K_REG_LEN sizeof(uint64_t) @@ -141,135 +144,107 @@ typedef enum { #define DESC_LO_WRITE_OFF 60 #define DESC_LO_WRITE_BIT (1UL << DESC_LO_WRITE_OFF) -#define PSHTP_IND_OFF 0 -#define PSHTP_IND_END 11 -#define PSHTP_IND_LEN (PSHTP_IND_END - PSHTP_IND_OFF + 1) -#define PSHTP_FXIND_OFF 16 -#define PSHTP_FXIND_END 26 -#define PSHTP_FXIND_LEN (PSHTP_FXIND_END - PSHTP_FXIND_OFF + 1) -#define PSHTP_TIND_OFF 32 -#define PSHTP_TIND_END 42 -#define PSHTP_TIND_LEN (PSHTP_TIND_END - PSHTP_TIND_OFF + 1) -#define PSHTP_FX_OFF 48 -#define PSHTP_FX_BIT (1UL << PSHTP_FX_OFF) - #define USD_LO_BASE_OFF 0 -#define USD_LO_BASE_END 47 -#define USD_LO_BASE_LEN (USD_LO_BASE_END - USD_LO_BASE_OFF + 1) +#define USD_LO_BASE_LEN 48 #define USD_LO_PROTECTED_OFF 58 -#define USD_LO_PROTECTED_BIT (1UL << USD_LO_PROTECTED_OFF) +#define USD_LO_PROTECTED_BIT (1ULL << USD_LO_PROTECTED_OFF) #define USD_LO_READ_OFF 59 -#define USD_LO_READ_BIT (1UL << USD_LO_READ_OFF) +#define USD_LO_READ_BIT (1ULL << USD_LO_READ_OFF) #define USD_LO_WRITE_OFF 60 -#define USD_LO_WRITE_BIT (1UL << USD_LO_WRITE_OFF) +#define USD_LO_WRITE_BIT (1ULL << USD_LO_WRITE_OFF) #define USD_HI_CURPTR_OFF 0 -#define USD_HI_CURPTR_END 31 -#define USD_HI_CURPTR_LEN (USD_HI_CURPTR_END - USD_HI_CURPTR_OFF + 1) +#define USD_HI_CURPTR_LEN 32 #define USD_HI_SIZE_OFF 32 -#define USD_HI_SIZE_END 63 -#define USD_HI_SIZE_LEN (USD_HI_SIZE_END - USD_HI_SIZE_OFF + 1) +#define USD_HI_SIZE_LEN 32 #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) +#define CR1_HI_BR_LEN 28 #define CR1_HI_WDBL_OFF 35 -#define CR1_HI_WDBL_BIT (1UL << CR1_HI_WDBL_OFF) +#define CR1_HI_WDBL_BIT (1ULL << CR1_HI_WDBL_OFF) #define CR1_HI_USSZ_OFF 36 -#define CR1_HI_USSZ_END 63 -#define CR1_HI_USSZ_LEN (CR1_HI_USSZ_END - CR1_HI_USSZ_OFF + 1) +#define CR1_HI_USSZ_LEN 28 #define CR1_LO_TR_OFF 0 -#define CR1_LO_TR_END 14 -#define CR1_LO_TR_LEN (CR1_LO_TR_END - CR1_LO_TR_OFF + 1) +#define CR1_LO_TR_LEN 15 #define CR1_LO_EIN_OFF 16 -#define CR1_LO_EIN_END 23 -#define CR1_LO_EIN_LEN (CR1_LO_EIN_END - CR1_LO_EIN_OFF + 1) +#define CR1_LO_EIN_LEN 8 #define CR1_LO_SS_OFF 24 -#define CR1_LO_SS_BIT (1UL << CR1_LO_SS_OFF) +#define CR1_LO_SS_BIT (1ULL << CR1_LO_SS_OFF) #define CR1_LO_WFX_OFF 25 -#define CR1_LO_WFX_BIT (1UL << CR1_LO_WFX_OFF) +#define CR1_LO_WFX_BIT (1ULL << CR1_LO_WFX_OFF) #define CR1_LO_WPSZ_OFF 26 -#define CR1_LO_WPSZ_END 32 -#define CR1_LO_WPSZ_LEN (CR1_LO_WPSZ_END - CR1_LO_WPSZ_OFF + 1) +#define CR1_LO_WPSZ_LEN 7 #define CR1_LO_WBS_OFF 33 -#define CR1_LO_WBS_END 39 -#define CR1_LO_WBS_LEN (CR1_LO_WBS_END - CR1_LO_WBS_OFF + 1) +#define CR1_LO_WBS_LEN 7 #define CR1_LO_CUIR_OFF 40 -#define CR1_LO_CUIR_END 56 -#define CR1_LO_CUIR_LEN (CR1_LO_CUIR_END - CR1_LO_CUIR_OFF + 1) +#define CR1_LO_CUIR_LEN 17 #define CR1_LO_PSR_OFF 57 -#define CR1_LO_PSR_END 63 -#define CR1_LO_PSR_LEN (CR1_LO_PSR_END - CR1_LO_PSR_OFF + 1) +#define CR1_LO_PSR_LEN 7 #define BR_RBS_OFF 0 /* based regs window offset */ -#define BR_RBS_END 5 -#define BR_RBS_LEN (BR_RBS_END - BR_RBS_OFF + 1) +#define BR_RBS_LEN 6 #define BR_RSZ_OFF 6 /* based regs window size */ -#define BR_RSZ_END 11 -#define BR_RSZ_LEN (BR_RSZ_END - BR_RSZ_OFF + 1) +#define BR_RSZ_LEN 6 #define BR_RCUR_OFF 12 /* based regs current index */ -#define BR_RCUR_END 17 -#define BR_RCUR_LEN (BR_RCUR_END - BR_RCUR_OFF + 1) -#define BR_BN_OFF BR_RBS_OFF -#define BR_BN_END BR_RCUR_END -#define BR_BN_LEN (BR_BN_END - BR_BN_OFF + 1) +#define BR_RCUR_LEN 6 +#define BR_BN_OFF 0 +#define BR_BN_LEN 18 #define BR_PSZ_OFF 18 /* based pregs window size */ -#define BR_PSZ_END 22 -#define BR_PSZ_LEN (BR_PSZ_END - BR_PSZ_OFF + 1) +#define BR_PSZ_LEN 5 #define BR_PCUR_OFF 23 /* based pregs current index */ -#define BR_PCUR_END 27 -#define BR_PCUR_LEN (BR_PCUR_END - BR_PCUR_OFF + 1) -#define BR_BP_OFF BR_PSZ_OFF -#define BR_BP_END BR_PCUR_END -#define BR_BP_LEN (BR_BP_END - BR_BP_OFF + 1) +#define BR_PCUR_LEN 5 +#define BR_BP_OFF 18 +#define BR_BP_LEN 10 + +#define BGR_VAL_OFF 0 +#define BGR_VAL_LEN 8 +#define BGR_CUR_OFF 8 +#define BGR_CUR_LEN 3 +#define BGR_MASK 0x7ff #define LSR_LCNT_OFF 0 /* loop counter */ -#define LSR_LCNT_END 31 -#define LSR_LCNT_LEN (LSR_LCNT_END - LSR_LCNT_OFF + 1) +#define LSR_LCNT_LEN 32 #define LSR_ECNT_OFF 32 /* epilogue counter */ -#define LSR_ECNT_END 36 -#define LSR_ECNT_LEN (LSR_ECNT_END - LSR_ECNT_OFF + 1) +#define LSR_ECNT_LEN 5 #define LSR_VLC_OFF 37 /* loop count valid bit */ #define LSR_VLC_BIT (1UL << LSR_VLC_OFF) #define LSR_OVER_OFF 38 /* loop count overflow */ #define LSR_LDMC_OFF 39 /* loads manual control */ #define LSR_LDOVL_OFF 40 /* load overlap */ -#define LSR_LDOVL_END 47 -#define LSR_LDOVL_SIZE (LSR_LDOVL_END - LSR_LDOVL_OFF + 1) +#define LSR_LDOVL_LEN 8 #define LSR_PCNT_OFF 48 /* prologue counter */ -#define LSR_PCNT_END 52 -#define LSR_PCNT_LEN (LSR_PCNT_END - LSR_PCNT_OFF + 1) +#define LSR_PCNT_LEN 5 #define LSR_STRMD_OFF 53 /* store remainder counter */ -#define LSR_STRMD_END 59 -#define LSR_STRMD_LEN (LSR_STRMD_END - LSR_STRMD_OFF + 1) -#define LSR_SEMC_OFF /* side effects manual control */ -#define LSR_ILCR_MASK 0x1f001fffffffffUL +#define LSR_STRMD_LEN 7 +#define LSR_SEMC_OFF 60 /* side effects manual control */ +#define ILCR_MASK 0x1f001f -#define UPSR_FE_OFF 0 /* floating point enable */ -#define UPSR_FE_BIT 1 -#define UPSR_SE_OFF 1 /* supervisor mode enable (only for Intel) */ -#define UPSR_SE_BIT (1 << UPSR_SE_OFF) -#define UPSR_AC_OFF 2 /* not-aligned access control */ -#define UPSR_AC_BIT (1 << UPSR_AC_OFF) -#define UPSR_DI_OFF 3 /* delayed interrupt (only for Intel) */ -#define UPSR_DI_BIT (1 << UPSR_DI_OFF) -#define UPSR_WP_OFF 4 /* write protection (only for Intel) */ -#define UPSR_WP_BIT (1 << UPSR_WP_OFF) -#define UPSR_IE_OFF 5 /* interrupt enable */ -#define UPSR_IE_BIT (1 << UPSR_IE_OFF) -#define UPSR_A20_OFF 6 /* emulation of 1 Mb memory (only for Intel) */ -#define UPSR_A20_BIT (1 << UPSR_A20_OFF) -#define UPSR_NMIE_OFF 7 /* not masked interrupt enable */ -#define UPSR_NMIE_BIT (1 << UPSR_NMIE_OFF) -/* next field of register exist only on E3S/ES2/E2S/E8C/E1C+ CPUs */ -#define UPSR_FSM_OFF 8 /* floating comparison mode flag */ - /* 1 - compatible with x86/x87 */ -#define UPSR_FSM_BIT (1 << UPSR_FSM_OFF) -#define UPSR_IMPT_OFF 9 /* ignore Memory Protection Table flag */ -#define UPSR_IMPT_BIT (1 << UPSR_IMPT_OFF) -#define UPSR_IUC_OFF 10 /* ignore access right for uncached pages */ -#define UPSR_IUC_BIT (1 << UPSR_IUC_OFF) +#define PSR_PM 0x01U /* privileged mode */ +#define PSR_IE 0x02U +#define PSR_SGE 0x04U +#define PSR_LW 0x08U +#define PSR_UIE 0x10U +#define PSR_NMIE 0x20U +#define PSR_UNMIE 0x40U +#define PSR_MASK 0x7fU + +#define UPSR_FE 0x01U /* floating point enable */ +#define UPSR_SE 0x02U /* supervisor mode enable (only for Intel) */ +#define UPSR_AC 0x04U /* not-aligned access control */ +#define UPSR_DI 0x08U /* delayed interrupt (only for Intel) */ +#define UPSR_WP 0x10U /* write protection (only for Intel) */ +#define UPSR_IE 0x20U /* interrupt enable */ +#define UPSR_A20 0x40U /* emulation of 1 Mb memory (only for Intel) */ +#define UPSR_NMIE 0x80U /* not masked interrupt enable */ +#define UPSR_FSM 0x100U /* only on E3S/ES2/E2S/E8C/E1C+ CPUs */ + /* floating comparison mode flag */ + /* 1 - compatible with x86/x87 */ +#define UPSR_IMPT 0x200U /* ignore Memory Protection Table flag */ +#define UPSR_IUC 0x400U /* ignore access right for uncached pages */ +#define UPSR_MASK 0x7ff + +#define CUIR_MASK 0x1ffff #define IDR_MDL_OFF 0 /* CPU model number */ #define IDR_MDL_END 7 @@ -344,6 +319,93 @@ typedef enum { #endif } Exception; +typedef enum { + SR_PSR = 0x00, + SR_WD = 0x01, + SR_CORE_MODE = 0x04, + SR_CWD = 0x06, + SR_PSP_HI = 0x07, + SR_PSP_LO = 0x09, + SR_PSHTP = 0x0b, + SR_PCSP_HI = 0x0d, + SR_PCSP_LO = 0x0f, + SR_PCSHTP = 0x13, + SR_CTPR1 = 0x15, + SR_CTPR2 = 0x16, + SR_CTPR3 = 0x17, + SR_SBR = 0x1e, + SR_CUTD = 0x21, + SR_EIR = 0x23, + SR_TSD = 0x24, + SR_CUIR = 0x25, + SR_OSCUD_HI = 0x26, + SR_OSCUD_LO = 0x27, + SR_OSGD_HI = 0x28, + SR_OSGD_LO = 0x29, + SR_OSEM = 0x2a, + SR_USD_HI = 0x2c, + SR_USD_LO = 0x2d, + SR_TR = 0x2e, + SR_OSR0 = 0x2f, + SR_CUD_HI = 0x30, + SR_CUD_LO = 0x31, + SR_GD_HI = 0x32, + SR_GD_LO = 0x33, + SR_CS_HI = 0x34, + SR_CS_LO = 0x35, + SR_DS_HI = 0x36, + SR_DS_LO = 0x37, + SR_ES_HI = 0x38, + SR_ES_LO = 0x39, + SR_FS_HI = 0x3a, + SR_FS_LO = 0x3b, + SR_GS_HI = 0x3c, + SR_GS_LO = 0x3d, + SR_SS_HI = 0x3e, + SR_SS_LO = 0x3f, + SR_DIBCR = 0x40, + SR_DIMCR = 0x41, + SR_DIBSR = 0x42, + SR_DTCR = 0x43, + SR_DIBAR0 = 0x48, + SR_DIBAR1 = 0x49, + SR_DIBAR2 = 0x4a, + SR_DIBAR3 = 0x4b, + SR_DIMAR0 = 0x4c, + SR_DIMAR1 = 0x4d, + SR_DTRAF = 0x4e, + SR_DTART = 0x4f, + SR_CR0_HI = 0x51, + SR_CR0_LO = 0x53, + SR_CR1_HI = 0x55, + SR_CR1_LO = 0x57, + SR_SCLKM1 = 0x70, + SR_SCLKM2 = 0x71, + SR_CU_HW0 = 0x78, + SR_UPSR = 0x80, + SR_IP = 0x81, + SR_NIP = 0x82, + SR_LSR = 0x83, + SR_PFPFR = 0x84, + SR_FPCR = 0x85, + SR_FPSR = 0x86, + SR_ILCR = 0x87, + SR_BR = 0x88, + SR_BGR = 0x89, + SR_IDR = 0x8A, + SR_CLKR = 0x90, + SR_RNDPR = 0x91, + SR_SCLKR = 0x92, + SR_TIR_HI = 0x9C, + SR_TIR_LO = 0x9D, + SR_RPR = 0xA0, + SR_SBBP = 0xA1, + SR_RPR_HI = 0xA2, + SR_UPSRM = 0xC0, + SR_LSR1 = 0xC3, + SR_ILCR1 = 0xC7, +} StateReg; + struct e2k_def_t { const char *name; const char *canonical_name; @@ -436,8 +498,11 @@ typedef struct { }; uint64_t hi; }; + /* FIXME: HACK: pointer to tag storage */ target_ulong base_tag; -} E2KStackState, E2KPsState, E2KPcsState; +} E2KPsp; + +#define E2K_PSP_LO_MASK (GEN_MASK(56, 8) | GEN_MASK(0, E2K_VA_SIZE)) typedef struct { int32_t base; @@ -659,22 +724,24 @@ typedef struct { union { uint64_t lo; struct { - uint64_t base: 48; - uint64_t unused1: 10; - uint64_t protected: 1; - uint64_t read: 1; - uint64_t write: 1; - uint64_t unsued2: 3; + uint64_t base : E2K_VA_SIZE; /* [47: 0] */ + uint64_t unused1 : 57 - E2K_VA_MSB; /* [57:48] */ + uint64_t protected : 1; /* [58] */ + uint64_t read : 1; /* [59] */ + uint64_t write : 1; /* [60] */ + uint64_t unsued2 : 3; /* [63:61] */ }; }; union { uint64_t hi; struct { - uint64_t curptr: 32; - uint64_t size: 32; + uint64_t curptr : 32; /* [31: 0] */ + uint64_t size : 32; /* [63:32] */ }; }; -} E2KUserStackDesc; +} E2KRwap; + +#define E2K_RWAP_LO_MASK (GEN_MASK(58, 3) | GEN_MASK(0, E2K_VA_SIZE)) typedef union { struct { @@ -713,33 +780,37 @@ typedef union { } E2KReg; typedef struct CPUArchState { - /* register file */ - uint8_t tags[E2K_REG_COUNT]; /* registers tags */ - E2KReg regs[E2K_REG_COUNT]; /* low parts of registers */ - uint64_t pregs; /* predicate file */ - target_ulong ip; /* instruction address */ - - /* big constant values */ - E2KReg tmp[12]; - /* pre saved registers */ - E2KReg tmp_saved[6]; - /* alops results */ - E2KReg al_result[12]; - - /* DAM */ - E2KDamEntry dam[32]; - - /* Procedure chain info = cr0_lo, cr0_hi, cr1_lo, cr1_hi */ - E2KPcsState pcsp; - - /* Procedure stack pointer (for regs) */ - E2KPsState psp; + /* Registers Tags File */ + uint8_t tags[E2K_REG_COUNT]; + /* Registers File */ + E2KReg regs[E2K_REG_COUNT]; + /* Predicate Registers File */ + uint64_t pregs; + /* Instruction Address */ + target_ulong ip; + /* Next Instruction Address */ + target_ulong nip; + /* Procedure Chain Stack Pointer (control registers) */ + E2KPsp pcsp; + /* Procedure Stack Pointer (window registers) */ + E2KPsp psp; + /* Non-Protected User Stack Pointer */ + E2KRwap usd; + /* Non-Protected User Stack Base address */ + uint64_t sbr; + /* Procedure Registers Window state */ E2KWdState wd; + /* Flag to clear the upper half of the register for 32-bit operations */ + uint32_t wdbl; + /* Based Registers Window state */ E2KBnState bn; + /* Based Predicate Registers Window state */ E2KBpState bp; + /* Based Global Registers Window state */ + uint32_t bgr; - /* loop status register */ + /* Loop Status Register */ uint64_t lsr; uint64_t lsr_lcnt; uint32_t lsr_ecnt; @@ -748,40 +819,84 @@ typedef struct CPUArchState { uint32_t lsr_pcnt; uint32_t lsr_strmd; - uint64_t sbr; - E2KUserStackDesc usd; + /* Initial Loop Counter Register */ + uint32_t ilcr; + uint64_t ilcr_lcnt; - /* control registers */ - E2KCtpr ctprs[3]; // Control Transfer Preparation Register (CTPR) + /* Control Transfer Preparation Register (CTPR) */ + E2KCtpr ctprs[3]; + /* Control Transfer Condition */ target_ulong ct_cond; - - target_ulong nip; /* next instruction address */ - uint64_t upsr; + uint32_t psr; + uint32_t upsr; + uint32_t cuir; + /* System Register */ + uint64_t osr0; uint64_t idr; + uint64_t core_mode; - E2KPfpfr pfpfr; // Packed Floating Point Flag Register (PFPFR) - E2KFpsrState fpsr; // Floating point state register (FPSR) - E2KFpcrState fpcr; // Floating point control register (FPCR) + /* Packed Floating Point Flag Register (PFPFR) */ + E2KPfpfr pfpfr; + /* Floating point state register (FPSR) */ + E2KFpsrState fpsr; + /* Floating point control register (FPCR) */ + E2KFpcrState fpcr; - float_status fp_status; - float_status fx_status; - + /* OS Compilation Unit Descriptor */ + E2KRwap oscud; + /* OS Compilation Unit Globals Descriptor */ + E2KRwap osgd; + + /* User Compilation Unit Descriptor */ + E2KRwap cud; + /* User Compilation Unit Globals Descriptor */ + E2KRwap gd; + + /* Segment Registers */ + E2KRwap cs; + E2KRwap ds; + E2KRwap es; + E2KRwap fs; + E2KRwap gs; + E2KRwap ss; + + /* Array Access Unit State */ E2KAauState aau; + /* DAM */ + E2KDamEntry dam[32]; + + /* + * Internal use + */ + + /* TODO */ int interrupt_index; - /* internal use */ - uint32_t is_bp; /* breakpoint flag */ - uint64_t last_val0; /* ld mas=7 + st mas=2 */ - uint64_t last_val1; /* ld mas=7 + st mas=2 */ + /* 32/64-bit scalar/packed float status */ + float_status fp_status; + /* 80-bit float status */ + float_status fx_status; - /* zeroing upper register half for 32-bit instructions */ - uint32_t wdbl; + /* Temporary storage for big constant values */ + E2KReg tmp[12]; + /* Temporary storage for pre saved registers */ + E2KReg tmp_saved[6]; + /* Temporary storage for empty and temporary results of alops */ + E2KReg al_result[12]; + + /* breakpoint flag */ + uint32_t is_bp; + + /* FIXME: DAM? ld mas=7 + st mas=2 */ + uint64_t last_val0; + uint64_t last_val1; /* Fields up to this point are cleared by a CPU reset */ struct {} end_reset_fields; + /* ISA version */ uint32_t version; /* Force alop to preserve the destination register before writing to it. * Default: false */ @@ -838,8 +953,9 @@ bool e2k_cpu_tlb_fill(CPUState *cpu, vaddr address, int size, bool probe, uintptr_t retaddr); void e2k_update_fp_status(CPUE2KState *env); void e2k_update_fx_status(CPUE2KState *env); -void e2k_pcs_new(E2KPcsState *pcs); -void e2k_ps_new(E2KPsState *ps); +#ifdef CONFIG_USER_ONLY +void e2k_psp_new(E2KPsp *psp, unsigned int size, bool tags); +#endif void e2k_proc_call(CPUE2KState *env, int base, target_ulong ret_ip, bool force_fx); void e2k_proc_return(CPUE2KState *env, bool force_fx); diff --git a/target/e2k/gdbstub.c b/target/e2k/gdbstub.c index e77841bdf8..bd26abd210 100644 --- a/target/e2k/gdbstub.c +++ b/target/e2k/gdbstub.c @@ -52,22 +52,22 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) } switch (n) { - case 35: return gdb_get_reg64(mem_buf, 0); // psr + case 35: return gdb_get_reg64(mem_buf, env->psr); // psr case 36: return gdb_get_reg64(mem_buf, env->upsr); // upsr - case 37: return gdb_get_reg64(mem_buf, 0); // oscud_lo - case 38: return gdb_get_reg64(mem_buf, 0); // oscud_hi - case 39: return gdb_get_reg64(mem_buf, 0); // osgd_lo - case 40: return gdb_get_reg64(mem_buf, 0); // osgd_hi + case 37: return gdb_get_reg64(mem_buf, env->oscud.lo); // oscud_lo + case 38: return gdb_get_reg64(mem_buf, env->oscud.hi); // oscud_hi + case 39: return gdb_get_reg64(mem_buf, env->osgd.lo); // osgd_lo + case 40: return gdb_get_reg64(mem_buf, env->osgd.hi); // osgd_hi case 41: return gdb_get_reg64(mem_buf, 0); // osem - case 42: return gdb_get_reg64(mem_buf, 0); // osr0 - case 43: return gdb_get_reg64(mem_buf, 0); // pfpfr - case 44: return gdb_get_reg64(mem_buf, 0); // fpcr - case 45: return gdb_get_reg64(mem_buf, 0); // fpsr + case 42: return gdb_get_reg64(mem_buf, env->osr0); // osr0 + case 43: return gdb_get_reg64(mem_buf, env->pfpfr.raw); // pfpfr + case 44: return gdb_get_reg64(mem_buf, env->fpcr.raw); // fpcr + case 45: return gdb_get_reg64(mem_buf, env->fpsr.raw); // fpsr case 46: return gdb_get_reg64(mem_buf, 0); // usbr case 47: return gdb_get_reg64(mem_buf, env->usd.lo); // usd_lo case 48: return gdb_get_reg64(mem_buf, env->usd.hi); // usd_hi - case 49: return gdb_get_reg64(mem_buf, env_psp_lo_get(env)); // psp_lo - case 50: return gdb_get_reg64(mem_buf, env_psp_hi_get(env)); // psp_hi + case 49: return gdb_get_reg64(mem_buf, env->psp.lo); // psp_lo + case 50: return gdb_get_reg64(mem_buf, env->psp.hi); // psp_hi case 51: return gdb_get_reg64(mem_buf, 0); // pshtp case 52: return gdb_get_reg64(mem_buf, env->pregs); // pregs case 53: return gdb_get_reg64(mem_buf, env->ip); // ip @@ -80,25 +80,25 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) return gdb_get_reg64(mem_buf, cr1_hi); } case 56: return gdb_get_reg64(mem_buf, 0); // cwd - case 57: return gdb_get_reg64(mem_buf, env_pcsp_lo_get(env)); // pcsp_lo - case 58: return gdb_get_reg64(mem_buf, env_pcsp_hi_get(env)); // pcsp_hi + case 57: return gdb_get_reg64(mem_buf, env->pcsp.lo); // pcsp_lo + case 58: return gdb_get_reg64(mem_buf, env->pcsp.hi); // pcsp_hi case 59: return gdb_get_reg64(mem_buf, 0); // pcshtp - case 60: return gdb_get_reg64(mem_buf, 0); // cud_lo - case 61: return gdb_get_reg64(mem_buf, 0); // cud_hi - case 62: return gdb_get_reg64(mem_buf, 0); // gd_lo - case 63: return gdb_get_reg64(mem_buf, 0); // gd_hi - case 64: return gdb_get_reg64(mem_buf, 0); // cs_lo - case 65: return gdb_get_reg64(mem_buf, 0); // cs_hi - case 66: return gdb_get_reg64(mem_buf, 0); // ds_lo - case 67: return gdb_get_reg64(mem_buf, 0); // ds_hi - case 68: return gdb_get_reg64(mem_buf, 0); // es_lo - case 69: return gdb_get_reg64(mem_buf, 0); // es_hi - case 70: return gdb_get_reg64(mem_buf, 0); // fs_lo - case 71: return gdb_get_reg64(mem_buf, 0); // fs_hi - case 72: return gdb_get_reg64(mem_buf, 0); // gs_lo - case 73: return gdb_get_reg64(mem_buf, 0); // gs_hi - case 74: return gdb_get_reg64(mem_buf, 0); // ss_lo - case 75: return gdb_get_reg64(mem_buf, 0); // ss_hi + case 60: return gdb_get_reg64(mem_buf, env->cud.lo); // cud_lo + case 61: return gdb_get_reg64(mem_buf, env->cud.hi); // cud_hi + case 62: return gdb_get_reg64(mem_buf, env->gd.lo); // gd_lo + case 63: return gdb_get_reg64(mem_buf, env->gd.hi); // gd_hi + case 64: return gdb_get_reg64(mem_buf, env->cs.lo); // cs_lo + case 65: return gdb_get_reg64(mem_buf, env->cs.hi); // cs_hi + case 66: return gdb_get_reg64(mem_buf, env->ds.lo); // ds_lo + case 67: return gdb_get_reg64(mem_buf, env->ds.hi); // ds_hi + case 68: return gdb_get_reg64(mem_buf, env->es.lo); // es_lo + case 69: return gdb_get_reg64(mem_buf, env->es.hi); // es_hi + case 70: return gdb_get_reg64(mem_buf, env->fs.lo); // fs_lo + case 71: return gdb_get_reg64(mem_buf, env->fs.hi); // fs_hi + case 72: return gdb_get_reg64(mem_buf, env->gs.lo); // gs_lo + case 73: return gdb_get_reg64(mem_buf, env->gs.hi); // gs_hi + case 74: return gdb_get_reg64(mem_buf, env->ss.lo); // ss_lo + case 75: return gdb_get_reg64(mem_buf, env->ss.hi); // ss_hi default: break; } @@ -178,9 +178,9 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) case 333: return gdb_get_reg64(mem_buf, 0); // dtart case 334: return gdb_get_reg64(mem_buf, env_wd_get(env)); // wd case 335: return gdb_get_reg64(mem_buf, 0); // unk - case 336: return gdb_get_reg64(mem_buf, 0); // bgr + case 336: return gdb_get_reg64(mem_buf, env->bgr); // bgr case 337: return gdb_get_reg64(mem_buf, 0); // unk - case 338: return gdb_get_reg64(mem_buf, 0); // nip + case 338: return gdb_get_reg64(mem_buf, env->nip); // nip case 339: return gdb_get_reg64(mem_buf, env->ctprs[0].raw); // ctpr1 case 340: return gdb_get_reg64(mem_buf, env->ctprs[1].raw); // ctpr2 case 341: return gdb_get_reg64(mem_buf, env->ctprs[2].raw); // ctpr3 @@ -189,17 +189,8 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) case 344: return gdb_get_reg64(mem_buf, 0); // cutd case 345: return gdb_get_reg64(mem_buf, 0); // cuir case 346: return gdb_get_reg64(mem_buf, 0); // tsd - case 347: { // lsr - uint64_t lsr = env->lsr; - lsr = deposit64(lsr, LSR_LCNT_OFF, LSR_LCNT_LEN, env->lsr_lcnt); - lsr = deposit64(lsr, LSR_ECNT_OFF, LSR_ECNT_LEN, env->lsr_ecnt); - lsr = deposit64(lsr, LSR_VLC_OFF, 1, env->lsr_vlc); - lsr = deposit64(lsr, LSR_OVER_OFF, 1, env->lsr_over); - lsr = deposit64(lsr, LSR_PCNT_OFF, LSR_PCNT_LEN, env->lsr_pcnt); - lsr = deposit64(lsr, LSR_STRMD_OFF, LSR_STRMD_LEN, env->lsr_strmd); - return gdb_get_reg64(mem_buf, lsr); - } - case 348: return gdb_get_reg64(mem_buf, env->lsr & LSR_ILCR_MASK); // ilcr + case 347: return gdb_get_reg64(mem_buf, env_lsr_get(env)); /* lsr */ + case 348: return gdb_get_reg64(mem_buf, env_ilcr_get(env)); /* ilcr */ default: break; } @@ -328,8 +319,8 @@ static int gdb_set_v2(CPUE2KState *env, uint8_t *mem_buf, int n) static int gdb_get_v3(CPUE2KState *env, GByteArray *buf, int n) { if (n == 0) { - /* TODO: core_mode */ - return gdb_get_reg64(buf, 0); + /* core_mode */ + return gdb_get_reg64(buf, env->core_mode); } return 0; @@ -344,13 +335,16 @@ static int gdb_set_v3(CPUE2KState *env, uint8_t *mem_buf, int n) static int gdb_get_v5(CPUE2KState *env, GByteArray *buf, int n) { if (n == 0) { + /* lsr1 */ return gdb_get_reg64(buf, env->lsr_lcnt); } else if (n == 1) { - // TODO: ilcr1 - return gdb_get_reg64(buf, 0); + /* ilcr1 */ + return gdb_get_reg64(buf, env->ilcr_lcnt); } else if (n >= 2 && n < 34) { + /* xgN (upper 64-bit) */ return gdb_get_reg64(buf, env->regs[E2K_NR_COUNT + n - 2].hi); } else if (n >= 34 && n < 66) { + /* qpgN tags */ return gdb_get_reg8(buf, env->tags[E2K_NR_COUNT + n - 34]); } diff --git a/target/e2k/helper-tcg.h b/target/e2k/helper-tcg.h index 424a6587c4..7c9a768620 100644 --- a/target/e2k/helper-tcg.h +++ b/target/e2k/helper-tcg.h @@ -35,37 +35,10 @@ #define ident(x) (x) /* helper.c */ -void G_NORETURN raise_exception(CPUE2KState *env, int exception_index); -void G_NORETURN raise_exception_ra(CPUE2KState *env, int exception_index, +void G_NORETURN raise_exception(CPUE2KState *desc, int exception_index); +void G_NORETURN raise_exception_ra(CPUE2KState *desc, int exception_index, uintptr_t retaddr); -static inline uint64_t stack_desc_lo(E2KStackState *desc) -{ - uint64_t lo = 0; - - lo = deposit64(lo, DESC_LO_BASE_OFF, DESC_LO_BASE_LEN, - (uint64_t) desc->base); - lo = deposit64(lo, DESC_LO_READ_OFF, 1, desc->is_readable); - lo = deposit64(lo, DESC_LO_WRITE_OFF, 1, desc->is_writable); - - return lo; -} - -static inline uint64_t stack_desc_hi(E2KStackState *env) -{ - uint64_t hi = 0; - - hi = deposit64(hi, DESC_HI_IND_OFF, DESC_HI_IND_LEN, env->index); - hi = deposit64(hi, DESC_HI_SIZE_OFF, DESC_HI_SIZE_OFF, env->size); - - return hi; -} - -#define env_pcsp_lo_get(env) stack_desc_lo(&(env)->pcsp) -#define env_pcsp_hi_get(env) stack_desc_hi(&(env)->pcsp) -#define env_psp_lo_get(env) stack_desc_lo(&(env)->psp) -#define env_psp_hi_get(env) stack_desc_hi(&(env)->psp) - static inline uint64_t env_wd_get(CPUE2KState *env) { E2KWdState *wd = &env->wd; @@ -137,4 +110,35 @@ static inline void env_lsr_set(CPUE2KState *env, uint64_t val) env->lsr_strmd = extract64(val, LSR_STRMD_OFF, LSR_STRMD_LEN); } +static inline uint64_t env_ilcr_get(CPUE2KState *env) +{ + return ((uint64_t) env->ilcr << LSR_ECNT_OFF) + | (env->ilcr_lcnt & GEN_MASK(0, LSR_LCNT_LEN)); +} + +static inline void env_ilcr_set(CPUE2KState *env, uint64_t value) +{ + env->ilcr = (value >> LSR_ECNT_OFF) & ILCR_MASK; + env->ilcr_lcnt = value & GEN_MASK(0, LSR_LCNT_LEN); +} + +static inline uint64_t env_usd_lo_get(CPUE2KState *env) +{ + uint64_t r = 0; + + r = deposit64(r, USD_LO_BASE_OFF, USD_LO_BASE_LEN, env->usd.base); + r |= env->usd.protected ? USD_LO_PROTECTED_BIT : 0; + r |= env->usd.read ? USD_LO_READ_BIT : 0; + r |= env->usd.write ? USD_LO_WRITE_BIT : 0; + return r; +} + +static inline void env_usd_lo_set(CPUE2KState *env, uint64_t value) +{ + env->usd.base = extract64(value, USD_LO_BASE_OFF, USD_LO_BASE_LEN); + env->usd.protected = (value & USD_LO_PROTECTED_BIT) != 0; + env->usd.read = (value & USD_LO_READ_BIT) != 0; + env->usd.write = (value & USD_LO_WRITE_BIT) != 0; +} + #endif /* E2K_HELPER_TCG_H */ diff --git a/target/e2k/helper.c b/target/e2k/helper.c index 7c4f12454b..4c882fc7a9 100644 --- a/target/e2k/helper.c +++ b/target/e2k/helper.c @@ -165,6 +165,8 @@ void e2k_proc_call(CPUE2KState *env, int base, target_ulong ret_ip, crs.cr1.wpsz = env->wd.psize / 2; crs.cr1.wfx = env->wd.fx; crs.cr1.wdbl = env->wdbl; + crs.cr1.psr = env->psr; + crs.cr1.cuir = env->cuir; crs.cr1.br = env_br_get(env); crs.cr1.ussz = env->usd.size >> 4; @@ -189,6 +191,8 @@ void e2k_proc_return(CPUE2KState *env, bool force_fx) env->pregs = crs.cr0_lo; env->ip = crs.cr0_hi & ~7; env_br_set(env, crs.cr1.br); + env->cuir = crs.cr1.cuir; + env->psr = crs.cr1.psr; env->wd.size = env->wd.psize + base; env->wd.psize = crs.cr1.wpsz * 2; env->wd.fx = crs.cr1.wfx; diff --git a/target/e2k/helper.h b/target/e2k/helper.h index e14c322242..27f22be8c7 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -30,9 +30,8 @@ DEF_HELPER_4(dam_unlock_addr, int, env, i64, int, int) DEF_HELPER_2(getsp, i64, env, i32) -DEF_HELPER_FLAGS_2(rrd, TCG_CALL_NO_WG_SE, i64, env, int) -DEF_HELPER_3(rwd, void, env, int, i64) -DEF_HELPER_3(rws, void, env, int, i32) +DEF_HELPER_FLAGS_2(state_reg_get, TCG_CALL_NO_WG_SE, i64, env, int) +DEF_HELPER_3(state_reg_set, void, env, i64, int) DEF_HELPER_FLAGS_2(sxt, TCG_CALL_NO_RWG_SE, i64, i32, i32) DEF_HELPER_FLAGS_2(clmull, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target/e2k/helper_int.c b/target/e2k/helper_int.c index 31c3c5de17..0a51237134 100644 --- a/target/e2k/helper_int.c +++ b/target/e2k/helper_int.c @@ -19,83 +19,283 @@ static uint64_t cr_read(CPUE2KState *env, size_t offset) return cpu_ldq_le_data(env, addr); } -uint64_t HELPER(rrd)(CPUE2KState *env, int idx) +uint64_t HELPER(state_reg_get)(CPUE2KState *env, int index) { - switch (idx) { - case 0x01: return env_wd_get(env); /* %wd */ - case 0x07: return env_psp_hi_get(env); /* %psp.hi */ - case 0x09: return env_psp_lo_get(env); /* %psp.lo */ - case 0x0d: return env_pcsp_hi_get(env); /* %pcsp.hi */ - case 0x0f: return env_pcsp_lo_get(env); /* %pcsp.lo */ - case 0x13: return 0; /* %pcshtp */ - case 0x2c: return env->usd.hi; /* %usd.hi */ - case 0x2d: return env->usd.lo; /* %usd.lo */ - case 0x51: return cr_read(env, offsetof(E2KCrs, cr0_hi)); /* %cr0.hi */ - case 0x53: return cr_read(env, offsetof(E2KCrs, cr0_lo)); /* %cr0.lo */ - case 0x55: return cr_read(env, offsetof(E2KCrs, cr1.hi)); /* %cr1.hi */ - case 0x57: return cr_read(env, offsetof(E2KCrs, cr1.lo)); /* %cr1.lo */ - case 0x80: return env->upsr; /* %upsr */ - case 0x81: return env->ip; /* %ip */ - case 0x83: return env_lsr_get(env); /* %lsr */ - case 0x84: return env->pfpfr.raw; /* %pfpfr */ - case 0x85: return env->fpcr.raw; /* %fpcr */ - case 0x86: return env->fpsr.raw; /* %fpsr */ - case 0x8a: return env->idr; /* %idr */ - case 0x90: return cpu_get_host_ticks(); /* %clkr */ - case 0xc3: return env->lsr_lcnt; /* %lsr1 */ + switch (index) { + case SR_PSR: return env->psr; + case SR_WD: return env_wd_get(env); + case SR_CORE_MODE: return env->core_mode; + case SR_CWD: return 0; /* ignore */ + case SR_PSP_HI: return env->psp.hi; + case SR_PSP_LO: return env->psp.lo; + case SR_PSHTP: return 0; /* ignore */ + case SR_PCSP_HI: return env->pcsp.hi; + case SR_PCSP_LO: return env->pcsp.lo; + case SR_PCSHTP: return 0; /* ignore */ + case SR_CTPR1: return env->ctprs[0].raw; + case SR_CTPR2: return env->ctprs[1].raw; + case SR_CTPR3: return env->ctprs[2].raw; + case SR_SBR: return env->sbr; + case SR_CUTD: + case SR_EIR: + case SR_TSD: goto todo; + case SR_CUIR: return env->cuir; + case SR_OSCUD_HI: return env->oscud.hi; + case SR_OSCUD_LO: return env->oscud.lo; + case SR_OSGD_HI: return env->osgd.hi; + case SR_OSGD_LO: return env->osgd.lo; + case SR_OSEM: goto todo; + case SR_USD_HI: return env->usd.hi; + case SR_USD_LO: return env->usd.lo; + case SR_TR: goto todo; + case SR_OSR0: return env->osr0; + case SR_CUD_HI: return env->cud.hi; + case SR_CUD_LO: return env->cud.lo; + case SR_GD_HI: return env->gd.hi; + case SR_GD_LO: return env->gd.lo; + case SR_CS_HI: return env->cs.hi; + case SR_CS_LO: return env->cs.lo; + case SR_DS_HI: return env->ds.hi; + case SR_DS_LO: return env->ds.lo; + case SR_ES_HI: return env->es.hi; + case SR_ES_LO: return env->es.lo; + case SR_FS_HI: return env->fs.hi; + case SR_FS_LO: return env->fs.lo; + case SR_GS_HI: return env->gs.hi; + case SR_GS_LO: return env->gs.lo; + case SR_SS_HI: return env->ss.hi; + case SR_SS_LO: return env->ss.lo; + case SR_DIBCR: + case SR_DIMCR: + case SR_DIBSR: + case SR_DTCR: + case SR_DIBAR0: + case SR_DIBAR1: + case SR_DIBAR2: + case SR_DIBAR3: + case SR_DIMAR0: + case SR_DIMAR1: + case SR_DTRAF: + case SR_DTART: goto todo; + case SR_CR0_HI: return cr_read(env, offsetof(E2KCrs, cr0_hi)); + case SR_CR0_LO: return cr_read(env, offsetof(E2KCrs, cr0_lo)); + case SR_CR1_HI: return cr_read(env, offsetof(E2KCrs, cr1.hi)); + case SR_CR1_LO: return cr_read(env, offsetof(E2KCrs, cr1.lo)); + case SR_SCLKM1: + case SR_SCLKM2: + case SR_CU_HW0: goto todo; + case SR_UPSR: return env->upsr; + case SR_IP: return env->ip; + case SR_NIP: return env->nip; + case SR_LSR: return env_lsr_get(env); + case SR_PFPFR: return env->pfpfr.raw; + case SR_FPCR: return env->fpcr.raw; + case SR_FPSR: return env->fpsr.raw; + case SR_ILCR: return env_ilcr_get(env); + case SR_BR: return env_br_get(env); + case SR_BGR: return env->bgr; + case SR_IDR: return env->idr; + case SR_CLKR: return cpu_get_host_ticks(); // FIXME + case SR_RNDPR: + case SR_SCLKR: + case SR_TIR_HI: + case SR_TIR_LO: + case SR_RPR: + case SR_SBBP: + case SR_RPR_HI: + case SR_UPSRM: goto todo; + case SR_LSR1: return env->lsr_lcnt; + case SR_ILCR1: return env->ilcr_lcnt; default: - qemu_log_mask(LOG_UNIMP, "read unknown state register 0x%x\n", idx); - return 0; + /* The index is checked during translation. */ + g_assert_not_reached(); + break; } + +todo: + qemu_log("reading a state register %#x is not implemented\n", index); + return 0; } -void HELPER(rwd)(CPUE2KState *env, int idx, uint64_t val) -{ - switch(idx) { - case 0x80: /* %upsr */ - env->upsr = val; +#define CASE_RWAP_SET(e, f) \ + case glue(e, _HI): \ + env->f.hi = value; \ + break; \ + case glue(e, _LO): \ + env->f.lo = value & E2K_RWAP_LO_MASK; \ break; - case 0x83: /* %lsr */ - env_lsr_set(env, val); - break; - case 0x84: /* %pfpfr */ - env->pfpfr.raw = val; - e2k_update_fp_status(env); - break; - case 0x85: /* %fpcr */ - env->fpcr.raw = val; - e2k_update_fx_status(env); - break; - case 0x86: env->fpsr.raw = val; break; /* %fpsr */ - case 0xc3: env->lsr_lcnt = val; break; /* %lsr1 */ - default: - qemu_log_mask(LOG_UNIMP, "rwd unknown state register 0x%x\n", idx); - break; - } -} -void HELPER(rws)(CPUE2KState *env, int idx, uint32_t val) +void HELPER(state_reg_set)(CPUE2KState *env, uint64_t value, int index) { - switch (idx) { - case 0x80: /* %upsr */ - env->upsr = deposit64(env->upsr, 0, 32, val); + switch (index) { + case SR_UPSR: + case SR_LSR: + case SR_ILCR: + case SR_PFPFR: + case SR_FPCR: + case SR_FPSR: + case SR_SCLKR: + case SR_TIR_HI: + case SR_TIR_LO: + case SR_RPR: + case SR_SBBP: + case SR_RPR_HI: + case SR_UPSRM: + case SR_LSR1: + case SR_ILCR1: break; - case 0x83: /* %lsr */ - env->lsr_lcnt = val; + case SR_CUIR: + raise_exception(env, EXCP_ILLEGAL_OPCODE); /* FIXME */ break; - case 0x84: /* %pfpfr */ - env->pfpfr.raw = val; - e2k_update_fp_status(env); - break; - case 0x85: /* %fpcr */ - env->fpcr.raw = val; - e2k_update_fx_status(env); - break; - case 0x86: env->fpsr.raw = val; break; /* %fpsr */ default: - qemu_log_mask(LOG_UNIMP, "rws unknown state register 0x%x\n", idx); + if ((env->psr & PSR_PM) == 0) { + raise_exception(env, EXCP_PRIV_ACTION); + } break; } + + switch (index) { + case SR_PSR: + env->psr = value & PSR_MASK; + break; + case SR_WD: + env_wd_set(env, value); + break; + case SR_CORE_MODE: + // FIXME: core_mode + qemu_log("FIXME: core_mode is set to %#lx\n", value); + env->core_mode = value; + break; + case SR_CWD: + /* ignore */ + break; + case SR_PSP_HI: + env->psp.hi = value; + break; + case SR_PSP_LO: + env->psp.lo = value & E2K_PSP_LO_MASK; + break; + case SR_PSHTP: + /* ignore */ + break; + case SR_PCSP_HI: + env->pcsp.hi = value; + break; + case SR_PCSP_LO: + env->pcsp.lo = value & E2K_PSP_LO_MASK; + break; + case SR_PCSHTP: + /* ignore */ + break; + case SR_CTPR1: + env->ctprs[0].raw = value; + break; + case SR_CTPR2: + env->ctprs[1].raw = value; + break; + case SR_CTPR3: + env->ctprs[2].raw = value; + break; + case SR_SBR: + env->sbr = value; + break; + case SR_CUTD: + case SR_EIR: + case SR_TSD: + goto todo; + case SR_CUIR: + env->cuir = value & CUIR_MASK; + break; + case SR_OSEM: + case SR_TR: + goto todo; + case SR_OSR0: + env->osr0 = value; + break; + CASE_RWAP_SET(SR_OSCUD, oscud) + CASE_RWAP_SET(SR_OSGD, osgd) + CASE_RWAP_SET(SR_USD, usd) + CASE_RWAP_SET(SR_CUD, cud) + CASE_RWAP_SET(SR_GD, gd) + CASE_RWAP_SET(SR_CS, cs) + CASE_RWAP_SET(SR_DS, ds) + CASE_RWAP_SET(SR_ES, es) + CASE_RWAP_SET(SR_FS, fs) + CASE_RWAP_SET(SR_GS, gs) + CASE_RWAP_SET(SR_SS, ss) + case SR_DIBCR: + case SR_DIMCR: + case SR_DIBSR: + case SR_DTCR: + case SR_DIBAR0: + case SR_DIBAR1: + case SR_DIBAR2: + case SR_DIBAR3: + case SR_DIMAR0: + case SR_DIMAR1: + case SR_DTRAF: + case SR_DTART: + case SR_CR0_HI: + case SR_CR0_LO: + case SR_CR1_HI: + case SR_CR1_LO: + case SR_SCLKM1: + case SR_SCLKM2: + case SR_CU_HW0: + goto todo; + case SR_UPSR: + env->upsr = value & UPSR_MASK; + break; + case SR_LSR: + env_lsr_set(env, value); + env_ilcr_set(env, value); + break; + case SR_PFPFR: + env->pfpfr.raw = value; + e2k_update_fp_status(env); + break; + case SR_FPCR: + env->fpcr.raw = value; + e2k_update_fx_status(env); + break; + case SR_FPSR: + env->fpsr.raw = value; + break; + case SR_ILCR: + env->ilcr = (value >> LSR_ECNT_OFF) & ILCR_MASK; + env->ilcr_lcnt = value & GEN_MASK(0, LSR_LCNT_LEN); + break; + case SR_BR: + env_br_set(env, value); + break; + case SR_BGR: + env->bgr = value & BGR_MASK; + break; + case SR_RNDPR: + case SR_SCLKR: + case SR_TIR_HI: + case SR_TIR_LO: + case SR_RPR: + case SR_SBBP: + case SR_RPR_HI: + case SR_UPSRM: + goto todo; + case SR_LSR1: + env->lsr_lcnt = value; + env->ilcr_lcnt = value; + break; + case SR_ILCR1: + env->ilcr_lcnt = value; + break; + default: + /* The index is checked during translation. */ + g_assert_not_reached(); + break; + } + + return; +todo: + qemu_log("write to state register %#x is not implemented\n", index); } uint64_t HELPER(getsp)(CPUE2KState *env, uint32_t src2) diff --git a/target/e2k/translate.c b/target/e2k/translate.c index f26dbee569..b67844f3d7 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -3505,9 +3505,8 @@ static void gen_rrd(Alop *alop) Tagged_i64 r = tagged_new_i64(); TCGv_i32 t0 = tcg_const_i32(alop->als.src1); - // TODO: check version gen_save_cpu_state(alop->ctx); - gen_helper_rrd(r.val, cpu_env, t0); + gen_helper_state_reg_get(r.val, cpu_env, t0); tcg_gen_movi_i32(r.tag, 0); gen_al_result_d(alop, r); @@ -3515,22 +3514,36 @@ static void gen_rrd(Alop *alop) tagged_free_i64(r); } -#define IMPL_GEN_RW(name, S, helper) \ - static void name(Alop *alop) \ - { \ - tagged(S) b = tagged_new(S); \ - TCGv_i32 t0 = tcg_const_i32(alop->als.dst); \ - \ - /* TODO: check version */ \ - gen_tagged_src(2, S, alop, b); \ - helper(cpu_env, t0, b.val); \ - \ - tcg_temp_free_i32(t0); \ - tagged_free(S, b); \ - } +static inline void gen_state_reg_write(Alop *alop, TCGv_i64 value) +{ + TCGv_i32 t0 = tcg_const_i32(alop->als.dst); -IMPL_GEN_RW(gen_rwd, d, gen_helper_rwd) -IMPL_GEN_RW(gen_rws, s, gen_helper_rws) + gen_helper_state_reg_set(cpu_env, value, t0); + tcg_temp_free_i32(t0); +} + +static void gen_rws(Alop *alop) +{ + Tagged_i32 s2 = tagged_new_i32(); + TCGv_i64 t0 = tcg_temp_new_i64(); + + gen_tagged_src2_s(alop, s2); + gen_delayed_alop_tag_check(alop, s2.tag); + tcg_gen_extu_i32_i64(t0, s2.val); + gen_state_reg_write(alop, t0); + tcg_temp_free_i64(t0); + tagged_free_i32(s2); +} + +static void gen_rwd(Alop *alop) +{ + Tagged_i64 s2 = tagged_new_i64(); + + gen_tagged_src2_d(alop, s2); + gen_delayed_alop_tag_check(alop, s2.tag); + gen_state_reg_write(alop, s2.val); + tagged_free_i64(s2); +} #define IMPL_GEN_MOV(name, S, code) \ static void name(Alop *alop) \ @@ -7660,7 +7673,7 @@ static void gen_stubs(DisasContext *ctx) } } -static inline target_ulong do_decode(DisasContext *ctx, CPUState *cs) +static target_ulong do_decode(DisasContext *ctx, CPUState *cs) { E2KCPU *cpu = E2K_CPU(cs); CPUE2KState *env = &cpu->env; @@ -7682,6 +7695,127 @@ static inline target_ulong do_decode(DisasContext *ctx, CPUState *cs) return ctx->pc + len; } +static bool validate_state_reg(DisasContext *ctx, int index, bool write) +{ + switch (index) { + case SR_PSR: + case SR_WD: + case SR_CWD: + case SR_PSP_HI: + case SR_PSP_LO: + case SR_PSHTP: + case SR_PCSP_HI: + case SR_PCSP_LO: + case SR_PCSHTP: + case SR_CTPR1: + case SR_CTPR2: + case SR_CTPR3: + case SR_SBR: + case SR_CUTD: + case SR_CUIR: + case SR_OSCUD_HI: + case SR_OSCUD_LO: + case SR_OSGD_HI: + case SR_OSGD_LO: + case SR_OSEM: + case SR_USD_HI: + case SR_USD_LO: + case SR_OSR0: + case SR_CUD_HI: + case SR_CUD_LO: + case SR_GD_HI: + case SR_GD_LO: + case SR_CS_HI: + case SR_CS_LO: + case SR_DS_HI: + case SR_DS_LO: + case SR_ES_HI: + case SR_ES_LO: + case SR_FS_HI: + case SR_FS_LO: + case SR_GS_HI: + case SR_GS_LO: + case SR_SS_HI: + case SR_SS_LO: + case SR_DIBCR: + case SR_DIMCR: + case SR_DIBSR: + case SR_DTCR: + case SR_DIBAR0: + case SR_DIBAR1: + case SR_DIBAR2: + case SR_DIBAR3: + case SR_DIMAR0: + case SR_DIMAR1: + case SR_DTRAF: + case SR_DTART: + case SR_CR0_HI: + case SR_CR0_LO: + case SR_CR1_HI: + case SR_CR1_LO: + case SR_SCLKM1: + case SR_SCLKM2: + case SR_CU_HW0: + case SR_UPSR: + case SR_NIP: + case SR_LSR: + case SR_PFPFR: + case SR_FPCR: + case SR_FPSR: + case SR_ILCR: + case SR_BR: + case SR_BGR: + case SR_CLKR: + case SR_RNDPR: + case SR_SCLKR: + case SR_TIR_HI: + case SR_TIR_LO: + case SR_RPR: + case SR_SBBP: + case SR_RPR_HI: + case SR_UPSRM: + return true; + case SR_IDR: + case SR_IP: + return !write; + case SR_EIR: + case SR_TSD: + case SR_TR: + return false; /* FIXME */ + case SR_CORE_MODE: + return ctx->version >= 3; + case SR_LSR1: + case SR_ILCR1: + return ctx->version >= 5; + default: + return false; + } +} + +static void validate_bundle(DisasContext *ctx) +{ + int i; + + for (i = 0; i < 6; i++) { + Alop *alop = &ctx->alops[i]; + + switch (alop->format) { + case ALOPF15: + if (!validate_state_reg(ctx, alop->als.dst, true)) { + gen_tr_excp_illopc(alop->ctx); + } + break; + case ALOPF16: + if (!validate_state_reg(ctx, alop->als.src2, false)) { + gen_tr_excp_illopc(alop->ctx); + } + break; + default: + break; + } + } +} + static inline void gen_window_bounds_checki_i32(TCGCond cond, TCGv_i32 arg1, int arg2) { @@ -7964,6 +8098,7 @@ static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs) #endif /* CONFIG_USER_ONLY */ ctx->loop_mode = (ctx->bundle.hs & (1 << 10)) != 0; + validate_bundle(ctx); gen_alop_reg_indices_check(ctx); gen_setwd(ctx); gen_cs0(ctx);