* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: tsparcv9internal.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* ========== Copyright Header End ============================================
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
#ifndef _TSPARCV9INTERNAL_H_
#define _TSPARCV9INTERNAL_H_
#pragma ident "@(#)tsparcv9internal.h 1.47 07/02/15 SMI"
* defines to support the values we stuff into the simcpu_t
#define v9_ccr miscreg[0]
#define v9_asi miscreg[1]
#define v9_fsr_exc miscreg[3]
#define v9_fsr_tem miscreg[4]
#define v9_fsr_ctrl miscreg[5]
#define v9_gsr miscreg[6]
#define V9_FSR_RD_MASK MASK64(31,30)
#define V9_FSR_TEM_BIT 23
#define V9_FSR_TEM_MASK MASK64(27,23)
#define V9_FSR_NS_MASK MASK64(22,22)
#define V9_FSR_FTT_SHIFT 14
#define V9_FSR_FTT_MASK MASK64(16,14)
#define V9_FSR_FCC0_SHIFT 10
#define V9_FSR_FCC1_SHIFT 32
#define V9_FSR_FCC_BITS 2
#define V9_FSR_FCC_MASK MASK64((V9_FSR_FCC_BITS - 1),0)
#define V9_FSR_AEXC_MASK MASK64(9,5)
#define V9_FSR_CEXC_MASK MASK64(4,0)
#define V9_FSR_ALL_FCC_MASK \
(MASK64((V9_FSR_FCC1_SHIFT+(V9_FSR_FCC_BITS*3)-1),V9_FSR_FCC1_SHIFT) | \
MASK64((V9_FSR_FCC0_SHIFT+V9_FSR_FCC_BITS-1),V9_FSR_FCC0_SHIFT))
/* ldfsr/ldxfsr mask - does not change reserved/readonly or ftt fields. */
#define V9_FSR_REG_MASK (V9_FSR_ALL_FCC_MASK | V9_FSR_RD_MASK | \
V9_FSR_AEXC_MASK | V9_FSR_CEXC_MASK)
#define V9_FSR_FCC0(_fsr) (((_fsr) >> V9_FSR_FCC0_SHIFT) & V9_FSR_FCC_MASK)
/* _fccn can be 1, 2 or 3 */
#define V9_FSR_FCCN(_fsr, _fccn) (((_fsr) >> (V9_FSR_FCC1_SHIFT + (((_fccn) - 1) * V9_FSR_FCC_BITS))) & V9_FSR_FCC_MASK)
/* Bits in CEXC, AEXC and TEM */
#define V9_FSR_NV_BIT 0x10
#define V9_FSR_OF_BIT 0x08
#define V9_FSR_UF_BIT 0x04
#define V9_FSR_DZ_BIT 0x02
#define V9_FSR_NX_BIT 0x01
/* GSR - General Status Register */
#define V9_GSR_MASK_MASK MASK64(63, 32)
#define V9_GSR_IM_MASK MASK64(27, 27)
#define V9_GSR_IRND_SHIFT 25
#define V9_GSR_IRND_MASK MASK64(26, 25)
#define V9_GSR_SCALE_MASK MASK64(7, 3)
#define V9_GSR_ALIGN_MASK MASK64(2, 0)
#define V9_GSR_REG_MASK (V9_GSR_MASK_MASK | V9_GSR_IM_MASK | \
V9_GSR_IRND_MASK | V9_GSR_SCALE_MASK | \
V9_UnInitialised
, /* Not a legit state - tells us allocated but not inited */
V9_User
, V9_Priv
, V9_HyperPriv
, V9_RED
, V9_Error
,
V9_State_Max
/* Not a legit state - used to let us know the max number of states */
/* For useful debugging stuff: */
extern char * sparcv9_state_name
[];
Sparcv9_trap_power_on_reset
= 0x1,
Sparcv9_trap_watchdog_reset
= 0x2,
Sparcv9_trap_externally_initiated_reset
= 0x3,
Sparcv9_trap_software_initiated_reset
= 0x4,
Sparcv9_trap_RED_state_exception
= 0x5,
Sparcv9_trap_instruction_access_exception
= 0x8,
Sparcv9_trap_instruction_access_MMU_miss
= 0x9,
Sparcv9_trap_instruction_access_error
= 0xa,
Sparcv9_trap_illegal_instruction
= 0x10,
Sparcv9_trap_privileged_opcode
= 0x11,
Sparcv9_trap_unimplemented_LDD
= 0x12,
Sparcv9_trap_unimplemented_STD
= 0x13,
Sparcv9_trap_fp_disabled
= 0x20,
Sparcv9_trap_fp_exception_ieee_754
= 0x21,
Sparcv9_trap_fp_exception_other
= 0x22,
Sparcv9_trap_tag_overflow
= 0x23,
Sparcv9_trap_clean_window
= 0x24,
/* 0x25-0x27 clean_window reserved */
Sparcv9_trap_division_by_zero
= 0x28,
Sparcv9_trap_internal_processor_error
= 0x29,
Sparcv9_trap_data_access_exception
= 0x30,
Sparcv9_trap_data_access_MMU_miss
= 0x31,
Sparcv9_trap_data_access_error
= 0x32,
Sparcv9_trap_data_access_protection
= 0x33,
Sparcv9_trap_mem_address_not_aligned
= 0x34,
Sparcv9_trap_LDDF_mem_address_not_aligned
= 0x35,
Sparcv9_trap_STDF_mem_address_not_aligned
= 0x36,
Sparcv9_trap_privileged_action
= 0x37,
Sparcv9_trap_LDQF_mem_address_not_aligned
= 0x38,
Sparcv9_trap_STQF_mem_address_not_aligned
= 0x39,
Sparcv9_trap_async_data_error
= 0x40,
Sparcv9_trap_interrupt_level_1
= 0x41,
Sparcv9_trap_interrupt_level_2
= 0x42,
Sparcv9_trap_interrupt_level_3
= 0x43,
Sparcv9_trap_interrupt_level_4
= 0x44,
Sparcv9_trap_interrupt_level_5
= 0x45,
Sparcv9_trap_interrupt_level_6
= 0x46,
Sparcv9_trap_interrupt_level_7
= 0x47,
Sparcv9_trap_interrupt_level_8
= 0x48,
Sparcv9_trap_interrupt_level_9
= 0x49,
Sparcv9_trap_interrupt_level_a
= 0x4a,
Sparcv9_trap_interrupt_level_b
= 0x4b,
Sparcv9_trap_interrupt_level_c
= 0x4c,
Sparcv9_trap_interrupt_level_d
= 0x4d,
Sparcv9_trap_interrupt_level_e
= 0x4e,
Sparcv9_trap_interrupt_level_f
= 0x4f,
Sparcv9_trap_spill_0_normal
= 0x80,
Sparcv9_trap_spill_1_normal
= 0x84,
Sparcv9_trap_spill_2_normal
= 0x88,
Sparcv9_trap_spill_3_normal
= 0x8c,
Sparcv9_trap_spill_4_normal
= 0x90,
Sparcv9_trap_spill_5_normal
= 0x94,
Sparcv9_trap_spill_6_normal
= 0x98,
Sparcv9_trap_spill_7_normal
= 0x9c,
Sparcv9_trap_spill_0_other
= 0xa0,
Sparcv9_trap_spill_1_other
= 0xa4,
Sparcv9_trap_spill_2_other
= 0xa8,
Sparcv9_trap_spill_3_other
= 0xac,
Sparcv9_trap_spill_4_other
= 0xb0,
Sparcv9_trap_spill_5_other
= 0xb4,
Sparcv9_trap_spill_6_other
= 0xb8,
Sparcv9_trap_spill_7_other
= 0xbc,
Sparcv9_trap_fill_0_normal
= 0xc0,
Sparcv9_trap_fill_1_normal
= 0xc4,
Sparcv9_trap_fill_2_normal
= 0xc8,
Sparcv9_trap_fill_3_normal
= 0xcc,
Sparcv9_trap_fill_4_normal
= 0xd0,
Sparcv9_trap_fill_5_normal
= 0xd4,
Sparcv9_trap_fill_6_normal
= 0xd8,
Sparcv9_trap_fill_7_normal
= 0xdc,
Sparcv9_trap_fill_0_other
= 0xe0,
Sparcv9_trap_fill_1_other
= 0xe4,
Sparcv9_trap_fill_2_other
= 0xe8,
Sparcv9_trap_fill_3_other
= 0xec,
Sparcv9_trap_fill_4_other
= 0xf0,
Sparcv9_trap_fill_5_other
= 0xf4,
Sparcv9_trap_fill_6_other
= 0xf8,
Sparcv9_trap_fill_7_other
= 0xfc,
Sparcv9_trap_trap_instruction
= 0x100,
Sparcv9_trap_htrap_instruction
= 0x180,
Sparcv9_trap_illegal_value
= 0x200
SPARCv9_FTT_IEEE_754_exception
= 1,
SPARCv9_FTT_unfinished_FPop
= 2,
SPARCv9_FTT_unimplemented_FPop
= 3,
SPARCv9_FTT_sequence_error
= 4,
SPARCv9_FTT_hardware_error
= 5,
SPARCv9_FTT_invalid_fp_register
= 6,
MA_V9_LdFSR
= MA_Non_Gen_Base
,
MA_V9_LdXFSR
= MA_V9_LdFSR
+ MA_Non_Gen_Skip
,
MA_V9_StFSR
= MA_V9_LdXFSR
+ MA_Non_Gen_Skip
,
MA_V9_StXFSR
= MA_V9_StFSR
+ MA_Non_Gen_Skip
,
MA_V9_Flush
= MA_V9_StXFSR
+ MA_Non_Gen_Skip
* These macros must be passed an op masked with MA_Op_Mask.
#define IS_V9_MA_LOAD(_op) (_IS_MA_LOAD((_op)) || \
(maccess_t)MA_V9_LdFSR == (_op) || \
(maccess_t)MA_V9_LdXFSR == (_op))
#define IS_V9_MA_STORE(_op) (_IS_MA_STORE((_op)) || \
(maccess_t)MA_V9_StFSR == (_op) || \
(maccess_t)MA_V9_StXFSR == (_op) || \
(maccess_t)MA_V9_Flush == (_op))
#define IS_V9_MA_ATOMIC(_op) (_IS_MA_ATOMIC((_op)))
* The actual definition of sparcv9_cpu_t:
extern hrtime_t base_hrtime
;
#define RAW_HRTIME (gethrtime() - base_hrtime)
#define HRT_TO_TICK(_hrt, _scale) ((uint64_t)((double)(_hrt) * (_scale)))
#define TICK_TO_HRT(_tick, _scale_recip) ((hrtime_t)((double)(_tick) * \
#define _RAW_TCOUNTER(_tcp) HRT_TO_TICK(RAW_HRTIME, (_tcp)->scale)
#define RAW_TICK(_v9p) (options.walltime ? _RAW_TCOUNTER((_v9p)->tick) : \
#define RAW_STICK(_v9p) (options.walltime ? _RAW_TCOUNTER((_v9p)->stick) : \
#define RAW_TICK(_v9p) ((_v9p)->simp->cycle)
#define RAW_STICK(_v9p) ((_v9p)->simp->cycle)
/* ticktarg_t needs to be able to hold uint64_t and hrtime_t */
typedef uint64_t ticktarg_t
;
bool_t interrupt_enabled
;
* Legion debug features used by all sparcv9 processors
* and parsed from config file.
uint64_t exit_at
; /* if set in conf file, exit when
we reach this num of instns */
uint64_t perf_cycle_gap
; /* Override PERF_CYCLE_GAP */
uint_t active_window
; /* window currently in intreg file */
uint_t active_global
; /* globals currently in intreg file */
/* -1 if intregs not active */
#define V9_WSTATE_NORMAL_BITS 0
#define V9_WSTATE_OTHER_BITS 3
#define V9_WSTATE_MASK 0x7
#define V9_REG_GROUP 8 /* 8 registers */
#define V9_LOCAL_OFFSET 16
uint_t nwins_mask
; /* set to nwins-1 */
#define V9_GLOBAL_GROUP 8
#define V9_GLOBAL_OFFSET 0
#define Q_MAXPGL 2 /* Max GL for cpu obeying Q spec */
#define V9_PSTATE_IE_BIT 1
#define V9_PSTATE_PRIV_BIT 2
#define V9_PSTATE_AM_BIT 3
#define V9_PSTATE_PEF_BIT 4
#define V9_PSTATE_MM_BITS 6
#define V9_PSTATE_MM_MASK 0x3
#define V9_PSTATE_TLE_BIT 8
#define V9_PSTATE_CLE_BIT 9
#define V9_PSTATE_TCT_BIT 12
bool_t int_enabled
; /* IE */
bool_t addr_mask
; /* AM */
v9_mm_t mm
; /* memory mode */
bool_t fpu_enabled
; /* PEF */
#define V9_HPSTATE_TLZ_BIT 0
#define V9_HPSTATE_HPRIV_BIT 2
#define V9_HPSTATE_RED_BIT 5
#define V9_HPSTATE_IBE_BIT 10
bool_t tlz
; /* trap level zero */
bool_t ibe
; /* instruction breakpoint enable */
/* Trap support registers */
uint_t tl
; /* trap level reg */
uint_t maxtl
; /* max supported (SPARCv9_TLSPACE-1) */
uint_t pil
; /* processor interrupt level */
#define Q_MAXPTL 2 /* Max TL for cpu obeying Q spec */
#define SPARCv9_TLSPACE 8
tvaddr_t tpc
[SPARCv9_TLSPACE
]; /* tpc[0] = TPC1 etc. */
tvaddr_t tnpc
[SPARCv9_TLSPACE
];
uint64_t tstate
[SPARCv9_TLSPACE
];
uint16_t tt
[SPARCv9_TLSPACE
]; /* trap type */
#define N_TPC(_v9p, _tl) (_v9p)->tpc[ (_tl)-1 ]
#define N_TNPC(_v9p, _tl) (_v9p)->tnpc[ (_tl)-1 ]
#define N_TSTATE(_v9p, _tl) (_v9p)->tstate[ (_tl)-1 ]
#define N_TT(_v9p, _tl) (_v9p)->tt[ (_tl)-1 ]
uint64_t htstate
[SPARCv9_TLSPACE
];
#define N_HTSTATE(_v9p, _tl) (_v9p)->htstate[ (_tl)-1 ]
#define V9_TBA_MASK ((tvaddr_t)~((1LL<<15)-1))
tvaddr_t tba
; /* trap base address */
#define V9_HTBA_MASK ((tvaddr_t)~((1LL<<14)-1))
tvaddr_t htba
; /* hypervisor trap base address */
/* Other misc registers */
tick_compare_t tick_cmpr
;
tick_compare_t stick_cmpr
;
tick_compare_t hstick_cmpr
;
simcycle_t icount
[V9_State_Max
];
* (NOTE: for efficiency, many fsr fields are implemented using
* simcpu_t private registers)
bool_t has_fpu
; /* true if this v9 cpu is supposed to have an fpu */
bool_t fpu_on
; /* true if is fully enabled (has_fpu, pstate.pef=1, fprs.fef=1) */
bool_t fef
; /* floating point enabled in FPRS register */
/* combine with pstate.pef to enable FPU */
#define V9_FPRS_FEF_BIT 2
* Specific callbacks for the type of sparc core we have
void (*read_state_reg
)(simcpu_t
* sp
, uint_t rdest
, uint_t state_regnum
);
void (*write_state_reg
)(simcpu_t
* sp
, uint_t state_regnum
, uint64_t val
);
void (*read_priv_reg
)(simcpu_t
* sp
, uint_t rdest
, uint_t priv_regnum
);
void (*write_priv_reg
)(simcpu_t
* sp
, uint_t priv_regnum
, uint64_t val
);
void (*read_hyp_priv_reg
)(simcpu_t
* sp
, uint_t rdest
, uint_t hpriv_regnum
);
void (*write_hyp_priv_reg
)(simcpu_t
* sp
, uint_t hpriv_regnum
, uint64_t val
);
bool_t (*check_vahole
)(simcpu_t
* sp
, tvaddr_t pc
);
void (*done_retry
)(simcpu_t
* sp
, bool_t is_done
);
void (*jpriv
)(simcpu_t
* sp
, tvaddr_t addr
);
void (*asi_access
)(simcpu_t
* sp
, maccess_t op
, uint_t regnum
, uint_t asi
, uint64_t reg1
, uint64_t reg2
, asi_flag_t asi_flag
);
void (*post_precise_trap
)(simcpu_t
* sp
, sparcv9_trap_type_t v9trap
);
/* Pointer to implementation specific v9 info - for use with callbacks */
#if PERFORMANCE_CHECK /* { */
#define PERF_ACCUMULATE_ICOUNT(_v9p) do { \
simcycle_t _icount = ICOUNT(_v9p->simp); \
_v9p->perf.icount[_v9p->state] += (_icount - _v9p->perf.enter_icount); \
_v9p->perf.enter_icount = _icount; \
#define PERF_ACCUMULATE_ICOUNT(_v9p) do { } while (0)
#define NEXT_INSTN(_sp) do { (_sp)->pc = (_sp)->npc; (_sp)->npc += 4; } while (0)
/* FIXME: may want to check for PC alignment with SET_PC_WITH_DS */
#define SET_PC_WITH_DS(_sp, _targ) do { (_sp)->pc = (_sp)->npc; (_sp)->npc = (_targ); } while (0)
extern void sparcv9_save_instr(simcpu_t
* sp
, uint_t rdest_num
, tvaddr_t newval
);
extern void sparcv9_restore_instr(simcpu_t
* sp
, uint_t rdest_num
, tvaddr_t newval
);
extern void sparcv9_return_instr(simcpu_t
* sp
, tvaddr_t newval
);
extern void sparcv9_udiv64(simcpu_t
* sp
, uint_t rdest_num
, uint64_t a
, uint64_t b
);
extern void sparcv9_trapcc(simcpu_t
* sp
, uint64_t tnum
, uint_t cc
, cond_type_t cond
);
extern void ss_iflush_by_pa(simcpu_t
* sp
, uint64_t pa
, uint_t gran
);
/* FLUSH instruction granularity = 64 bytes */
#define SS_FLUSH_GRAN 0x40
/* macros to help with the formation of cc values */
#define _V9_cc_n(_n) ((_n)<<3)
#define _V9_cc_z(_z) ((_z)<<2)
#define _V9_cc_v(_v) ((_v)<<1)
#define _V9_cc_c(_c) (_c)
#define _V9_cc(_n, _z, _v, _c) _V9_cc_n(_n)|_V9_cc_z(_z)|_V9_cc_v(_v)|_V9_cc_c(_c)
#define V9_icc(_n, _z, _v, _c) _V9_cc(_n, _z, _v, _c)
#define V9_xcc(_n, _z, _v, _c) (_V9_cc(_n, _z, _v, _c)<<4)
#define V9_icc_n(_n) ((_n)<<3)
#define V9_icc_z(_z) ((_z)<<2)
#define V9_icc_v(_v) ((_v)<<1)
#define V9_icc_c(_c) (_c)
#define V9_xcc_n(_n) ((_n)<<7)
#define V9_xcc_z(_z) ((_z)<<6)
#define V9_xcc_v(_v) ((_v)<<5)
#define V9_xcc_c(_c) ((_c)<<4)
#define V9_icc_n_mask V9_icc_n(1ULL)
#define V9_icc_z_mask V9_icc_z(1ULL)
#define V9_icc_v_mask V9_icc_v(1ULL)
#define V9_icc_c_mask V9_icc_c(1ULL)
#define V9_xcc_n_mask V9_xcc_n(1ULL)
#define V9_xcc_z_mask V9_xcc_z(1ULL)
#define V9_xcc_v_mask V9_xcc_v(1ULL)
#define V9_xcc_c_mask V9_xcc_c(1ULL)
#define V9_ext_icc(_x) ((_x)&V9_icc_mask)
#define V9_ext_xcc(_x) (((_x)&V9_xcc_mask)>>4)
/* FPU condition codes */
uint64_t sparcv9_invert_endianess(uint64_t *regp
, uint32_t count
);
* Support functions for debugging Legion's SPARC v9 modules
#if !defined(NDEBUG) /* { */
extern void sparcv9_dump_intregs(simcpu_t
*sp
);
extern void sparcv9_dump_state(simcpu_t
*sp
);
#define DBG_FSR 0x1000000000LL
#define DBG_FP 0x40000000000LL
#define DBGFSR(s) do { if (debug_bits & DBG_FSR) { s } } while (0) /* floating point status register */
#define DBGFP(s) do { if (debug_bits & DBG_FP) { s } } while (0) /* floating point instructions */
#define DBG_FPRS 0x2000000000LL
#define DBGFPRS(s) do { if (debug_bits & DBG_FPRS) { s } } while (0) /* floating point registers state */
#define DBGFSR(s) do { } while (0)
#define DBGFPRS(s) do { } while (0)
#ifndef FP_DECODE_DISABLED
#define FP_EXEC_FPU_ON_CHECK \
sparcv9_cpu_t * v9p = (sparcv9_cpu_t*)(sp->specificp); \
v9p->post_precise_trap(sp, Sparcv9_trap_fp_disabled); \
#else /* FP_DECODE_DISABLED */
#define FP_EXEC_FPU_ON_CHECK
#endif /* FP_DECODE_DISABLED */
#endif /* _TSPARCV9INTERNAL_H_ */