#ifndef E2K_CPU_H #define E2K_CPU_H #include "qemu/bswap.h" #include "cpu-qom.h" #include "exec/cpu-defs.h" #include "fpu/softfloat.h" void e2k_tcg_initialize(void); /* a1ba: fsqrtid, fxsqrtixx, fxsqrtuxx are instructions that * calculate intermediate square root * I don't think the results of these instructions are meant to be used * somewhere else than final square root instruction (fsqrttd, fxsqrttxx) * Correctly emulating that instruction may impact performance * * Uncomment this macro to have correct implementation, * or left as is to just copy values */ /* #define TARGET_E2K_PRECISE_FSQRTID */ /* FIXME: nfx window mode * numas13: I don't know why elbrus always spill/fill in fx mode. * If we enable 'nfx' mode It will break "finish" command in gdb because * it will try to read registers from hell. */ #define E2K_FORCE_FX true #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) #define E2K_REG_SIZE (E2K_REG_LEN * 8) #define E2K_TAG_MASK_32 0x03 #define E2K_TAG_MASK_64 0x0f #define E2K_TAG_MASK_80 E2K_TAG_MASK_64 #define E2K_TAG_MASK_128 0xff #define E2K_WR_COUNT 64 /* %rN [0, 64) */ #define E2K_BR_COUNT 128 /* %b[N] [0, 128) */ #define E2K_NR_COUNT 224 #define E2K_GR_COUNT 32 /* %gN [0, 32) */ #define E2K_BGR_COUNT 8 /* %gN [24, 32) */ #define E2K_REG_COUNT (E2K_NR_COUNT + E2K_GR_COUNT) #define E2K_TLS_REG (E2K_NR_COUNT + 13) #define E2K_PR_COUNT 32 /* %predN [0, 32) */ typedef enum { E2K_TAG_NUMBER32 = 0, E2K_TAG_NUMBER64 = 0, E2K_TAG_NUMBER80 = 0, E2K_TAG_NUMBER128 = 0, E2K_TAG_NON_NUMBER32 = 0x01, E2K_TAG_NON_NUMBER64 = 0x05, E2K_TAG_NON_NUMBER80 = 0x05, E2K_TAG_NON_NUMBER128 = 0x55, } E2kRegisterTag; #define E2K_MOVA_RESULT_INVALID 0xeaed0f70eaed0f70 #define E2K_LD_RESULT_INVALID 0x4afafafa4afafafa #define CRS_SIZE (sizeof(E2KCrs)) #define CTPR_BASE_OFF 0 #define CTPR_BASE_END 47 #define CTPR_BASE_LEN (CTPR_BASE_END - CTPR_BASE_OFF + 1) #define CTPR_TAG_OFF 54 #define CTPR_TAG_END 56 #define CTPR_TAG_LEN (CTPR_TAG_END - CTPR_TAG_OFF + 1) #define CTPR_OPC_OFF 57 #define CTPR_OPC_END 58 #define CTPR_OPC_LEN (CTPR_OPC_END - CTPR_OPC_OFF + 1) #define CTPR_IPD_OFF 59 #define CTPR_IPD_END 60 #define CTPR_IPD_LEN (CTPR_IPD_END - CTPR_IPD_OFF + 1) typedef enum { CTPR_TAG_NONE = 0x0, CTPR_TAG_RETURN = 0x2, CTPR_TAG_DISP = 0x3, CTPR_TAG_SDISP = 0x5, } CtprTag; typedef enum { CTPR_OPC_DISP = 0x0, CTPR_OPC_LDISP = 0x1, CTPR_OPC_SIGRET = 0x3, } CtprOpc; #ifdef CONFIG_USER_ONLY # define E2K_SYSCALL_MAX_ARGS 10 /* fake kernel addresses */ # if TARGET_LONG_BITS == 64 # define E2K_FAKE_KERN_START 0xe20000000000 # define E2K_FAKE_KERN_END 0xe30000000000 # else /* TARGET_LONG_BITS == 32 */ # define E2K_FAKE_KERN_START 0xe0000000 # define E2K_FAKE_KERN_END 0xe3000000 # endif # define E2K_SYSCALL_ADDR1 (E2K_FAKE_KERN_START + 0x800 * 1) # define E2K_SYSCALL_ADDR3 (E2K_FAKE_KERN_START + 0x800 * 3) # define E2K_SYSCALL_ADDR4 (E2K_FAKE_KERN_START + 0x800 * 4) # define E2K_SYSCALL_ADDR6 (E2K_FAKE_KERN_START + 0x800 * 6) # define E2K_SYSRET_ADDR (E2K_FAKE_KERN_START + 0x15700) # define E2K_SIGRET_ADDR (E2K_FAKE_KERN_START + 0x15800) # define E2K_SYSRET_BACKTRACE_ADDR (E2K_FAKE_KERN_START + 0x15900) #endif #define WD_BASE_OFF 0 #define WD_BASE_END 10 #define WD_BASE_LEN (WD_BASE_END - WD_BASE_OFF + 1) #define WD_SIZE_OFF 16 #define WD_SIZE_END 26 #define WD_SIZE_LEN (WD_SIZE_END - WD_SIZE_OFF + 1) #define WD_PSIZE_OFF 32 #define WD_PSIZE_END 42 #define WD_PSIZE_LEN (WD_PSIZE_END - WD_PSIZE_OFF + 1) #define WD_FX_OFF 48 #define WD_FX_BIT (1UL << WD_FX_OFF) #define DESC_HI_IND_OFF 0 /* index for SPILL */ #define DESC_HI_IND_END 31 #define DESC_HI_IND_LEN (DESC_HI_IND_END - DESC_HI_IND_OFF + 1) #define DESC_HI_SIZE_OFF 32 /* stack size */ #define DESC_HI_SIZE_END 63 #define DESC_HI_SIZE_LEN (DESC_HI_SIZE_END - DESC_HI_SIZE_OFF + 1) #define DESC_LO_BASE_OFF 0 /* stack address */ #define DESC_LO_BASE_END 47 #define DESC_LO_BASE_LEN (DESC_LO_BASE_END - DESC_LO_BASE_OFF + 1) #define DESC_LO_READ_OFF 59 #define DESC_LO_READ_BIT (1UL << DESC_LO_READ_OFF) #define DESC_LO_WRITE_OFF 60 #define DESC_LO_WRITE_BIT (1UL << DESC_LO_WRITE_OFF) #define USD_LO_BASE_OFF 0 #define USD_LO_BASE_LEN 48 #define USD_LO_PROTECTED_OFF 58 #define USD_LO_PROTECTED_BIT (1ULL << USD_LO_PROTECTED_OFF) #define USD_LO_READ_OFF 59 #define USD_LO_READ_BIT (1ULL << USD_LO_READ_OFF) #define USD_LO_WRITE_OFF 60 #define USD_LO_WRITE_BIT (1ULL << USD_LO_WRITE_OFF) #define USD_HI_CURPTR_OFF 0 #define USD_HI_CURPTR_LEN 32 #define USD_HI_SIZE_OFF 32 #define USD_HI_SIZE_LEN 32 #define CR1_HI_BR_OFF 0 #define CR1_HI_BR_LEN 28 #define CR1_HI_WDBL_OFF 35 #define CR1_HI_WDBL_BIT (1ULL << CR1_HI_WDBL_OFF) #define CR1_HI_USSZ_OFF 36 #define CR1_HI_USSZ_LEN 28 #define CR1_LO_TR_OFF 0 #define CR1_LO_TR_LEN 15 #define CR1_LO_EIN_OFF 16 #define CR1_LO_EIN_LEN 8 #define CR1_LO_SS_OFF 24 #define CR1_LO_SS_BIT (1ULL << CR1_LO_SS_OFF) #define CR1_LO_WFX_OFF 25 #define CR1_LO_WFX_BIT (1ULL << CR1_LO_WFX_OFF) #define CR1_LO_WPSZ_OFF 26 #define CR1_LO_WPSZ_LEN 7 #define CR1_LO_WBS_OFF 33 #define CR1_LO_WBS_LEN 7 #define CR1_LO_CUIR_OFF 40 #define CR1_LO_CUIR_LEN 17 #define CR1_LO_PSR_OFF 57 #define CR1_LO_PSR_LEN 7 #define BR_RBS_OFF 0 /* based regs window offset */ #define BR_RBS_LEN 6 #define BR_RSZ_OFF 6 /* based regs window size */ #define BR_RSZ_LEN 6 #define BR_RCUR_OFF 12 /* based regs current index */ #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_LEN 5 #define BR_PCUR_OFF 23 /* based pregs current index */ #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_LEN 32 #define LSR_ECNT_OFF 32 /* epilogue counter */ #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_LEN 8 #define LSR_PCNT_OFF 48 /* prologue counter */ #define LSR_PCNT_LEN 5 #define LSR_STRMD_OFF 53 /* store remainder counter */ #define LSR_STRMD_LEN 7 #define LSR_SEMC_OFF 60 /* side effects manual control */ #define ILCR_MASK 0x1f001f #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 #define IDR_MDL_LEN (IDR_MDL_END - IDR_MDL_OFF + 1) #define IDR_REV_OFF 8 /* revision number */ #define IDR_REV_END 11 #define IDR_REV_LEN (IDR_REV_END - IDR_REV_OFF + 1) #define IDR_WBL_OFF 12 /* write-back length of L2 */ #define IDR_WBL_END 14 #define IDR_WBL_LEN (IDR_WBL_END - IDR_WBL_OFF + 1) #define IDR_MS_OFF 15 /* model specific info */ #define IDR_MS_END 63 #define IDR_MS_LEN (IDR_MS_END - IDR_MS_OFF + 1) /* Cache write-back length */ #define IDR_WBL_0 0x0 /* none CPU internal cache */ #define IDR_WBL_32 0x1 #define IDR_WBL_64 0x2 #define IDR_WBL_128 0x3 #define IDR_WBL_256 0x4 #define IDR_WBL_TO_BYTES(wbl) ((wbl) ? (1 << ((wbs) + 4)) : 1) typedef enum { EXCP_ILLEGAL_OPCODE = 0, EXCP_PRIV_ACTION = 1, EXCP_FP_DISABLED = 2, EXCP_FP_STACK_U = 3, EXCP_D_INTERRUPT = 4, EXCP_DIAG_CT_COND = 5, EXCP_DIAG_INSTR_ADDR = 6, EXCP_ILLEGAL_INSTR_ADDR = 7, EXCP_INSTR_DEBUG = 8, EXCP_WINDOW_BOUNDS = 9, EXCP_USER_STACK_BOUNDS = 10, EXCP_PROC_STACK_BOUNDS = 11, EXCP_CHAIN_STACK_BOUNDS = 12, EXCP_FP_STACK_O = 13, EXCP_DIAG_COND = 14, EXCP_DIAG_OPERAND = 15, EXCP_ILLEGAL_OPERAND = 16, EXCP_ARRAY_BOUNDS = 17, EXCP_ACCESS_RIGHTS = 18, EXCP_ADDR_NOT_ALIGNED = 19, EXCP_INSTR_PAGE_MISS = 20, EXCP_INSTR_PAGE_PROT = 21, EXCP_AINSTR_PAGE_MISS = 22, EXCP_AINSTR_PAGE_PROT = 23, EXCP_LAST_WISH = 24, EXCP_BASE_NOT_ALIGNED = 25, EXCP_DATA_DEBUG = 28, EXCP_DATA_PAGE = 29, EXCP_RECOVERY_POINT = 31, EXCP_INTERRUPT = 32, EXCP_NM_INTERRUPT = 33, EXCP_DIV = 34, EXCP_FP = 35, EXCP_MEM_LOCK = 36, EXCP_MEM_LOCK_AS = 37, EXCP_MEM_ERROR_OUT_CPU = 38, EXCP_MEM_ERROR_MAU = 39, EXCP_MEM_ERROR_L2 = 40, EXCP_MEM_ERROR_L1_35 = 41, EXCP_MEM_ERROR_L1_02 = 42, EXCP_MEM_ERROR_ICACHE = 43, EXCP_MAX = 43, #ifdef CONFIG_USER_ONLY EXCP_SYSCALL = 100, #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; const char *gdb_arch; uint32_t isa_version; }; typedef struct { uint32_t base; uint32_t size; uint32_t cur; } E2KBnState; typedef struct { uint32_t size; uint32_t cur; } E2KBpState; typedef struct { union { struct { uint64_t tr: 15; uint64_t unused1: 1; uint64_t ein: 8; uint64_t ss: 1; uint64_t wfx: 1; uint64_t wpsz: 7; uint64_t wbs: 7; uint64_t cuir: 17; uint64_t psr: 7; }; struct { uint64_t unused2: 40; uint64_t cui: 16; uint64_t ic: 1; uint64_t pm: 1; /* privileged mode */ uint64_t ie: 1; uint64_t sge: 1; uint64_t lw: 1; uint64_t uie: 1; uint64_t nmie: 1; uint64_t unmie: 1; }; uint64_t lo; }; union { struct { uint64_t br: 28; uint64_t unused3: 7; uint64_t wdbl: 1; /* user stack size */ uint64_t ussz: 28; }; struct { uint64_t rbs: 6; uint64_t rsz: 6; uint64_t rcur: 6; uint64_t psz: 5; uint64_t pcur: 5; uint64_t unused4: 36; }; uint64_t hi; }; } E2KCr1; typedef struct { uint64_t cr0_lo; uint64_t cr0_hi; E2KCr1 cr1; } E2KCrs; typedef struct { union { struct { uint64_t base: 48; /* 47:0 */ uint64_t unused1: 7; /* 55:48 */ uint64_t stub3: 1; /* 56 */ uint64_t stub2: 1; /* 57 */ uint64_t stub1: 1; /* 58 */ uint64_t is_readable: 1; /* 59 */ uint64_t is_writable: 1; /* 60 */ uint64_t itag: 3; /* 63:61 */ }; uint64_t lo; }; union { struct { uint64_t index: 32; /* 31:0 */ uint64_t size: 32; /* 63:32 */ }; uint64_t hi; }; /* FIXME: HACK: pointer to tag storage */ target_ulong base_tag; } E2KPsp; #define E2K_PSP_LO_MASK (GEN_MASK(56, 8) | GEN_MASK(0, E2K_VA_SIZE)) typedef struct { int32_t base; int32_t size; int32_t psize; bool fx; } E2KWdState; typedef enum { AASR_NULL = 0, AASR_READY = 1, AASR_ACTIVE = 3, AASR_STOPPED = 5, } E2KAasrState; typedef union { struct { uint32_t unused : 5; uint32_t stb : 1; uint32_t iab : 1; uint32_t lds : 3; }; uint32_t raw; } E2KAasr; typedef enum { AAD_TAG_UNV = 0, AAD_TAG_UDT = 1, AAD_TAG_UET = 2, AAD_TAG_UAP = 4, AAD_TAG_USAP = 5, AAD_TAG_UDS = 6, } E2KAadTag; typedef struct { union { struct { uint64_t base : 48; /* 48:0 */ uint64_t unused1 : 6; /* 53:48 */ uint64_t tag : 3; /* 56:54 */ uint64_t mb : 1; /* 57 */ uint64_t ed : 1; /* 58 */ uint64_t rw : 2; /* 60:59 */ uint64_t unused2 : 3; /* 63:60 */ }; uint64_t lo; }; union { struct { uint64_t unused3 : 32; uint64_t size : 32; }; uint64_t hi; }; } E2KAad; typedef enum { AALDA_EXC_EIO = 1, AALDA_EXC_EPM = 2, AALDA_EXC_EPMSI = 3, } E2KAaldaExc; typedef union { struct { uint8_t exc: 2; uint8_t cincr: 1; uint8_t unused1: 1; uint8_t root: 1; uint8_t unused2: 3; }; uint8_t raw; } E2KAalda; /* AAU prefetch instruction */ typedef union { struct { union { struct { uint32_t abs: 5; uint32_t asz: 3; /* version >= 2 || si == 0 */ uint32_t ind: 4; uint32_t incr: 3; uint32_t aad: 5; uint32_t mrng: 5; uint32_t fmt: 3; uint32_t dcd: 2; uint32_t si: 1; uint32_t ct: 1; }; struct { uint32_t unused1: 8; /* version <= 1 && si == 1 */ uint32_t area: 5; uint32_t am: 1; uint32_t be: 1; uint32_t unused2: 16; uint32_t dpl: 1; }; uint32_t lo; }; union { uint32_t disp; uint32_t hi; }; }; uint64_t raw; } E2KAauPrefInstr; typedef struct { E2KAauPrefInstr pi; /* prefetch instr */ uint32_t cdi; /* current data index */ uint32_t ldi; /* loaded data index */ target_ulong last_page; bool last_page_valid; } E2KAauAreaState; typedef struct { E2KAauAreaState area[32]; } E2KAauPrefState; typedef struct { E2KAasr sr; uint32_t fstr; uint64_t ldm; uint64_t ldv; uint32_t stis[16]; uint32_t sti_tags; uint32_t incrs[8]; uint32_t incr_tags; uint32_t inds[16]; uint32_t ind_tags; E2KAad ds[32]; E2KAalda lda[64]; E2KAauPrefState pl, pr; } E2KAauState; typedef union { struct { uint64_t base: 48; /* 47:0 */ uint64_t unused1: 6; /* 53:48 */ uint64_t tag: 3; /* 56:54 */ uint64_t opc: 2; /* 58:57 */ uint64_t ipd: 2; /* 60:59 */ uint64_t unused2: 3; /* 63:61 */ }; uint64_t raw; } E2KCtpr; /* E2K FPU regs are compatible with x87 regs */ #define FP_IE (1U << 0) /* invalid operation */ #define FP_DE (1U << 1) /* denormalized operand */ #define FP_ZE (1U << 2) /* zero divide */ #define FP_OE (1U << 3) /* overflow */ #define FP_UE (1U << 4) /* underflow */ #define FP_PE (1U << 5) /* precision */ typedef union { struct { uint32_t ef : 6; /* exception flags */ uint32_t sf : 1; /* stack fault, unused */ uint32_t es : 1; /* error summary status */ uint32_t _c0 : 1; /* condition code 0, unused */ uint32_t c1 : 1; /* condition code 1 */ uint32_t _c2 : 1; /* condition code 2, unused */ uint32_t top: 3; /* stack top, unused */ uint32_t _c3 : 1; /* condition code 3, unused */ uint32_t b : 1; /* fpu busy */ }; uint32_t raw; } E2KFpsrState; #define FP_EM (FP_IE|FP_DE|FP_ZE|FP_OE|FP_UE|FP_PE) #define FPCR_PC_SP 0 /* single precision (32 bits) */ #define FPCR_PC_RESERVED 1 /* reserved */ #define FPCR_PC_DP 2 /* double precision (64 bits) */ #define FPCR_PC_XP 3 /* extended precision (80 bits) */ #define FP_RC_NEAR 0 /* round to nearest */ #define FP_RC_DOWN 1 /* round down */ #define FP_RC_UP 2 /* round up */ #define FP_RC_CHOP 3 /* round toward zero (truncate) */ typedef union { struct { uint32_t em : 6; /* masks flags */ uint32_t _one : 1; /* reserved, always 1 (?) */ uint32_t _zero0 : 1; /* reserved, always 0 */ uint32_t pc : 2; /* precision control */ uint32_t rc : 2; /* rounding control */ uint32_t ic : 1; /* infinity control */ uint32_t _zero1 : 3; /* reserved */ }; uint32_t raw; } E2KFpcrState; /* * Packed Floating Point Flag Register (PFPFR) */ typedef union { struct { uint32_t ef: 6; /* 5:0 */ uint32_t zero1: 1; /* 6 */ uint32_t em: 6; /* 12:7 */ uint32_t rc: 2; /* 14:13 */ uint32_t fz: 1; /* 15 */ uint32_t zero2: 10; /* 25:16 */ uint32_t dm: 6; /* 31:26 */ }; uint32_t raw; } E2KPfpfr; typedef struct { union { uint64_t lo; struct { 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; /* [31: 0] */ uint64_t size : 32; /* [63:32] */ }; }; } E2KRwap; #define E2K_RWAP_LO_MASK (GEN_MASK(58, 3) | GEN_MASK(0, E2K_VA_SIZE)) typedef union { struct { uint64_t l1col: 2; /* 1:0 */ uint64_t l1msb: 2; /* 3:2 */ uint64_t word: 9; /* 12:4 */ uint64_t page: 28; /* 40:13 */ uint64_t mask: 8; /* 48:41 */ uint64_t rg: 8; /* 56:49 */ uint64_t quadro: 1; /* 57 */ uint64_t val: 1; /* 58 */ uint64_t unused: 5; /* 63:59 */ }; uint64_t raw; } E2KDamEntry; typedef union { uint32_t u32; uint64_t u64; floatx80 f80; uint8_t ub[16]; uint16_t uh[8]; uint32_t uw[4]; uint64_t ud[2]; int8_t sb[16]; int16_t sh[8]; int32_t sw[4]; int64_t sd[2]; struct { uint64_t lo; uint64_t hi; }; } E2KReg; typedef struct CPUArchState { /* 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 */ uint64_t lsr; uint64_t lsr_lcnt; uint32_t lsr_ecnt; uint32_t lsr_vlc; uint32_t lsr_over; uint32_t lsr_pcnt; uint32_t lsr_strmd; /* Initial Loop Counter Register */ uint32_t ilcr; uint64_t ilcr_lcnt; /* Control Transfer Preparation Register (CTPR) */ E2KCtpr ctprs[3]; /* Control Transfer Condition */ target_ulong ct_cond; uint32_t psr; uint32_t upsr; uint32_t cuir; /* System Register */ uint64_t osr0; uint64_t idr; uint64_t core_mode; /* Packed Floating Point Flag Register (PFPFR) */ E2KPfpfr pfpfr; /* Floating point state register (FPSR) */ E2KFpsrState fpsr; /* Floating point control register (FPCR) */ E2KFpcrState fpcr; /* 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; /* 32/64-bit scalar/packed float status */ float_status fp_status; /* 80-bit float status */ float_status fx_status; /* 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 */ bool force_save_alc_dst; /* Enable tags handling. * Default: false */ bool enable_tags; struct e2k_def_t def; uint32_t elf_flags; } CPUE2KState; /** * E2KCPU: * @env: #CPUE2KState * * An Elbrus CPU. */ struct ArchCPU { /*< private >*/ CPUState parent_obj; /*< public >*/ CPUNegativeOffsetState neg; CPUE2KState env; }; static inline void cpu_get_tb_cpu_state(CPUE2KState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags) { *pc = env->ip; *cs_base = 0; *pflags = MMU_USER_IDX; } static inline int cpu_mmu_index(CPUE2KState *env, bool ifetch) { #ifdef CONFIG_USER_ONLY return MMU_USER_IDX; #else #error softmmu is not supported on E2K #endif } void e2k_cpu_dump_state(CPUState *cs, FILE *f, int flags); void e2k_cpu_do_interrupt(CPUState *cs); void e2k_cpu_list(void); int e2k_cpu_signal_handler(int host_signum, void *pinfo, void *puc); int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n); int e2k_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n); void e2k_cpu_register_gdb_regs_for_features(CPUState *cs); bool e2k_cpu_tlb_fill(CPUState *cpu, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); void e2k_update_fp_status(CPUE2KState *env); void e2k_update_fx_status(CPUE2KState *env); /* * PCSP * @base = mmap(size) * @base_tags = 0 * * PSP * @base = mmap(size) * @base_tags = mmap(size / 8) */ void e2k_psp_new(E2KPsp *psp, uint32_t size, uint64_t base, uint64_t base_tags); void e2k_proc_call(CPUE2KState *env, int base, target_ulong ret_ip, bool force_fx); void e2k_proc_return(CPUE2KState *env, bool force_fx); #define cpu_signal_handler e2k_cpu_signal_handler #define cpu_list e2k_cpu_list #include "exec/cpu-all.h" #endif