e2k: Update get/set state regs.

Signed-off-by: Denis Drakhnya <numas13@gmail.com>
This commit is contained in:
Denis Drakhnia 2021-03-29 19:25:50 +03:00 committed by Denis Drakhnia
parent 21ff5cbef9
commit 48290cb80c
14 changed files with 796 additions and 345 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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(&regs->pcsp);
e2k_ps_new(&regs->psp);
e2k_psp_new(&regs->pcsp, E2K_DEFAULT_PCS_SIZE, false);
e2k_psp_new(&regs->psp, E2K_DEFAULT_PS_SIZE, true);
}
static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUE2KState *env)

View File

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

View File

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

View File

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

View File

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

View File

@ -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 */

View File

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

View File

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

View File

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

View File

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