| 1 | /* |
| 2 | * ========== Copyright Header Begin ========================================== |
| 3 | * |
| 4 | * OpenSPARC T2 Processor File: tsparcv9internal.h |
| 5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. |
| 6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. |
| 7 | * |
| 8 | * The above named program is free software; you can redistribute it and/or |
| 9 | * modify it under the terms of the GNU General Public |
| 10 | * License version 2 as published by the Free Software Foundation. |
| 11 | * |
| 12 | * The above named program is distributed in the hope that it will be |
| 13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 15 | * General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public |
| 18 | * License along with this work; if not, write to the Free Software |
| 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. |
| 20 | * |
| 21 | * ========== Copyright Header End ============================================ |
| 22 | */ |
| 23 | /* |
| 24 | * Copyright 2007 Sun Microsystems, Inc. All rights reserved. |
| 25 | * Use is subject to license terms. |
| 26 | */ |
| 27 | |
| 28 | #ifndef _TSPARCV9INTERNAL_H_ |
| 29 | #define _TSPARCV9INTERNAL_H_ |
| 30 | |
| 31 | #pragma ident "@(#)tsparcv9internal.h 1.47 07/02/15 SMI" |
| 32 | |
| 33 | #ifdef __cplusplus |
| 34 | extern "C" { |
| 35 | #endif |
| 36 | |
| 37 | /* |
| 38 | * defines to support the values we stuff into the simcpu_t |
| 39 | * misc registers |
| 40 | */ |
| 41 | |
| 42 | #define v9_ccr miscreg[0] |
| 43 | #define v9_asi miscreg[1] |
| 44 | #define v9_y miscreg[2] |
| 45 | #define v9_fsr_exc miscreg[3] |
| 46 | #define v9_fsr_tem miscreg[4] |
| 47 | #define v9_fsr_ctrl miscreg[5] |
| 48 | #define v9_gsr miscreg[6] |
| 49 | |
| 50 | #define V9_FSR_RD_BIT 30 |
| 51 | #define V9_FSR_RD_MASK MASK64(31,30) |
| 52 | #define V9_FSR_TEM_BIT 23 |
| 53 | #define V9_FSR_TEM_MASK MASK64(27,23) |
| 54 | #define V9_FSR_NS_MASK MASK64(22,22) |
| 55 | #define V9_FSR_FTT_SHIFT 14 |
| 56 | #define V9_FSR_FTT_MASK MASK64(16,14) |
| 57 | #define V9_FSR_FCC0_SHIFT 10 |
| 58 | #define V9_FSR_FCC1_SHIFT 32 |
| 59 | #define V9_FSR_FCC_BITS 2 |
| 60 | #define V9_FSR_FCC_MASK MASK64((V9_FSR_FCC_BITS - 1),0) |
| 61 | #define V9_FSR_AEXC_MASK MASK64(9,5) |
| 62 | #define V9_FSR_CEXC_MASK MASK64(4,0) |
| 63 | |
| 64 | #define V9_FSR_ALL_FCC_MASK \ |
| 65 | (MASK64((V9_FSR_FCC1_SHIFT+(V9_FSR_FCC_BITS*3)-1),V9_FSR_FCC1_SHIFT) | \ |
| 66 | MASK64((V9_FSR_FCC0_SHIFT+V9_FSR_FCC_BITS-1),V9_FSR_FCC0_SHIFT)) |
| 67 | |
| 68 | /* ldfsr/ldxfsr mask - does not change reserved/readonly or ftt fields. */ |
| 69 | #define V9_FSR_REG_MASK (V9_FSR_ALL_FCC_MASK | V9_FSR_RD_MASK | \ |
| 70 | V9_FSR_TEM_MASK | \ |
| 71 | V9_FSR_AEXC_MASK | V9_FSR_CEXC_MASK) |
| 72 | |
| 73 | #define V9_FSR_FCC0(_fsr) (((_fsr) >> V9_FSR_FCC0_SHIFT) & V9_FSR_FCC_MASK) |
| 74 | /* _fccn can be 1, 2 or 3 */ |
| 75 | #define V9_FSR_FCCN(_fsr, _fccn) (((_fsr) >> (V9_FSR_FCC1_SHIFT + (((_fccn) - 1) * V9_FSR_FCC_BITS))) & V9_FSR_FCC_MASK) |
| 76 | |
| 77 | /* Bits in CEXC, AEXC and TEM */ |
| 78 | #define V9_FSR_NV_BIT 0x10 |
| 79 | #define V9_FSR_OF_BIT 0x08 |
| 80 | #define V9_FSR_UF_BIT 0x04 |
| 81 | #define V9_FSR_DZ_BIT 0x02 |
| 82 | #define V9_FSR_NX_BIT 0x01 |
| 83 | |
| 84 | /* GSR - General Status Register */ |
| 85 | #define V9_GSR_MASK_MASK MASK64(63, 32) |
| 86 | #define V9_GSR_IM_MASK MASK64(27, 27) |
| 87 | #define V9_GSR_IRND_SHIFT 25 |
| 88 | #define V9_GSR_IRND_MASK MASK64(26, 25) |
| 89 | #define V9_GSR_SCALE_MASK MASK64(7, 3) |
| 90 | #define V9_GSR_ALIGN_MASK MASK64(2, 0) |
| 91 | |
| 92 | #define V9_GSR_REG_MASK (V9_GSR_MASK_MASK | V9_GSR_IM_MASK | \ |
| 93 | V9_GSR_IRND_MASK | V9_GSR_SCALE_MASK | \ |
| 94 | V9_GSR_ALIGN_MASK) |
| 95 | |
| 96 | |
| 97 | typedef enum { |
| 98 | V9_UnInitialised, /* Not a legit state - tells us allocated but not inited */ |
| 99 | V9_User, V9_Priv, V9_HyperPriv, V9_RED, V9_Error, |
| 100 | V9_State_Max /* Not a legit state - used to let us know the max number of states */ |
| 101 | } sparcv9_state_t; |
| 102 | |
| 103 | /* For useful debugging stuff: */ |
| 104 | extern char * sparcv9_state_name[]; |
| 105 | |
| 106 | typedef enum { |
| 107 | /* 0x0 Reserved */ |
| 108 | Sparcv9_trap_power_on_reset = 0x1, |
| 109 | Sparcv9_trap_watchdog_reset = 0x2, |
| 110 | Sparcv9_trap_externally_initiated_reset = 0x3, |
| 111 | Sparcv9_trap_software_initiated_reset = 0x4, |
| 112 | Sparcv9_trap_RED_state_exception = 0x5, |
| 113 | /* 0x6-0x7 Reserved */ |
| 114 | Sparcv9_trap_instruction_access_exception = 0x8, |
| 115 | Sparcv9_trap_instruction_access_MMU_miss = 0x9, |
| 116 | Sparcv9_trap_instruction_access_error = 0xa, |
| 117 | /* 0xb-0xf Reserved */ |
| 118 | Sparcv9_trap_illegal_instruction = 0x10, |
| 119 | Sparcv9_trap_privileged_opcode = 0x11, |
| 120 | Sparcv9_trap_unimplemented_LDD = 0x12, |
| 121 | Sparcv9_trap_unimplemented_STD = 0x13, |
| 122 | /* 0x14-0x1f Reserved */ |
| 123 | Sparcv9_trap_fp_disabled = 0x20, |
| 124 | Sparcv9_trap_fp_exception_ieee_754 = 0x21, |
| 125 | Sparcv9_trap_fp_exception_other = 0x22, |
| 126 | Sparcv9_trap_tag_overflow = 0x23, |
| 127 | Sparcv9_trap_clean_window = 0x24, |
| 128 | /* 0x25-0x27 clean_window reserved */ |
| 129 | Sparcv9_trap_division_by_zero = 0x28, |
| 130 | Sparcv9_trap_internal_processor_error = 0x29, |
| 131 | /* 0x2a-0x2f Reserved */ |
| 132 | Sparcv9_trap_data_access_exception = 0x30, |
| 133 | Sparcv9_trap_data_access_MMU_miss = 0x31, |
| 134 | Sparcv9_trap_data_access_error = 0x32, |
| 135 | Sparcv9_trap_data_access_protection = 0x33, |
| 136 | Sparcv9_trap_mem_address_not_aligned = 0x34, |
| 137 | Sparcv9_trap_LDDF_mem_address_not_aligned = 0x35, |
| 138 | Sparcv9_trap_STDF_mem_address_not_aligned = 0x36, |
| 139 | Sparcv9_trap_privileged_action = 0x37, |
| 140 | Sparcv9_trap_LDQF_mem_address_not_aligned = 0x38, |
| 141 | Sparcv9_trap_STQF_mem_address_not_aligned = 0x39, |
| 142 | /* 0x3a-0x3f Reserved */ |
| 143 | Sparcv9_trap_async_data_error = 0x40, |
| 144 | Sparcv9_trap_interrupt_level_1 = 0x41, |
| 145 | Sparcv9_trap_interrupt_level_2 = 0x42, |
| 146 | Sparcv9_trap_interrupt_level_3 = 0x43, |
| 147 | Sparcv9_trap_interrupt_level_4 = 0x44, |
| 148 | Sparcv9_trap_interrupt_level_5 = 0x45, |
| 149 | Sparcv9_trap_interrupt_level_6 = 0x46, |
| 150 | Sparcv9_trap_interrupt_level_7 = 0x47, |
| 151 | Sparcv9_trap_interrupt_level_8 = 0x48, |
| 152 | Sparcv9_trap_interrupt_level_9 = 0x49, |
| 153 | Sparcv9_trap_interrupt_level_a = 0x4a, |
| 154 | Sparcv9_trap_interrupt_level_b = 0x4b, |
| 155 | Sparcv9_trap_interrupt_level_c = 0x4c, |
| 156 | Sparcv9_trap_interrupt_level_d = 0x4d, |
| 157 | Sparcv9_trap_interrupt_level_e = 0x4e, |
| 158 | Sparcv9_trap_interrupt_level_f = 0x4f, |
| 159 | /* 0x50-0x5f Reserved */ |
| 160 | /* 0x60-0x7f Impl Dep */ |
| 161 | |
| 162 | Sparcv9_trap_spill_0_normal = 0x80, |
| 163 | Sparcv9_trap_spill_1_normal = 0x84, |
| 164 | Sparcv9_trap_spill_2_normal = 0x88, |
| 165 | Sparcv9_trap_spill_3_normal = 0x8c, |
| 166 | Sparcv9_trap_spill_4_normal = 0x90, |
| 167 | Sparcv9_trap_spill_5_normal = 0x94, |
| 168 | Sparcv9_trap_spill_6_normal = 0x98, |
| 169 | Sparcv9_trap_spill_7_normal = 0x9c, |
| 170 | |
| 171 | Sparcv9_trap_spill_0_other = 0xa0, |
| 172 | Sparcv9_trap_spill_1_other = 0xa4, |
| 173 | Sparcv9_trap_spill_2_other = 0xa8, |
| 174 | Sparcv9_trap_spill_3_other = 0xac, |
| 175 | Sparcv9_trap_spill_4_other = 0xb0, |
| 176 | Sparcv9_trap_spill_5_other = 0xb4, |
| 177 | Sparcv9_trap_spill_6_other = 0xb8, |
| 178 | Sparcv9_trap_spill_7_other = 0xbc, |
| 179 | |
| 180 | Sparcv9_trap_fill_0_normal = 0xc0, |
| 181 | Sparcv9_trap_fill_1_normal = 0xc4, |
| 182 | Sparcv9_trap_fill_2_normal = 0xc8, |
| 183 | Sparcv9_trap_fill_3_normal = 0xcc, |
| 184 | Sparcv9_trap_fill_4_normal = 0xd0, |
| 185 | Sparcv9_trap_fill_5_normal = 0xd4, |
| 186 | Sparcv9_trap_fill_6_normal = 0xd8, |
| 187 | Sparcv9_trap_fill_7_normal = 0xdc, |
| 188 | |
| 189 | Sparcv9_trap_fill_0_other = 0xe0, |
| 190 | Sparcv9_trap_fill_1_other = 0xe4, |
| 191 | Sparcv9_trap_fill_2_other = 0xe8, |
| 192 | Sparcv9_trap_fill_3_other = 0xec, |
| 193 | Sparcv9_trap_fill_4_other = 0xf0, |
| 194 | Sparcv9_trap_fill_5_other = 0xf4, |
| 195 | Sparcv9_trap_fill_6_other = 0xf8, |
| 196 | Sparcv9_trap_fill_7_other = 0xfc, |
| 197 | |
| 198 | /* trap 0x100-0x17f, */ |
| 199 | Sparcv9_trap_trap_instruction = 0x100, |
| 200 | /* htrap 0x180-0x1ff, */ |
| 201 | Sparcv9_trap_htrap_instruction = 0x180, |
| 202 | Sparcv9_trap_illegal_value = 0x200 |
| 203 | } sparcv9_trap_type_t; |
| 204 | |
| 205 | |
| 206 | typedef enum { |
| 207 | v9_mm_tso = 0x0, |
| 208 | v9_mm_pso = 0x1, |
| 209 | v9_mm_rmo = 0x2, |
| 210 | v9_mm_illegal = 0x3 |
| 211 | } v9_mm_t; |
| 212 | |
| 213 | |
| 214 | typedef enum { |
| 215 | SPARCv9_FTT_None = 0, |
| 216 | SPARCv9_FTT_IEEE_754_exception = 1, |
| 217 | SPARCv9_FTT_unfinished_FPop = 2, |
| 218 | SPARCv9_FTT_unimplemented_FPop = 3, |
| 219 | SPARCv9_FTT_sequence_error = 4, |
| 220 | SPARCv9_FTT_hardware_error = 5, |
| 221 | SPARCv9_FTT_invalid_fp_register = 6, |
| 222 | SPARCv9_FTT_reserved = 7 |
| 223 | } v9_fsr_ftt_t; |
| 224 | |
| 225 | |
| 226 | enum V9_MACCESS { |
| 227 | MA_V9_LdFSR = MA_Non_Gen_Base, |
| 228 | MA_V9_LdXFSR = MA_V9_LdFSR + MA_Non_Gen_Skip, |
| 229 | MA_V9_StFSR = MA_V9_LdXFSR + MA_Non_Gen_Skip, |
| 230 | MA_V9_StXFSR = MA_V9_StFSR + MA_Non_Gen_Skip, |
| 231 | MA_V9_Flush = MA_V9_StXFSR + MA_Non_Gen_Skip |
| 232 | }; |
| 233 | |
| 234 | /* |
| 235 | * These macros must be passed an op masked with MA_Op_Mask. |
| 236 | */ |
| 237 | #define IS_V9_MA_LOAD(_op) (_IS_MA_LOAD((_op)) || \ |
| 238 | (maccess_t)MA_V9_LdFSR == (_op) || \ |
| 239 | (maccess_t)MA_V9_LdXFSR == (_op)) |
| 240 | #define IS_V9_MA_STORE(_op) (_IS_MA_STORE((_op)) || \ |
| 241 | (maccess_t)MA_V9_StFSR == (_op) || \ |
| 242 | (maccess_t)MA_V9_StXFSR == (_op) || \ |
| 243 | (maccess_t)MA_V9_Flush == (_op)) |
| 244 | #define IS_V9_MA_ATOMIC(_op) (_IS_MA_ATOMIC((_op))) |
| 245 | |
| 246 | |
| 247 | typedef enum { |
| 248 | USE_ASI_REG, |
| 249 | NO_FLAG |
| 250 | } asi_flag_t; |
| 251 | |
| 252 | |
| 253 | /* |
| 254 | * The actual definition of sparcv9_cpu_t: |
| 255 | * private to this module |
| 256 | */ |
| 257 | |
| 258 | |
| 259 | #if WALL_TIME |
| 260 | |
| 261 | extern hrtime_t base_hrtime; |
| 262 | |
| 263 | #define RAW_HRTIME (gethrtime() - base_hrtime) |
| 264 | #define HRT_TO_TICK(_hrt, _scale) ((uint64_t)((double)(_hrt) * (_scale))) |
| 265 | #define TICK_TO_HRT(_tick, _scale_recip) ((hrtime_t)((double)(_tick) * \ |
| 266 | (_scale_recip))) |
| 267 | |
| 268 | #define _RAW_TCOUNTER(_tcp) HRT_TO_TICK(RAW_HRTIME, (_tcp)->scale) |
| 269 | #define RAW_TICK(_v9p) (options.walltime ? _RAW_TCOUNTER((_v9p)->tick) : \ |
| 270 | ((_v9p)->simp->cycle)) |
| 271 | #define RAW_STICK(_v9p) (options.walltime ? _RAW_TCOUNTER((_v9p)->stick) : \ |
| 272 | ((_v9p)->simp->cycle)) |
| 273 | |
| 274 | #else /* WALL_TIME */ |
| 275 | |
| 276 | #define RAW_TICK(_v9p) ((_v9p)->simp->cycle) |
| 277 | #define RAW_STICK(_v9p) ((_v9p)->simp->cycle) |
| 278 | |
| 279 | #endif /* WALL_TIME */ |
| 280 | |
| 281 | typedef struct { |
| 282 | #if WALL_TIME |
| 283 | double scale; |
| 284 | double scale_recip; |
| 285 | #endif /* WALL_TIME */ |
| 286 | uint64_t offset; |
| 287 | bool_t non_priv_trap; |
| 288 | } tick_counter_t; |
| 289 | |
| 290 | /* ticktarg_t needs to be able to hold uint64_t and hrtime_t */ |
| 291 | typedef uint64_t ticktarg_t; |
| 292 | |
| 293 | typedef struct { |
| 294 | uint64_t compare; |
| 295 | ticktarg_t target; |
| 296 | bool_t interrupt_enabled; |
| 297 | bool_t triggered; |
| 298 | bool_t pending; |
| 299 | tick_counter_t *counter; |
| 300 | } tick_compare_t; |
| 301 | |
| 302 | /* |
| 303 | * Legion debug features used by all sparcv9 processors |
| 304 | * and parsed from config file. |
| 305 | */ |
| 306 | struct PROC_DEBUG { |
| 307 | uint64_t exit_at; /* if set in conf file, exit when |
| 308 | we reach this num of instns */ |
| 309 | uint64_t perf_cycle_gap; /* Override PERF_CYCLE_GAP */ |
| 310 | }; |
| 311 | |
| 312 | |
| 313 | struct SPARCV9_CPU { |
| 314 | /* Window registers */ |
| 315 | uint_t cwp; |
| 316 | uint_t cansave; |
| 317 | uint_t canrestore; |
| 318 | uint_t otherwin; |
| 319 | uint_t cleanwin; |
| 320 | uint_t wstate_other; |
| 321 | uint_t wstate_normal; |
| 322 | |
| 323 | uint_t active_window; /* window currently in intreg file */ |
| 324 | uint_t active_global; /* globals currently in intreg file */ |
| 325 | /* -1 if intregs not active */ |
| 326 | |
| 327 | #define V9_WSTATE_NORMAL_BITS 0 |
| 328 | #define V9_WSTATE_OTHER_BITS 3 |
| 329 | #define V9_WSTATE_MASK 0x7 |
| 330 | |
| 331 | |
| 332 | |
| 333 | #define V9_REG_GROUP 8 /* 8 registers */ |
| 334 | #define V9_IN_OFFSET 24 |
| 335 | #define V9_LOCAL_OFFSET 16 |
| 336 | #define V9_OUT_OFFSET 8 |
| 337 | uint_t nwins; |
| 338 | uint_t nwins_mask; /* set to nwins-1 */ |
| 339 | uint64_t * winsp; |
| 340 | |
| 341 | #define V9_GLOBAL_GROUP 8 |
| 342 | #define V9_GLOBAL_OFFSET 0 |
| 343 | uint_t nglobals; |
| 344 | uint64_t * globalsp; |
| 345 | uint_t gl; |
| 346 | #define Q_MAXPGL 2 /* Max GL for cpu obeying Q spec */ |
| 347 | |
| 348 | #define V9_PSTATE_IE_BIT 1 |
| 349 | #define V9_PSTATE_PRIV_BIT 2 |
| 350 | #define V9_PSTATE_AM_BIT 3 |
| 351 | #define V9_PSTATE_PEF_BIT 4 |
| 352 | #define V9_PSTATE_MM_BITS 6 |
| 353 | #define V9_PSTATE_MM_MASK 0x3 |
| 354 | #define V9_PSTATE_TLE_BIT 8 |
| 355 | #define V9_PSTATE_CLE_BIT 9 |
| 356 | #define V9_PSTATE_TCT_BIT 12 |
| 357 | struct { |
| 358 | bool_t priv; /* PRIV */ |
| 359 | bool_t int_enabled; /* IE */ |
| 360 | bool_t addr_mask; /* AM */ |
| 361 | v9_mm_t mm; /* memory mode */ |
| 362 | bool_t fpu_enabled; /* PEF */ |
| 363 | bool_t cle; /* CLE */ |
| 364 | bool_t tle; /* TLE */ |
| 365 | bool_t tct; /* TCT */ |
| 366 | } pstate; |
| 367 | |
| 368 | #define V9_HPSTATE_TLZ_BIT 0 |
| 369 | #define V9_HPSTATE_HPRIV_BIT 2 |
| 370 | #define V9_HPSTATE_RED_BIT 5 |
| 371 | #define V9_HPSTATE_IBE_BIT 10 |
| 372 | struct { |
| 373 | bool_t hpriv; |
| 374 | bool_t tlz; /* trap level zero */ |
| 375 | bool_t red; /* RED */ |
| 376 | bool_t ibe; /* instruction breakpoint enable */ |
| 377 | } hpstate; |
| 378 | |
| 379 | /* Trap support registers */ |
| 380 | uint_t tl; /* trap level reg */ |
| 381 | uint_t maxtl; /* max supported (SPARCv9_TLSPACE-1) */ |
| 382 | uint_t pil; /* processor interrupt level */ |
| 383 | |
| 384 | #define Q_MAXPTL 2 /* Max TL for cpu obeying Q spec */ |
| 385 | |
| 386 | #define SPARCv9_TLSPACE 8 |
| 387 | tvaddr_t tpc[SPARCv9_TLSPACE]; /* tpc[0] = TPC1 etc. */ |
| 388 | tvaddr_t tnpc[SPARCv9_TLSPACE]; |
| 389 | uint64_t tstate[SPARCv9_TLSPACE]; |
| 390 | uint16_t tt[SPARCv9_TLSPACE]; /* trap type */ |
| 391 | #define N_TPC(_v9p, _tl) (_v9p)->tpc[ (_tl)-1 ] |
| 392 | #define N_TNPC(_v9p, _tl) (_v9p)->tnpc[ (_tl)-1 ] |
| 393 | #define N_TSTATE(_v9p, _tl) (_v9p)->tstate[ (_tl)-1 ] |
| 394 | #define N_TT(_v9p, _tl) (_v9p)->tt[ (_tl)-1 ] |
| 395 | |
| 396 | #define V9_TT_MASK 0x1ff |
| 397 | |
| 398 | uint64_t htstate[SPARCv9_TLSPACE]; |
| 399 | #define N_HTSTATE(_v9p, _tl) (_v9p)->htstate[ (_tl)-1 ] |
| 400 | |
| 401 | #define V9_TBA_MASK ((tvaddr_t)~((1LL<<15)-1)) |
| 402 | tvaddr_t tba; /* trap base address */ |
| 403 | #define V9_HTBA_MASK ((tvaddr_t)~((1LL<<14)-1)) |
| 404 | tvaddr_t htba; /* hypervisor trap base address */ |
| 405 | |
| 406 | /* Other misc registers */ |
| 407 | simcpu_t * simp; |
| 408 | |
| 409 | tick_counter_t *tick; |
| 410 | tick_counter_t *stick; |
| 411 | tick_counter_t _tick; |
| 412 | tick_counter_t _stick; |
| 413 | |
| 414 | tick_compare_t tick_cmpr; |
| 415 | tick_compare_t stick_cmpr; |
| 416 | tick_compare_t hstick_cmpr; |
| 417 | |
| 418 | uint32_t softint; |
| 419 | |
| 420 | sparcv9_state_t state; |
| 421 | uint64_t ver; |
| 422 | |
| 423 | PERFDEF(struct { |
| 424 | simcycle_t enter_icount; |
| 425 | simcycle_t icount[V9_State_Max]; |
| 426 | } perf; ) |
| 427 | |
| 428 | /* |
| 429 | * Floating point state |
| 430 | * (NOTE: for efficiency, many fsr fields are implemented using |
| 431 | * simcpu_t private registers) |
| 432 | */ |
| 433 | |
| 434 | bool_t has_fpu; /* true if this v9 cpu is supposed to have an fpu */ |
| 435 | bool_t fpu_on; /* true if is fully enabled (has_fpu, pstate.pef=1, fprs.fef=1) */ |
| 436 | struct { |
| 437 | bool_t fef; /* floating point enabled in FPRS register */ |
| 438 | /* combine with pstate.pef to enable FPU */ |
| 439 | bool_t du; |
| 440 | bool_t dl; |
| 441 | } fprs; |
| 442 | #define V9_FPRS_FEF_BIT 2 |
| 443 | #define V9_FPRS_DU_BIT 1 |
| 444 | #define V9_FPRS_DL_BIT 0 |
| 445 | |
| 446 | bool_t had_RED_trap; |
| 447 | |
| 448 | /* |
| 449 | * Specific callbacks for the type of sparc core we have |
| 450 | */ |
| 451 | |
| 452 | void (*read_state_reg)(simcpu_t* sp, uint_t rdest, uint_t state_regnum); |
| 453 | void (*write_state_reg)(simcpu_t* sp, uint_t state_regnum, uint64_t val); |
| 454 | void (*read_priv_reg)(simcpu_t* sp, uint_t rdest, uint_t priv_regnum); |
| 455 | void (*write_priv_reg)(simcpu_t* sp, uint_t priv_regnum, uint64_t val); |
| 456 | void (*read_hyp_priv_reg)(simcpu_t* sp, uint_t rdest, uint_t hpriv_regnum); |
| 457 | void (*write_hyp_priv_reg)(simcpu_t* sp, uint_t hpriv_regnum, uint64_t val); |
| 458 | |
| 459 | bool_t (*check_vahole)(simcpu_t* sp, tvaddr_t pc); |
| 460 | void (*done_retry)(simcpu_t* sp, bool_t is_done); |
| 461 | void (*jpriv)(simcpu_t* sp, tvaddr_t addr); |
| 462 | 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 ); |
| 463 | |
| 464 | void (*post_precise_trap)(simcpu_t * sp, sparcv9_trap_type_t v9trap); |
| 465 | |
| 466 | /* Pointer to implementation specific v9 info - for use with callbacks */ |
| 467 | void * impl_specificp; |
| 468 | |
| 469 | }; |
| 470 | |
| 471 | #if PERFORMANCE_CHECK /* { */ |
| 472 | #define PERF_ACCUMULATE_ICOUNT(_v9p) do { \ |
| 473 | simcycle_t _icount = ICOUNT(_v9p->simp); \ |
| 474 | _v9p->perf.icount[_v9p->state] += (_icount - _v9p->perf.enter_icount); \ |
| 475 | _v9p->perf.enter_icount = _icount; \ |
| 476 | } while (0) |
| 477 | #else /* } { */ |
| 478 | #define PERF_ACCUMULATE_ICOUNT(_v9p) do { } while (0) |
| 479 | #endif /* } */ |
| 480 | |
| 481 | |
| 482 | |
| 483 | |
| 484 | #define NEXT_INSTN(_sp) do { (_sp)->pc = (_sp)->npc; (_sp)->npc += 4; } while (0) |
| 485 | /* FIXME: may want to check for PC alignment with SET_PC_WITH_DS */ |
| 486 | #define SET_PC_WITH_DS(_sp, _targ) do { (_sp)->pc = (_sp)->npc; (_sp)->npc = (_targ); } while (0) |
| 487 | |
| 488 | |
| 489 | |
| 490 | extern void sparcv9_save_instr(simcpu_t * sp, uint_t rdest_num, tvaddr_t newval); |
| 491 | extern void sparcv9_restore_instr(simcpu_t * sp, uint_t rdest_num, tvaddr_t newval); |
| 492 | extern void sparcv9_return_instr(simcpu_t * sp, tvaddr_t newval); |
| 493 | |
| 494 | extern void sparcv9_udiv64(simcpu_t * sp, uint_t rdest_num, uint64_t a, uint64_t b); |
| 495 | |
| 496 | /* |
| 497 | * Other misc values |
| 498 | */ |
| 499 | |
| 500 | |
| 501 | typedef enum { |
| 502 | cond_a = 0x8, |
| 503 | cond_n = 0x0, |
| 504 | cond_ne = 0x9, |
| 505 | cond_e = 0x1, |
| 506 | cond_g = 0xA, |
| 507 | cond_le = 0x2, |
| 508 | cond_ge = 0xB, |
| 509 | cond_l = 0x3, |
| 510 | cond_gu = 0xC, |
| 511 | cond_leu = 0x4, |
| 512 | cond_cc = 0xD, |
| 513 | cond_cs = 0x5, |
| 514 | cond_pos = 0xE, |
| 515 | cond_neg = 0x6, |
| 516 | cond_vc = 0xF, |
| 517 | cond_vs = 0x7 |
| 518 | } cond_type_t; |
| 519 | |
| 520 | extern void sparcv9_trapcc(simcpu_t * sp, uint64_t tnum, uint_t cc, cond_type_t cond); |
| 521 | |
| 522 | |
| 523 | /* iflush */ |
| 524 | |
| 525 | extern void ss_iflush_by_pa(simcpu_t * sp, uint64_t pa, uint_t gran); |
| 526 | |
| 527 | /* FLUSH instruction granularity = 64 bytes */ |
| 528 | #define SS_FLUSH_GRAN 0x40 |
| 529 | |
| 530 | typedef enum { |
| 531 | cc_bit_c = 0x1, |
| 532 | cc_bit_v = 0x2, |
| 533 | cc_bit_z = 0x4, |
| 534 | cc_bit_n = 0x8 |
| 535 | } cc_bit_t; |
| 536 | |
| 537 | /* macros to help with the formation of cc values */ |
| 538 | |
| 539 | #define _V9_cc_n(_n) ((_n)<<3) |
| 540 | #define _V9_cc_z(_z) ((_z)<<2) |
| 541 | #define _V9_cc_v(_v) ((_v)<<1) |
| 542 | #define _V9_cc_c(_c) (_c) |
| 543 | |
| 544 | #define _V9_cc(_n, _z, _v, _c) _V9_cc_n(_n)|_V9_cc_z(_z)|_V9_cc_v(_v)|_V9_cc_c(_c) |
| 545 | #define V9_icc(_n, _z, _v, _c) _V9_cc(_n, _z, _v, _c) |
| 546 | #define V9_xcc(_n, _z, _v, _c) (_V9_cc(_n, _z, _v, _c)<<4) |
| 547 | |
| 548 | #define V9_icc_n(_n) ((_n)<<3) |
| 549 | #define V9_icc_z(_z) ((_z)<<2) |
| 550 | #define V9_icc_v(_v) ((_v)<<1) |
| 551 | #define V9_icc_c(_c) (_c) |
| 552 | |
| 553 | #define V9_xcc_n(_n) ((_n)<<7) |
| 554 | #define V9_xcc_z(_z) ((_z)<<6) |
| 555 | #define V9_xcc_v(_v) ((_v)<<5) |
| 556 | #define V9_xcc_c(_c) ((_c)<<4) |
| 557 | |
| 558 | |
| 559 | #define V9_icc_n_mask V9_icc_n(1ULL) |
| 560 | #define V9_icc_z_mask V9_icc_z(1ULL) |
| 561 | #define V9_icc_v_mask V9_icc_v(1ULL) |
| 562 | #define V9_icc_c_mask V9_icc_c(1ULL) |
| 563 | #define V9_xcc_n_mask V9_xcc_n(1ULL) |
| 564 | #define V9_xcc_z_mask V9_xcc_z(1ULL) |
| 565 | #define V9_xcc_v_mask V9_xcc_v(1ULL) |
| 566 | #define V9_xcc_c_mask V9_xcc_c(1ULL) |
| 567 | |
| 568 | #define V9_icc_mask 0x0f |
| 569 | #define V9_xcc_mask 0xf0 |
| 570 | |
| 571 | #define V9_ext_icc(_x) ((_x)&V9_icc_mask) |
| 572 | #define V9_ext_xcc(_x) (((_x)&V9_xcc_mask)>>4) |
| 573 | |
| 574 | /* FPU condition codes */ |
| 575 | |
| 576 | #define V9_fcc_u 3 |
| 577 | #define V9_fcc_g 2 |
| 578 | #define V9_fcc_l 1 |
| 579 | #define V9_fcc_e 0 |
| 580 | |
| 581 | |
| 582 | uint64_t sparcv9_invert_endianess(uint64_t *regp, uint32_t count); |
| 583 | |
| 584 | /* |
| 585 | * Support functions for debugging Legion's SPARC v9 modules |
| 586 | */ |
| 587 | #if !defined(NDEBUG) /* { */ |
| 588 | |
| 589 | extern void sparcv9_dump_intregs(simcpu_t *sp); |
| 590 | extern void sparcv9_dump_state(simcpu_t *sp); |
| 591 | |
| 592 | #endif /* } */ |
| 593 | |
| 594 | #ifndef NDEBUG /* { */ |
| 595 | #define DBG_FSR 0x1000000000LL |
| 596 | #define DBG_FP 0x40000000000LL |
| 597 | #define DBGFSR(s) do { if (debug_bits & DBG_FSR) { s } } while (0) /* floating point status register */ |
| 598 | #define DBGFP(s) do { if (debug_bits & DBG_FP) { s } } while (0) /* floating point instructions */ |
| 599 | #define DBG_FPRS 0x2000000000LL |
| 600 | #define DBGFPRS(s) do { if (debug_bits & DBG_FPRS) { s } } while (0) /* floating point registers state */ |
| 601 | #else /* } { */ |
| 602 | #define DBGFSR(s) do { } while (0) |
| 603 | #define DBGFPRS(s) do { } while (0) |
| 604 | #endif /* } */ |
| 605 | |
| 606 | #ifndef FP_DECODE_DISABLED |
| 607 | #define FP_EXEC_FPU_ON_CHECK \ |
| 608 | sparcv9_cpu_t * v9p = (sparcv9_cpu_t*)(sp->specificp); \ |
| 609 | if (!v9p->fpu_on) { \ |
| 610 | v9p->post_precise_trap(sp, Sparcv9_trap_fp_disabled); \ |
| 611 | return; \ |
| 612 | } |
| 613 | #else /* FP_DECODE_DISABLED */ |
| 614 | #define FP_EXEC_FPU_ON_CHECK |
| 615 | #endif /* FP_DECODE_DISABLED */ |
| 616 | |
| 617 | #ifdef __cplusplus |
| 618 | } |
| 619 | #endif |
| 620 | |
| 621 | #endif /* _TSPARCV9INTERNAL_H_ */ |