--- tme/ic/sparc/sparc-impl.h 2018/04/24 16:42:00 1.1.1.1 +++ tme/ic/sparc/sparc-impl.h 2018/04/24 16:43:52 1.1.1.2 @@ -1,9 +1,9 @@ -/* $Id: sparc-impl.h,v 1.1.1.1 2018/04/24 16:42:00 root Exp $ */ +/* $Id: sparc-impl.h,v 1.1.1.2 2018/04/24 16:43:52 root Exp $ */ /* ic/sparc/sparc-impl.h - implementation header file for SPARC emulation: */ /* - * Copyright (c) 2005 Matt Fredette + * Copyright (c) 2005, 2007, 2009 Matt Fredette * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,12 +37,18 @@ #define _IC_SPARC_IMPL_H #include -_TME_RCSID("$Id: sparc-impl.h,v 1.1.1.1 2018/04/24 16:42:00 root Exp $"); +_TME_RCSID("$Id: sparc-impl.h,v 1.1.1.2 2018/04/24 16:43:52 root Exp $"); /* includes: */ #include #include #include +#include +#if TME_HAVE_RECODE +#include +#endif /* TME_HAVE_RECODE */ +#include +#include #include /* macros: */ @@ -60,30 +66,82 @@ _TME_RCSID("$Id: sparc-impl.h,v 1.1.1.1 #define TME_SPARC_FORMAT3_MASK_RD (0x1f << 25) /* traps: */ -#define TME_SPARC_TRAP_none (0x00) -#define TME_SPARC_TRAP_reset (0x100) -#define TME_SPARC_TRAP_instruction_access_MMU_miss (0x3C) -#define TME_SPARC_TRAP_instruction_access_error (0x21) -#define TME_SPARC_TRAP_r_register_access_error (0x20) -#define TME_SPARC_TRAP_instruction_access_exception (0x01) -#define TME_SPARC_TRAP_privileged_instruction (0x03) -#define TME_SPARC_TRAP_illegal_instruction (0x02) -#define TME_SPARC_TRAP_fp_disabled (0x04) -#define TME_SPARC_TRAP_cp_disabled (0x24) -#define TME_SPARC_TRAP_unimplemented_FLUSH (0x25) -#define TME_SPARC_TRAP_watchpoint_detected (0x0B) -#define TME_SPARC_TRAP_window_overflow (0x05) -#define TME_SPARC_TRAP_window_underflow (0x06) -#define TME_SPARC_TRAP_mem_address_not_aligned (0x07) -#define TME_SPARC_TRAP_fp_exception (0x08) -#define TME_SPARC_TRAP_cp_exception (0x28) -#define TME_SPARC_TRAP_data_access_error (0x29) -#define TME_SPARC_TRAP_data_access_MMU_miss (0x2C) -#define TME_SPARC_TRAP_data_access_exception (0x09) -#define TME_SPARC_TRAP_tag_overflow (0x0A) -#define TME_SPARC_TRAP_division_by_zero (0x2A) -#define TME_SPARC_TRAP_trap_instruction(x) (0x80 + (x)) -#define TME_SPARC_TRAP_interrupt_level(il) (0x10 + (il)) +#define TME_SPARC_TRAP_IMPDEP_RESET (0x80000000) +#define _TME_SPARC_TRAP_IMPDEP(x) TME_BIT(30 - (x)) +#define _TME_SPARC_TRAP(priority, tt) (((priority) * 0x1000) + (tt)) +#define TME_SPARC_TRAP_PRIORITY(trap) \ + (((trap) / _TME_SPARC_TRAP(1, 0)) % (TME_SPARC_TRAP_IMPDEP_RESET / _TME_SPARC_TRAP(1, 0))) +#define TME_SPARC_TRAP_TT(trap) ((trap) % _TME_SPARC_TRAP(1, 0)) +#define TME_SPARC_TRAP_none _TME_SPARC_TRAP(0xfff, 0) + +/* sparc32 traps: */ +#define TME_SPARC32_TRAP_reset _TME_SPARC_TRAP( 1, 0x100) +#define TME_SPARC32_TRAP_instruction_access_MMU_miss _TME_SPARC_TRAP( 2, 0x3C) +#define TME_SPARC32_TRAP_instruction_access_error _TME_SPARC_TRAP( 3, 0x21) +#define TME_SPARC32_TRAP_r_register_access_error _TME_SPARC_TRAP( 4, 0x20) +#define TME_SPARC32_TRAP_instruction_access_exception _TME_SPARC_TRAP( 5, 0x01) +#define TME_SPARC32_TRAP_privileged_instruction _TME_SPARC_TRAP( 6, 0x03) +#define TME_SPARC32_TRAP_illegal_instruction _TME_SPARC_TRAP( 7, 0x02) +#define TME_SPARC32_TRAP_fp_disabled _TME_SPARC_TRAP( 8, 0x04) +#define TME_SPARC32_TRAP_cp_disabled _TME_SPARC_TRAP( 8, 0x24) +#define TME_SPARC32_TRAP_unimplemented_FLUSH _TME_SPARC_TRAP( 8, 0x25) +#define TME_SPARC32_TRAP_watchpoint_detected _TME_SPARC_TRAP( 8, 0x0B) +#define TME_SPARC32_TRAP_window_overflow _TME_SPARC_TRAP( 9, 0x05) +#define TME_SPARC32_TRAP_window_underflow _TME_SPARC_TRAP( 9, 0x06) +#define TME_SPARC32_TRAP_mem_address_not_aligned _TME_SPARC_TRAP(10, 0x07) +#define TME_SPARC32_TRAP_fp_exception _TME_SPARC_TRAP(11, 0x08) +#define TME_SPARC32_TRAP_cp_exception _TME_SPARC_TRAP(11, 0x28) +#define TME_SPARC32_TRAP_data_access_error _TME_SPARC_TRAP(12, 0x29) +#define TME_SPARC32_TRAP_data_access_MMU_miss _TME_SPARC_TRAP(12, 0x2C) +#define TME_SPARC32_TRAP_data_access_exception _TME_SPARC_TRAP(13, 0x09) +#define TME_SPARC32_TRAP_tag_overflow _TME_SPARC_TRAP(14, 0x0A) +#define TME_SPARC32_TRAP_division_by_zero _TME_SPARC_TRAP(15, 0x2A) +#define TME_SPARC32_TRAP_trap_instruction(x) _TME_SPARC_TRAP(16, 0x80 + (x)) +#define TME_SPARC32_TRAP_interrupt_level(il) _TME_SPARC_TRAP(32 - (il), 0x10 + (il)) + +/* sparc64 traps: */ +#define TME_SPARC64_TRAP_power_on_reset _TME_SPARC_TRAP( 0, 0x001) +#define TME_SPARC64_TRAP_watchdog_reset _TME_SPARC_TRAP( 1, 0x002) +#define TME_SPARC64_TRAP_externally_initiated_reset _TME_SPARC_TRAP( 1, 0x003) +#define TME_SPARC64_TRAP_software_initiated_reset _TME_SPARC_TRAP( 1, 0x004) +#define TME_SPARC64_TRAP_RED_state_exception _TME_SPARC_TRAP( 1, 0x005) +#define TME_SPARC64_TRAP_instruction_access_exception _TME_SPARC_TRAP( 5, 0x008) +#define TME_SPARC64_TRAP_instruction_access_MMU_miss _TME_SPARC_TRAP( 2, 0x009) +#define TME_SPARC64_TRAP_instruction_access_error _TME_SPARC_TRAP( 3, 0x00a) +#define TME_SPARC64_TRAP_illegal_instruction _TME_SPARC_TRAP( 7, 0x010) +#define TME_SPARC64_TRAP_privileged_opcode _TME_SPARC_TRAP( 6, 0x011) +#define TME_SPARC64_TRAP_unimplemented_LDD _TME_SPARC_TRAP( 6, 0x012) +#define TME_SPARC64_TRAP_unimplemented_STD _TME_SPARC_TRAP( 6, 0x013) +#define TME_SPARC64_TRAP_fp_disabled _TME_SPARC_TRAP( 8, 0x020) +#define TME_SPARC64_TRAP_fp_exception_ieee_754 _TME_SPARC_TRAP(11, 0x021) +#define TME_SPARC64_TRAP_fp_exception_other _TME_SPARC_TRAP(11, 0x022) +#define TME_SPARC64_TRAP_tag_overflow _TME_SPARC_TRAP(14, 0x023) +#define TME_SPARC64_TRAP_clean_window _TME_SPARC_TRAP(10, 0x024) +#define TME_SPARC64_TRAP_division_by_zero _TME_SPARC_TRAP(15, 0x028) +#define TME_SPARC64_TRAP_internal_processor_error _TME_SPARC_TRAP( 4, 0x029) +#define TME_SPARC64_TRAP_data_access_exception _TME_SPARC_TRAP(12, 0x030) +#define TME_SPARC64_TRAP_data_access_MMU_miss _TME_SPARC_TRAP(12, 0x031) +#define TME_SPARC64_TRAP_data_access_error _TME_SPARC_TRAP(12, 0x032) +#define TME_SPARC64_TRAP_data_access_protection _TME_SPARC_TRAP(12, 0x033) +#define TME_SPARC64_TRAP_mem_address_not_aligned _TME_SPARC_TRAP(10, 0x034) +#define TME_SPARC64_TRAP_LDDF_mem_address_not_aligned _TME_SPARC_TRAP(10, 0x035) +#define TME_SPARC64_TRAP_STDF_mem_address_not_aligned _TME_SPARC_TRAP(10, 0x036) +#define TME_SPARC64_TRAP_privileged_action _TME_SPARC_TRAP(11, 0x037) +#define TME_SPARC64_TRAP_LDQF_mem_address_not_aligned _TME_SPARC_TRAP(10, 0x038) +#define TME_SPARC64_TRAP_STQF_mem_address_not_aligned _TME_SPARC_TRAP(10, 0x039) +#define TME_SPARC64_TRAP_async_data_error _TME_SPARC_TRAP( 2, 0x040) +#define TME_SPARC64_TRAP_interrupt_level(n) _TME_SPARC_TRAP(32 - (n), 0x40 + (n)) +#define TME_SPARC64_TRAP_spill_normal(n) _TME_SPARC_TRAP( 9, 0x080 + (4 * (n))) +#define TME_SPARC64_TRAP_spill_other(n) _TME_SPARC_TRAP( 9, 0x0a0 + (4 * (n))) +#define TME_SPARC64_TRAP_fill_normal(n) _TME_SPARC_TRAP( 9, 0x0c0 + (4 * (n))) +#define TME_SPARC64_TRAP_fill_other(n) _TME_SPARC_TRAP( 9, 0x0e0 + (4 * (n))) +#define TME_SPARC64_TRAP_trap_instruction(x) _TME_SPARC_TRAP(16, 0x100 + (x)) + +/* generic traps: */ +#define TME_SPARC_TRAP(ic, trap) \ + (TME_SPARC_VERSION(ic) < 9 \ + ? _TME_CONCAT(TME_SPARC32_TRAP_,trap) \ + : _TME_CONCAT(TME_SPARC64_TRAP_,trap)) /* SPARC FPU FSR fields: */ #define TME_SPARC_FSR_RND (0xc0000000) @@ -135,8 +193,14 @@ _TME_RCSID("$Id: sparc-impl.h,v 1.1.1.1 /* sparc64 PSTATE flags: */ #define TME_SPARC64_PSTATE_CLE TME_BIT(9) -#define TME_SPARC64_PSTATE_PRIV TME_BIT(2) +#define TME_SPARC64_PSTATE_TLE TME_BIT(8) +#define TME_SPARC64_PSTATE_MM ((2 << 7) - (1 << 6)) +#define TME_SPARC64_PSTATE_RED TME_BIT(5) #define TME_SPARC64_PSTATE_PEF TME_BIT(4) +#define TME_SPARC64_PSTATE_AM TME_BIT(3) +#define TME_SPARC64_PSTATE_PRIV TME_BIT(2) +#define TME_SPARC64_PSTATE_IE TME_BIT(1) +#define TME_SPARC64_PSTATE_AG TME_BIT(0) /* sparc64 CCR flags: */ #define TME_SPARC64_CCR_XCC_N TME_BIT(7) @@ -148,57 +212,264 @@ _TME_RCSID("$Id: sparc-impl.h,v 1.1.1.1 #define TME_SPARC64_CCR_ICC_V TME_BIT(1) #define TME_SPARC64_CCR_ICC_C TME_BIT(0) #define TME_SPARC64_CCR_ICC (TME_SPARC64_CCR_ICC_N | TME_SPARC64_CCR_ICC_Z | TME_SPARC64_CCR_ICC_V | TME_SPARC64_CCR_ICC_C) +#define TME_SPARC64_CCR_XCC (TME_SPARC64_CCR_XCC_N | TME_SPARC64_CCR_XCC_Z | TME_SPARC64_CCR_XCC_V | TME_SPARC64_CCR_XCC_C) + +/* sparc64 FPRS flags: */ +#define TME_SPARC64_FPRS_DL TME_BIT(0) +#define TME_SPARC64_FPRS_DU TME_BIT(1) +#define TME_SPARC64_FPRS_FEF TME_BIT(2) + +/* sparc64 TSTATE flags: */ +#define TME_SPARC64_TSTATE_MASK_CWP (0x1f << 0) +#define TME_SPARC64_TSTATE_MASK_PSTATE (0xfff << 8) +#define TME_SPARC64_TSTATE_MASK_ASI (0xff << 24) +#define TME_SPARC64_TSTATE_MASK_CCR (((tme_uint64_t) 0xff) << 32) + +/* sparc64 WSTATE fields: */ +#define TME_SPARC64_WSTATE_NORMAL (0x07) +#define TME_SPARC64_WSTATE_OTHER (0x38) + +/* sparc64 VER fields: */ +#define TME_SPARC64_VER_MANUF (((tme_uint64_t) 0xffff) << 48) +#define TME_SPARC64_VER_IMPL (((tme_uint64_t) 0xffff) << 32) +#define TME_SPARC64_VER_MASK (((tme_uint32_t) 0xff) << 24) +#define TME_SPARC64_VER_MAXTL (((tme_uint32_t) 0xff) << 8) +#define TME_SPARC64_VER_MAXWIN (((tme_uint32_t) 0x1f) << 0) + +/* sparc64 TICK fields: */ +#define TME_SPARC64_TICK_NPT (((tme_uint64_t) 1) << 63) +#define TME_SPARC64_TICK_COUNTER (TME_SPARC64_TICK_NPT - 1) + +/* sparc VIS ASIs: */ +#define TME_SPARC_VIS_ASI_PST8 (0xc0) +#define TME_SPARC_VIS_ASI_PST16 (0xc2) +#define TME_SPARC_VIS_ASI_PST32 (0xc4) +#define TME_SPARC_VIS_ASI_FL8 (0xd0) +#define TME_SPARC_VIS_ASI_FL16 (0xd2) + +/* sparc VIS GSR fields: */ +#define TME_SPARC_VIS_GSR_ALIGNADDR_OFF ((2 << 2) - (1 << 0)) +#define TME_SPARC_VIS_GSR_SCALE_FACTOR ((2 << 6) - (1 << 3)) + +/* sparc conditions: */ +#define TME_SPARC_COND_N (0) +#define TME_SPARC_COND_E (1) +#define TME_SPARC_COND_LE (2) +#define TME_SPARC_COND_L (3) +#define TME_SPARC_COND_LEU (4) +#define TME_SPARC_COND_CS (5) +#define TME_SPARC_COND_NEG (6) +#define TME_SPARC_COND_VS (7) +#define TME_SPARC_COND_NOT (8) +#define TME_SPARC_COND_IS_CONDITIONAL(cond) (((cond) % TME_SPARC_COND_NOT) != TME_SPARC_COND_N) /* idle types and idle type state: */ #define TME_SPARC_IDLE_TYPE_NULL (0) #define TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_0 TME_BIT(0) #define TME_SPARC_IDLE_TYPE_SUNOS32_TYPE_0 TME_BIT(1) -#define TME_SPARC_IDLE_TYPES_SUPPORTED (((unsigned int) 0) - 1) +#define TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_1 TME_BIT(2) +#define TME_SPARC_IDLE_TYPE_NETBSD64_TYPE_0 TME_BIT(3) +#define TME_SPARC_IDLE_TYPE_NETBSD64_TYPE_1 TME_BIT(4) +#define TME_SPARC_IDLE_TYPE_SUNOS64_TYPE_0 TME_BIT(5) +#define TME_SPARC_IDLE_TYPES_32 \ + (TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_0 \ + + TME_SPARC_IDLE_TYPE_SUNOS32_TYPE_0 \ + + TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_1 \ + ) +#define TME_SPARC_IDLE_TYPES_64 \ + (TME_SPARC_IDLE_TYPE_NETBSD64_TYPE_0 \ + + TME_SPARC_IDLE_TYPE_NETBSD64_TYPE_1 \ + + TME_SPARC_IDLE_TYPE_SUNOS64_TYPE_0 \ + ) +#define TME_SPARC_IDLE_TYPES_TARGET_CALL \ + (TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_1 \ + + TME_SPARC_IDLE_TYPE_NETBSD64_TYPE_1 \ + ) +#define TME_SPARC_IDLE_TYPES_TARGET_BRANCH \ + (TME_SPARC_IDLE_TYPE_SUNOS32_TYPE_0 \ + ) +#define TME_SPARC_IDLE_TYPES_PC_RANGE \ + (TME_SPARC_IDLE_TYPE_NETBSD32_TYPE_0 \ + + TME_SPARC_IDLE_TYPE_SUNOS64_TYPE_0 \ + ) +#define TME_SPARC_IDLE_TYPE_IS_SUPPORTED(ic, x) \ + (((x) \ + & (0 - (unsigned int) 1)) \ + & (TME_SPARC_VERSION(ic) < 9 \ + ? TME_SPARC_IDLE_TYPES_32 \ + : TME_SPARC_IDLE_TYPES_64)) #define TME_SPARC_IDLE_TYPE_IS(ic, x) \ - ((TME_SPARC_IDLE_TYPES_SUPPORTED & (x)) \ - && (ic)->tme_sparc_idle_type == (x)) -#define TME_SPARC_IDLE_TYPE_PC_STATE(x) ((x) % sizeof(tme_uint32_t)) + (TME_SPARC_IDLE_TYPE_IS_SUPPORTED(ic, x) \ + & (ic)->tme_sparc_idle_type) +#define TME_SPARC_IDLE_TYPE_PC_STATE(x) (((tme_uint32_t) (x)) % sizeof(tme_uint32_t)) + +/* this makes an idle mark: */ +#define TME_SPARC_IDLE_MARK(ic) \ + do { \ + \ + /* increment the idle marks, up to two: */ \ + ic->tme_sparc_idle_marks += (ic->tme_sparc_idle_marks < 2); \ + \ + /* limit the remaining instruction burst to no more than \ + an idle instruction burst: */ \ + ic->_tme_sparc_instruction_burst_remaining \ + = TME_MIN(ic->_tme_sparc_instruction_burst_remaining, \ + ic->_tme_sparc_instruction_burst_idle); \ + ic->_tme_sparc_instruction_burst_other = TRUE; \ + } while (/* CONSTCOND */ 0) + +/* this stops idling: */ +#define TME_SPARC_IDLE_STOP(ic) \ + do { \ + \ + /* clear the idle marks: */ \ + ic->tme_sparc_idle_marks = 0; \ + } while (/* CONSTCOND */ 0) /* major modes of the emulator: */ #define TME_SPARC_MODE_EXECUTION (0) #define TME_SPARC_MODE_STOP (1) #define TME_SPARC_MODE_HALT (2) +#define TME_SPARC_MODE_OFF (3) +#define TME_SPARC_MODE_TIMING_LOOP (4) /* the maximum number of windows: */ #define TME_SPARC_WINDOWS_MAX (16) -/* given a CWP value, this returns the CWP register offset: */ -#define TME_SPARC_CWP_OFFSET(cwp) ((cwp) * 16) +/* the maximum number of trap levels: */ +#define TME_SPARC_TL_MAX (8) + +/* this updates the recode CWP register offsets: */ +#if TME_HAVE_RECODE +#define _TME_SPARC_RECODE_CWP_UPDATE(ic, reg_type) \ + do { \ + (ic)->tme_sparc_recode_window_base_offsets[0] \ + = (ic)->tme_sparc_reg8_offset[1] * 8 * sizeof(reg_type); \ + (ic)->tme_sparc_recode_window_base_offsets[1] \ + = (ic)->tme_sparc_reg8_offset[3] * 8 * sizeof(reg_type); \ + if (sizeof(reg_type) > sizeof(tme_uint32_t)) { \ + (ic)->tme_sparc_recode_window_base_offsets[2] \ + = (ic)->tme_sparc_reg8_offset[0] * 8 * sizeof(reg_type);\ + } \ + } while (/* CONSTCOND */ 0) +#else /* !TME_HAVE_RECODE */ +#define _TME_SPARC_RECODE_CWP_UPDATE(ic, reg_type) \ + do { \ + } while (/* CONSTCOND */ 0 && (ic) && (reg_type) 0) +#endif /* !TME_HAVE_RECODE */ + +/* this updates the CWP register offset: */ +#define _TME_SPARC_CWP_UPDATE(ic, cwp, reg8_offset_r8_r23, cwp_wraps, reg_type) \ + do { \ + (ic)->tme_sparc_reg8_offset[1] = (reg8_offset_r8_r23); \ + (ic)->tme_sparc_reg8_offset[2] = (reg8_offset_r8_r23); \ + (ic)->tme_sparc_reg8_offset[3] \ + = ((cwp) == (cwp_wraps) \ + ? ((8 - 24) / 8) \ + : (reg8_offset_r8_r23)); \ + _TME_SPARC_RECODE_CWP_UPDATE(ic, reg_type); \ + } while (/* CONSTCOND */ 0) + +/* this updates the sparc32 CWP register offsets: */ +#define TME_SPARC32_CWP_UPDATE(ic, cwp, reg8_offset_r8_r23) \ + do { \ + (reg8_offset_r8_r23) = (cwp) * 2; \ + _TME_SPARC_CWP_UPDATE(ic, cwp, reg8_offset_r8_r23, TME_SPARC_NWINDOWS(ic) - 1, tme_uint32_t); \ + } while (/* CONSTCOND */ 0) + +/* this updates the sparc64 CWP register offsets: */ +#define TME_SPARC64_CWP_UPDATE(ic, cwp, reg8_offset_r8_r23) \ + do { \ + assert (cwp < TME_SPARC_NWINDOWS(ic)); \ + (reg8_offset_r8_r23) \ + = (((TME_SPARC_NWINDOWS(ic) - 1) - cwp) \ + * 2); \ + _TME_SPARC_CWP_UPDATE(ic, cwp, reg8_offset_r8_r23, 0, tme_uint64_t); \ + } while (/* CONSTCOND */ 0) + +/* this gives the current %g0 register set index: */ +#define TME_SPARC_G0_OFFSET(ic) \ + (TME_SPARC_VERSION(ic) < 9 ? 0 : ((ic)->tme_sparc_reg8_offset[0] * 8)) /* this converts the given lvalue from a register number into a register set index: */ #define TME_SPARC_REG_INDEX(ic, reg) \ do { \ - if ((reg) > 7) { \ - (reg) += ic->tme_sparc_cwp_offset; \ - } \ - if ((reg) \ - > (TME_SPARC_CWP_OFFSET(TME_SPARC_NWINDOWS(ic)) + 7)) { \ - (reg) -= TME_SPARC_CWP_OFFSET(TME_SPARC_NWINDOWS(ic)); \ - } \ + (reg) += ((ic)->tme_sparc_reg8_offset[(reg) / 8] * 8); \ } while (/* CONSTCOND */ 0) -/* given a linear address, this hashes it into a DTLB entry: */ +/* this gives the hash for an address: */ +#define TME_SPARC_TLB_HASH(ic, context, address) \ + ((((tme_uint32_t) (address)) \ + >> (ic)->tme_sparc_tlb_page_size_log2) \ + + (0 && (context))) + +/* the size of the DTLB hash: */ #define _TME_SPARC_DTLB_HASH_SIZE (1024) -#define TME_SPARC_DTLB_ENTRY(ic, address) \ - (tme_memory_atomic_pointer_read(struct tme_sparc_tlb *, \ - (ic)->_tme_sparc_dtlb_array, \ - &(ic)->_tme_sparc_tlb_rwlock) \ - + ((address >> 10) & (_TME_SPARC_DTLB_HASH_SIZE - 1))) + +/* this gives the DTLB entry for a hash key: */ +#define TME_SPARC_DTLB_ENTRY(ic, tlb_hash) \ + (((tlb_hash) % _TME_SPARC_DTLB_HASH_SIZE) \ + + (0 && (ic))) /* the size of the ITLB hash: */ #define _TME_SPARC_ITLB_HASH_SIZE (32) -/* flags for the slow load and store functions: */ -#define TME_SPARC_SLOW_FLAG_A TME_BIT(5) -#define TME_SPARC_SLOW_FLAG_ATOMIC TME_BIT(6) -#define TME_SPARC_SLOW_FLAG_INSN TME_BIT(7) -#define TME_SPARC_SLOW_FLAG_NO_FAULTS TME_BIT(8) +/* this gives the ITLB entry for a hash key: */ +#define TME_SPARC_ITLB_ENTRY(ic, tlb_hash) \ + (_TME_SPARC_DTLB_HASH_SIZE \ + + ((tlb_hash) % _TME_SPARC_ITLB_HASH_SIZE) \ + + (0 && (ic))) + +/* the count of all TLB entries: */ +#define _TME_SPARC_TLB_COUNT \ + (_TME_SPARC_DTLB_HASH_SIZE \ + + _TME_SPARC_ITLB_HASH_SIZE) + +/* load/store information: */ +#define TME_SPARC_LSINFO_SIZE(x) (x) +#define TME_SPARC_LSINFO_WHICH_SIZE(x) (((x) / TME_SPARC_LSINFO_SIZE(1)) & 0xff) +#define TME_SPARC_LSINFO_ASI(x) ((x) << 8) +#define TME_SPARC_LSINFO_WHICH_ASI(x) (((x) / TME_SPARC_LSINFO_ASI(1)) & 0xff) +#define TME_SPARC_LSINFO_ASI_FLAGS(x) TME_SPARC_LSINFO_ASI(x) +#define TME_SPARC_LSINFO_WHICH_ASI_FLAGS(x) TME_SPARC_LSINFO_WHICH_ASI(x) +#define TME_SPARC_LSINFO_A (1 << 16) +#define TME_SPARC_LSINFO_OP_LD (1 << 17) +#define TME_SPARC_LSINFO_OP_ST (1 << 18) +#define TME_SPARC_LSINFO_OP_ATOMIC (1 << 19) +#define TME_SPARC_LSINFO_OP_FETCH (1 << 20) +#define TME_SPARC_LSINFO_LDD_STD (1 << 21) +#define TME_SPARC_LSINFO_NO_FAULT (1 << 22) +#define TME_SPARC_LSINFO_NO_CHECK_TLB (1 << 23) +#define TME_SPARC_LSINFO_SLOW_CYCLES (1 << 24) +#define TME_SPARC_LSINFO_LD_COMPLETED (1 << 25) +#define TME_SPARC_LSINFO_ENDIAN_LITTLE (1 << 26) +#define _TME_SPARC_LSINFO_X(x) (1 << (27 + (x))) + +/* load/store faults: */ +#define TME_SPARC_LS_FAULT_NONE (0) +#define TME_SPARC_LS_FAULT_ADDRESS_NOT_ALIGNED TME_BIT(0) +#define TME_SPARC_LS_FAULT_LDD_STD_RD_ODD TME_BIT(1) +#define TME_SPARC_LS_FAULT_BUS_FAULT TME_BIT(2) +#define TME_SPARC_LS_FAULT_BUS_ERROR TME_BIT(3) +#define _TME_SPARC_LS_FAULT_X(x) TME_BIT(4 + (x)) +#define TME_SPARC64_LS_FAULT_PRIVILEGED_ASI _TME_SPARC_LS_FAULT_X(0) +#define TME_SPARC64_LS_FAULT_NO_FAULT_NON_LOAD _TME_SPARC_LS_FAULT_X(1) +#define TME_SPARC64_LS_FAULT_NO_FAULT_FAULT _TME_SPARC_LS_FAULT_X(2) +#define TME_SPARC64_LS_FAULT_SIDE_EFFECTS _TME_SPARC_LS_FAULT_X(3) +#define TME_SPARC64_LS_FAULT_VA_RANGE _TME_SPARC_LS_FAULT_X(4) +#define TME_SPARC64_LS_FAULT_VA_RANGE_NNPC _TME_SPARC_LS_FAULT_X(5) +#define TME_SPARC64_LS_FAULT_UNCACHEABLE _TME_SPARC_LS_FAULT_X(6) +#define _TME_SPARC64_LS_FAULT_X(x) _TME_SPARC_LS_FAULT_X(7 + (x)) + +/* flags for memory features: */ +#define TME_SPARC_MEMORY_FLAG_HAS_NUCLEUS (1 << 0) +#define TME_SPARC_MEMORY_FLAG_HAS_INVERT_ENDIAN (1 << 1) +#define TME_SPARC_MEMORY_FLAG_HAS_LDDF_STDF_32 (1 << 2) +#define TME_SPARC_MEMORY_FLAG_HAS_LDQF_STQF_32 (1 << 3) + +/* the undefined FPU register number: */ +#define TME_SPARC_FPU_FPREG_NUMBER_UNDEF (64) /* flags for FPU features: */ #define TME_SPARC_FPU_FLAG_NO_QUAD TME_BIT(0) @@ -211,6 +482,68 @@ _TME_RCSID("$Id: sparc-impl.h,v 1.1.1.1 #define TME_SPARC_FPU_MODE_EXCEPTION_PENDING (1) #define TME_SPARC_FPU_MODE_EXCEPTION (2) +/* this marks an FPU register as dirty: */ +#define TME_SPARC_FPU_DIRTY(ic, fpreg_number) \ + do { \ + if (TME_SPARC_VERSION(ic) >= 9) { \ + assert ((TME_SPARC64_FPRS_DU - 1) \ + == TME_SPARC64_FPRS_DL); \ + (ic)->tme_sparc64_ireg_fprs \ + |= (TME_SPARC64_FPRS_DU \ + - ((fpreg_number) < 32)); \ + } \ + } while (/* CONSTCOND */ 0) + +/* this returns nonzero if the FPU is disabled: */ +#define TME_SPARC_FPU_IS_DISABLED(ic) \ + ((TME_SPARC_VERSION(ic) < 9) \ + ? ((ic)->tme_sparc32_ireg_psr & TME_SPARC32_PSR_EF) == 0 \ + : (((ic)->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_PEF) == 0 \ + || ((ic)->tme_sparc64_ireg_fprs & TME_SPARC64_FPRS_FEF) == 0)) + +/* this returns nonzero if recode supports this sparc: */ +#if TME_HAVE_RECODE +#ifndef TME_HAVE_INT64_T +#define TME_SPARC_HAVE_RECODE(ic) (1) +#else /* TME_HAVE_INT64_T */ +#define TME_SPARC_HAVE_RECODE(ic) \ + (TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 \ + || TME_SPARC_VERSION(ic) < 9) +#endif /* TME_HAVE_INT64_T */ +#else /* !TME_HAVE_RECODE */ +#define TME_SPARC_HAVE_RECODE(ic) (0) +#endif /* !TME_HAVE_RECODE */ + +#if TME_HAVE_RECODE + +/* this is the maximum number of cacheable address regions that we + will recode from: */ +#define TME_SPARC_RECODE_CACHEABLES_MAX (4) + +/* this is the modulus used in the recode source address hash: */ +#define TME_SPARC_RECODE_SRC_HASH_MODULUS (16381) + +/* the recode source address hash is set associative. this is the + number of ways in each set: */ +#define TME_SPARC_RECODE_SRC_HASH_SIZE_SET (4) + +/* the sparc recode TLB flags for loads and stores: */ +#define TME_SPARC_RECODE_TLB_FLAG_LD_USER(ic) TME_RECODE_TLB_FLAG(ic->tme_sparc_recode_ic, 0) +#define TME_SPARC_RECODE_TLB_FLAG_LD_PRIV(ic) TME_RECODE_TLB_FLAG(ic->tme_sparc_recode_ic, 1) +#define TME_SPARC_RECODE_TLB_FLAG_LD_NF(ic) TME_RECODE_TLB_FLAG(ic->tme_sparc_recode_ic, 2) +#define TME_SPARC_RECODE_TLB_FLAG_LD_F(ic) TME_RECODE_TLB_FLAG(ic->tme_sparc_recode_ic, 3) +#define TME_SPARC_RECODE_TLB_FLAG_ST_USER(ic) TME_RECODE_TLB_FLAG(ic->tme_sparc_recode_ic, 4) +#define TME_SPARC_RECODE_TLB_FLAG_ST_PRIV(ic) TME_RECODE_TLB_FLAG(ic->tme_sparc_recode_ic, 5) +#define TME_SPARC_RECODE_TLB_FLAG_LS_ENDIAN_LITTLE(ic) TME_RECODE_TLB_FLAG(ic->tme_sparc_recode_ic, 6) +#define TME_SPARC_RECODE_TLB_FLAG_LS_ENDIAN_BIG(ic) TME_RECODE_TLB_FLAG(ic->tme_sparc_recode_ic, 7) +#define TME_SPARC_RECODE_TLB_FLAG_LS_ENDIAN_INVERT(ic) TME_RECODE_TLB_FLAG(ic->tme_sparc_recode_ic, 8) + +/* the sparc recode TLB flags for chaining: */ +#define TME_SPARC_RECODE_TLB_FLAG_CHAIN_USER(ic) TME_RECODE_TLB_FLAG(ic->tme_sparc_recode_ic, 0) +#define TME_SPARC_RECODE_TLB_FLAG_CHAIN_PRIV(ic) TME_RECODE_TLB_FLAG(ic->tme_sparc_recode_ic, 1) + +#endif /* TME_HAVE_RECODE */ + /* instruction handler macros: */ #define TME_SPARC_FORMAT3_DECL(name, type) void name _TME_P((struct tme_sparc *, const type *, const type *, type *)) #ifdef __STDC__ @@ -221,7 +554,7 @@ _TME_RCSID("$Id: sparc-impl.h,v 1.1.1.1 #define TME_SPARC_FORMAT3_RS1 (*_rs1) #define TME_SPARC_FORMAT3_RS2 (*_rs2) #define TME_SPARC_FORMAT3_RD (*_rd) -#define TME_SPARC_FORMAT3_RD_ODD (*(_rd + (&(((struct tme_ic *) NULL)->tme_ic_ireg_uint32(1)) - &(((struct tme_ic *) NULL)->tme_ic_ireg_uint32(0))))) +#define TME_SPARC_FORMAT3_RD_ODD(iregs) (*(_rd + (&(((struct tme_ic *) NULL)->iregs(1)) - &(((struct tme_ic *) NULL)->iregs(0))))) #define TME_SPARC_INSN ic->_tme_sparc_insn #define TME_SPARC_INSN_OK return #define TME_SPARC_INSN_TRAP(trap) \ @@ -236,41 +569,28 @@ _TME_RCSID("$Id: sparc-impl.h,v 1.1.1.1 #define TME_SPARC_INSN_PRIV \ do { \ if (__tme_predict_false(!TME_SPARC_PRIV(ic))) { \ - TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_privileged_instruction);\ + TME_SPARC_INSN_TRAP(TME_SPARC_VERSION(ic) < 9 \ + ? TME_SPARC32_TRAP_privileged_instruction \ + : TME_SPARC64_TRAP_privileged_opcode); \ } \ } while (/* CONSTCOND */ 0) -#define TME_SPARC_INSN_FPU \ +#define TME_SPARC_INSN_FPU_ENABLED \ do { \ - if (__tme_predict_false((TME_SPARC_VERSION(ic) < 9) \ - ? ((ic)->tme_sparc32_ireg_psr & TME_SPARC32_PSR_EF) == 0 \ - : ((ic)->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_PEF) == 0)) { \ - TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_fp_disabled); \ - } \ - if (__tme_predict_false((ic)->tme_sparc_fpu_mode \ - != TME_SPARC_FPU_MODE_EXECUTE)) { \ - tme_sparc_fpu_exception_check(ic); \ - } \ + if (__tme_predict_false(TME_SPARC_FPU_IS_DISABLED(ic))) { \ + TME_SPARC_INSN_TRAP(TME_SPARC_TRAP(ic,fp_disabled));\ + } \ } while (/* CONSTCOND */ 0) -#define TME_SPARC_INSN_FPU_STORE(size) \ +#define TME_SPARC_INSN_FPU \ do { \ - if (__tme_predict_false((TME_SPARC_VERSION(ic) < 9) \ - ? ((ic)->tme_sparc32_ireg_psr & TME_SPARC32_PSR_EF) == 0 \ - : ((ic)->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_PEF) == 0)) { \ - TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_fp_disabled); \ - } \ - if (__tme_predict_false(((TME_SPARC_FORMAT3_RS1 \ - + TME_SPARC_FORMAT3_RS2) \ - % (size)) != 0)) { \ - TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_mem_address_not_aligned); \ - } \ + TME_SPARC_INSN_FPU_ENABLED; \ if (__tme_predict_false((ic)->tme_sparc_fpu_mode \ - == TME_SPARC_FPU_MODE_EXCEPTION_PENDING)) { \ + != TME_SPARC_FPU_MODE_EXECUTE)) { \ tme_sparc_fpu_exception_check(ic); \ } \ } while (/* CONSTCOND */ 0) -#define TME_SPARC_INSN_ILL \ - TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_illegal_instruction) +#define TME_SPARC_INSN_ILL(ic) \ + TME_SPARC_INSN_TRAP(TME_SPARC_TRAP(ic,illegal_instruction)) /* logging: */ #define TME_SPARC_LOG_HANDLE(ic) \ @@ -283,15 +603,21 @@ _TME_RCSID("$Id: sparc-impl.h,v 1.1.1.1 "mode=%d ", \ (ic)->_tme_sparc_mode); \ } \ + else if (TME_SPARC_VERSION(ic) < 9) { \ + tme_log_part(TME_SPARC_LOG_HANDLE(ic), \ + "pc=%c/0x%08" TME_PRIx32 " ", \ + (TME_SPARC_PRIV(ic) \ + ? 'S' \ + : 'U'), \ + ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC)); \ + } \ else { \ tme_log_part(TME_SPARC_LOG_HANDLE(ic), \ - "pc=%c/0x%08x ", \ + "pc=%c/0x%08" TME_PRIx64 " ", \ (TME_SPARC_PRIV(ic) \ ? 'S' \ : 'U'), \ - ((TME_SPARC_VERSION(ic) < 9) \ - ? ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC)\ - : (tme_uint32_t) ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC)));\ + ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC)); \ } \ do #define tme_sparc_log_finish(ic) \ @@ -305,31 +631,45 @@ _TME_RCSID("$Id: sparc-impl.h,v 1.1.1.1 } tme_sparc_log_finish(ic); \ } while (/* CONSTCOND */ 0) +/* PROM delay factors: */ +#define TME_SPARC_PROM_DELAY_FACTOR_UNCORRECTED ((tme_uint32_t) (0 - (tme_uint32_t) 1)) +#define TME_SPARC_PROM_DELAY_FACTOR_BEST ((tme_uint32_t) (0 - (tme_uint32_t) 2)) +#define TME_SPARC_PROM_DELAY_FACTOR_MIN ((tme_uint32_t) (0 - (tme_uint32_t) 3)) + +/* flags for _tme_sparc_external_check(): */ +#define TME_SPARC_EXTERNAL_CHECK_NULL (0) +#define TME_SPARC_EXTERNAL_CHECK_MUTEX_LOCKED (1 << 0) +#define TME_SPARC_EXTERNAL_CHECK_PCS_UPDATED (1 << 1) + /* miscellaneous: */ #define _TME_SPARC_VERSION(ic) ((ic)->tme_sparc_version) #define _TME_SPARC_NWINDOWS(ic) ((ic)->tme_sparc_nwindows) +#define _TME_SPARC_MEMORY_FLAGS(ic) ((ic)->tme_sparc_memory_flags) #define _TME_SPARC32_PRIV(ic) (((ic)->tme_sparc32_ireg_psr & TME_SPARC32_PSR_S) != 0) #define _TME_SPARC64_PRIV(ic) (((ic)->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_PRIV) != 0) #define TME_SPARC_VERSION(ic) _TME_SPARC_VERSION(ic) #define TME_SPARC_NWINDOWS(ic) _TME_SPARC_NWINDOWS(ic) +#define TME_SPARC_MEMORY_FLAGS(ic) _TME_SPARC_MEMORY_FLAGS(ic) #define TME_SPARC_PRIV(ic) \ ((TME_SPARC_VERSION(ic) < 9) \ ? _TME_SPARC32_PRIV(ic) \ : _TME_SPARC64_PRIV(ic)) -#define TME_SPARC_ASI_DATA(ic) \ - ((TME_SPARC_VERSION(ic) < 9) \ - ? (_TME_SPARC32_PRIV(ic) \ - ? TME_SPARC32_ASI_SD \ - : TME_SPARC32_ASI_UD) \ - : ((ic->tme_sparc64_ireg_pstate & TME_SPARC64_PSTATE_CLE)\ - ? TME_SPARC64_ASI_PRIMARY_LITTLE \ - : TME_SPARC64_ASI_PRIMARY)) /* structures: */ struct tme_sparc; +/* the widest supported sparc register: */ +#ifdef TME_HAVE_INT64_T +typedef tme_uint64_t tme_sparc_ireg_umax_t; +#else /* !TME_HAVE_INT64_T */ +typedef tme_uint32_t tme_sparc_ireg_umax_t; +#endif /* !TME_HAVE_INT64_T */ + /* format 3 instruction functions: */ typedef TME_SPARC_FORMAT3_DECL((*_tme_sparc32_format3), tme_uint32_t); +#ifdef TME_HAVE_INT64_T +typedef TME_SPARC_FORMAT3_DECL((*_tme_sparc64_format3), tme_uint64_t); +#endif /* TME_HAVE_INT64_T */ /* a sparc deferred-trap queue: */ struct tme_sparc_trapqueue { @@ -341,6 +681,107 @@ struct tme_sparc_trapqueue { tme_uint32_t tme_sparc_trapqueue_insn; }; +/* a sparc load/store: */ +struct tme_sparc_ls { + + /* this maps an address for the bus: */ + void (*tme_sparc_ls_address_map) _TME_P((struct tme_sparc *, struct tme_sparc_ls *)); + + /* the current slow cycle function: */ + void (*tme_sparc_ls_cycle) _TME_P((struct tme_sparc *, struct tme_sparc_ls *)); + + /* a pointer to the rd register: */ + union { + tme_uint32_t *_tme_sparc_ls_rd_u_32; +#define tme_sparc_ls_rd32 _tme_sparc_ls_rd_u._tme_sparc_ls_rd_u_32 +#ifdef TME_HAVE_INT64_T + tme_uint64_t *_tme_sparc_ls_rd_u_64; +#define tme_sparc_ls_rd64 _tme_sparc_ls_rd_u._tme_sparc_ls_rd_u_64 +#endif /* TME_HAVE_INT64_T */ + } _tme_sparc_ls_rd_u; + + /* a pointer to the TLB entry: */ + struct tme_sparc_tlb *tme_sparc_ls_tlb; + + /* the current address: */ + union { + tme_uint32_t _tme_sparc_ls_address_u_32; +#define tme_sparc_ls_address32 _tme_sparc_ls_address_u._tme_sparc_ls_address_u_32 +#ifdef TME_HAVE_INT64_T + tme_uint64_t _tme_sparc_ls_address_u_64; +#define tme_sparc_ls_address64 _tme_sparc_ls_address_u._tme_sparc_ls_address_u_64 +#endif /* TME_HAVE_INT64_T */ + } _tme_sparc_ls_address_u; + + /* the context and ASI mask: */ + tme_bus_context_t tme_sparc_ls_context; + tme_uint32_t tme_sparc_ls_asi_mask; + + /* the index of the TLB entry: */ + tme_uint32_t tme_sparc_ls_tlb_i; + + /* the lsinfo: */ + tme_uint32_t tme_sparc_ls_lsinfo; + + /* any fault information: */ + tme_uint32_t tme_sparc_ls_faults; + + /* the current size: */ + tme_uint8_t tme_sparc_ls_size; + + /* the current offset in the memory buffer: */ + tme_uint8_t tme_sparc_ls_buffer_offset; + + /* some current state of the operation: */ + tme_uint8_t tme_sparc_ls_state; + + /* a mapping TLB entry: */ + struct tme_bus_tlb tme_sparc_ls_tlb_map; + + /* a bus cycle structure: */ + struct tme_bus_cycle tme_sparc_ls_bus_cycle; +}; + +/* ASI handlers: */ +typedef void (*_tme_sparc_ls_asi_handler) _TME_P((struct tme_sparc *, struct tme_sparc_ls *)); + +#if TME_HAVE_RECODE + +/* this is the type used for keys in the recode source address hash. + if the widest recode guest is only 32 bits, we only need a + tme_uint32_t, because a sparc32 recode guest can only make 32-bit + guest addresses. + + otherwise, we use an unsigned long, which we assume is at least as + wide as the address size of the *host*. NB that this may be + narrower than the address size of a sparc guest, but since source + address hash keys are for guest addresses that are cacheable, which + correspond to host addresses, this is fine (the source address hash + key is essentially the guest address mapped into the host address + space): */ +#if TME_RECODE_SIZE_GUEST_MAX <= TME_RECODE_SIZE_32 +typedef tme_uint32_t tme_sparc_recode_src_key_t; +#else /* TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */ +typedef unsigned long tme_sparc_recode_src_key_t; +#endif /* TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */ + +/* a recode cacheable source memory: */ +struct tme_sparc_recode_cacheable { + + /* the cacheable contents and size: */ + const tme_shared tme_uint8_t *tme_sparc_recode_cacheable_contents; + unsigned long tme_sparc_recode_cacheable_size; + + /* the source address hash key for the first instruction word in the + cacheable contents: */ + tme_sparc_recode_src_key_t tme_sparc_recode_cacheable_src_key_first; + + /* the valids bitmap for this cacheable: */ + tme_shared tme_uint8_t *tme_sparc_recode_cacheable_valids; +}; + +#endif /* TME_HAVE_RECODE */ + /* the sparc state: */ struct tme_sparc { @@ -350,18 +791,29 @@ struct tme_sparc { to their contents: */ struct tme_ic tme_sparc_ic; - /* the current window pointer register offset: */ - unsigned int tme_sparc_cwp_offset; + /* the cycles scaling: */ + tme_misc_cycles_scaling_t tme_sparc_cycles_scaling; + tme_misc_cycles_scaling_t tme_sparc_cycles_unscaling; + + /* the number of scaled cycles per microsecond: */ + tme_uint32_t tme_sparc_cycles_scaled_per_usec; + + /* the register offsets for the four groups of eight registers: */ + tme_int8_t tme_sparc_reg8_offset[4]; /* the architecture version, and number of windows: */ unsigned int tme_sparc_version; unsigned int tme_sparc_nwindows; + /* v9 constants: */ + unsigned int tme_sparc64_maxtl; + /* the backpointer to our element: */ struct tme_element *tme_sparc_element; - /* our bus connection. if both are defined, the sparc bus connection - is an adaptation layer for the generic bus connection: */ + /* our bus connection. the sparc bus connection may be an + adaptation layer for another bus connection type: */ + struct tme_upa_bus_connection *_tme_upa_bus_connection; struct tme_sparc_bus_connection *_tme_sparc_bus_connection; struct tme_bus_connection *_tme_sparc_bus_generic; @@ -375,64 +827,247 @@ struct tme_sparc { tme_uint32_t tme_sparc_asi_mask_insn; tme_uint32_t tme_sparc_asi_mask_data; + /* the implementation-dependent data: */ + union { + const _tme_sparc32_format3 *_tme_sparc_execute_opmap_u_32; +#define _tme_sparc32_execute_opmap _tme_sparc_execute_opmap_u._tme_sparc_execute_opmap_u_32 +#ifdef TME_HAVE_INT64_T + const _tme_sparc64_format3 *_tme_sparc_execute_opmap_u_64; +#define _tme_sparc64_execute_opmap _tme_sparc_execute_opmap_u._tme_sparc_execute_opmap_u_64 +#endif /* TME_HAVE_INT64_T */ + } _tme_sparc_execute_opmap_u; + tme_uint32_t (*_tme_sparc_ls_asi_misaligned) _TME_P((struct tme_sparc *, tme_uint32_t)); + const _tme_sparc_ls_asi_handler *_tme_sparc_ls_asi_handlers; +#ifdef TME_HAVE_INT64_T + tme_uint64_t tme_sparc64_rstvaddr; +#endif /* TME_HAVE_INT64_T */ + /* the implementation-dependent functions: */ void (*_tme_sparc_execute) _TME_P((struct tme_sparc *)); - tme_uint32_t (*_tme_sparc_bus_fault) _TME_P((struct tme_sparc *, const struct tme_bus_cycle *, unsigned int, int)); - tme_uint32_t (*_tme_sparc_fetch_slow) _TME_P((struct tme_sparc *, int)); tme_uint32_t (*_tme_sparc_fpu_ver) _TME_P((struct tme_sparc *, const char *, char **)); + void (*_tme_sparc_external_check) _TME_P((struct tme_sparc *, int)); + void (*_tme_sparc_ls_address_map) _TME_P((struct tme_sparc *, struct tme_sparc_ls *)); + void (*_tme_sparc_ls_bus_cycle) _TME_P((const struct tme_sparc *, struct tme_sparc_ls *)); + void (*_tme_sparc_ls_bus_fault) _TME_P((struct tme_sparc *, struct tme_sparc_ls *, int)); + void (*_tme_sparc_ls_trap) _TME_P((struct tme_sparc *, struct tme_sparc_ls *)); + int (*_tme_sparc_tlb_fill) _TME_P((struct tme_bus_connection *, + struct tme_bus_tlb *, + tme_bus_addr_t, + unsigned int)); +#ifdef TME_HAVE_INT64_T + void (*_tme_sparc_upa_interrupt) _TME_P((struct tme_upa_bus_connection *, + tme_uint32_t, + const tme_uint64_t *, + struct tme_completion *)); +#endif /* TME_HAVE_INT64_T */ + void (*_tme_sparc64_update_pstate) _TME_P((struct tme_sparc *, tme_uint32_t, tme_uint32_t)); + + /* the runlength state: */ + struct tme_runlength tme_sparc_runlength; + tme_uint32_t tme_sparc_runlength_update_period; + tme_uint32_t tme_sparc_runlength_update_next; + + /* the instruction burst counts, and the remaining burst: */ +#define _tme_sparc_instruction_burst tme_sparc_runlength.tme_runlength_value + tme_uint32_t _tme_sparc_instruction_burst_idle; + tme_uint32_t _tme_sparc_instruction_burst_remaining; + unsigned int _tme_sparc_instruction_burst_other; - /* the instruction burst count, and the remaining burst: */ - unsigned int _tme_sparc_instruction_burst; - unsigned int _tme_sparc_instruction_burst_remaining; - - /* any currently busy instruction TLB entry: */ - struct tme_sparc_tlb *_tme_sparc_itlb_busy; + /* the token for any currently busy instruction TLB entry: */ + struct tme_token *_tme_sparc_itlb_current_token; /* instruction information: */ tme_uint32_t _tme_sparc_insn; - /* the data and instruction TLB entry sets: */ - union { - struct tme_sparc_tlb * tme_shared _tme_sparc_dtlb_array_u_sparc; - struct tme_bus_tlb * tme_shared _tme_sparc_dtlb_array_u_bus; - } _tme_sparc_dtlb_array_u; -#define _tme_sparc_dtlb_array _tme_sparc_dtlb_array_u._tme_sparc_dtlb_array_u_sparc -#define _tme_sparc_dtlb_array_bus _tme_sparc_dtlb_array_u._tme_sparc_dtlb_array_u_bus - union { - struct tme_sparc_tlb * tme_shared _tme_sparc_itlb_array_u_sparc; - struct tme_bus_tlb * tme_shared _tme_sparc_itlb_array_u_bus; - } _tme_sparc_itlb_array_u; -#define _tme_sparc_itlb_array _tme_sparc_itlb_array_u._tme_sparc_itlb_array_u_sparc -#define _tme_sparc_itlb_array_bus _tme_sparc_itlb_array_u._tme_sparc_itlb_array_u_bus - tme_rwlock_t _tme_sparc_tlb_rwlock; + /* memory flags: */ + tme_uint32_t tme_sparc_memory_flags; + + /* ASIs: */ + struct { + tme_uint8_t tme_sparc_asi_mask_flags; + tme_uint8_t tme_sparc_asi_handler; + } tme_sparc_asis[0x100]; + + /* contexts: */ + tme_bus_context_t tme_sparc_memory_context_max; + tme_bus_context_t tme_sparc_memory_context_default; + tme_uint32_t tme_sparc_memory_context_primary; + tme_uint32_t tme_sparc_memory_context_secondary; - /* the external request lines: */ + /* the external interface: */ tme_mutex_t tme_sparc_external_mutex; tme_cond_t tme_sparc_external_cond; - unsigned int tme_sparc_external_reset; - unsigned int tme_sparc_external_halt; - unsigned int tme_sparc_external_ipl; + tme_memory_atomic_flag_t tme_sparc_external_flag; + tme_memory_atomic_flag_t tme_sparc_external_reset_asserted; + tme_memory_atomic_flag_t tme_sparc_external_reset_negated; + tme_memory_atomic_flag_t tme_sparc_external_halt_asserted; + tme_memory_atomic_flag_t tme_sparc_external_halt_negated; + tme_memory_atomic_flag_t tme_sparc_external_bg_asserted; + tme_shared tme_uint8_t tme_sparc_external_ipl; + tme_rwlock_t tme_sparc_external_ipl_rwlock; /* the slow load/store buffer: */ - tme_uint8_t tme_sparc_memory_buffer[sizeof(tme_uint32_t) * 2]; + union { + tme_uint8_t tme_sparc_memory_buffer8s[64]; + tme_uint16_t tme_sparc_memory_buffer16s[32]; + tme_uint32_t tme_sparc_memory_buffer32s[16]; +#ifdef TME_HAVE_INT64_T + tme_uint64_t tme_sparc_memory_buffer64s[8]; +#endif /* TME_HAVE_INT64_T */ + } tme_sparc_memory_buffer; /* any FPU state: */ struct tme_ieee754_ctl tme_sparc_fpu_ieee754_ctl; _tme_const struct tme_ieee754_ops *tme_sparc_fpu_ieee754_ops; _tme_const struct tme_ieee754_ops *tme_sparc_fpu_ieee754_ops_user; _tme_const struct tme_ieee754_ops *tme_sparc_fpu_ieee754_ops_strict; - struct tme_float tme_sparc_fpu_fpregs[32]; - unsigned int tme_sparc_fpu_fpreg_sizes[32]; + struct tme_float tme_sparc_fpu_fpregs[TME_SPARC_FPU_FPREG_NUMBER_UNDEF]; + unsigned int tme_sparc_fpu_fpreg_sizes[TME_SPARC_FPU_FPREG_NUMBER_UNDEF]; tme_uint32_t tme_sparc_fpu_fsr; + tme_uint32_t tme_sparc_fpu_xfsr; struct tme_sparc_trapqueue tme_sparc_fpu_fq[1]; unsigned int tme_sparc_fpu_mode; unsigned int tme_sparc_fpu_flags; int tme_sparc_fpu_incomplete_abort; - /* any idle type, and idle type state: */ + /* any VIS state: */ + tme_uint32_t tme_sparc_vis_ls_fault_illegal; + tme_uint8_t tme_sparc_vis_gsr; + + /* the idle state: */ + tme_uint8_t tme_sparc_idle_marks; unsigned int tme_sparc_idle_type; - tme_uint32_t tme_sparc_idle_type_pc32; - tme_uint32_t tme_sparc_idle_type_pc64; + union { + tme_uint32_t tme_sparc_idle_pcs_32[4]; +#ifdef TME_HAVE_INT64_T + tme_uint64_t tme_sparc_idle_pcs_64[4]; +#endif /* TME_HAVE_INT64_T */ + } tme_sparc_idle_pcs; +#define tme_sparc_idle_pcs_32 tme_sparc_idle_pcs.tme_sparc_idle_pcs_32 +#define tme_sparc_idle_pcs_64 tme_sparc_idle_pcs.tme_sparc_idle_pcs_64 + + /* the address mask: */ + tme_sparc_ireg_umax_t tme_sparc_address_mask; + + /* the PROM delay factor: */ + tme_uint32_t tme_sparc_prom_delay_factor; + + /* the log2 of the TLB page size: */ + unsigned int tme_sparc_tlb_page_size_log2; + + /* the data and instruction TLB entry sets: */ + struct tme_sparc_tlb tme_sparc_tlbs[_TME_SPARC_TLB_COUNT]; + + /* either tokens or recode TLB entries for the sparc TLB entries: */ + union { + struct tme_token _tme_sparc_tlb_tokens_u_tokens[_TME_SPARC_TLB_COUNT]; +#define tme_sparc_tlb_tokens _tme_sparc_tlb_tokens_u._tme_sparc_tlb_tokens_u_tokens +#if TME_HAVE_RECODE + struct tme_recode_tlb_c16_a32 _tme_sparc_tlb_tokens_u_tlb32s[_TME_SPARC_TLB_COUNT]; +#define tme_sparc_recode_tlb32s _tme_sparc_tlb_tokens_u._tme_sparc_tlb_tokens_u_tlb32s +#if TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 + struct tme_recode_tlb_c16_a64 _tme_sparc_tlb_tokens_u_tlb64s[_TME_SPARC_TLB_COUNT]; +#define tme_sparc_recode_tlb64s _tme_sparc_tlb_tokens_u._tme_sparc_tlb_tokens_u_tlb64s +#endif /* TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */ +#endif /* TME_HAVE_RECODE */ + } _tme_sparc_tlb_tokens_u; + + /* timing information: */ + tme_uint8_t tme_sparc_timing_loop_cycles_each; + tme_int8_t tme_sparc_timing_loop_addend; + tme_uint8_t tme_sparc_timing_loop_branch_taken_max; + tme_sparc_ireg_umax_t tme_sparc_timing_loop_branch_taken_count_max_m1; + union tme_value64 tme_sparc_timing_loop_start; + union tme_value64 tme_sparc_timing_loop_finish; + +#if TME_HAVE_RECODE + + /* the recode IC: */ + struct tme_recode_ic *tme_sparc_recode_ic; + + /* the register window base offsets. %r8 through %r23 use window + zero, %r24 through %r31 use window one, and %r0 through %r7 use + window two: */ + tme_int32_t tme_sparc_recode_window_base_offsets[3]; + + /* the flags thunks: */ + const struct tme_recode_flags_thunk *tme_sparc_recode_flags_thunk_add; + const struct tme_recode_flags_thunk *tme_sparc_recode_flags_thunk_sub; + const struct tme_recode_flags_thunk *tme_sparc_recode_flags_thunk_logical; + const struct tme_recode_flags_thunk *tme_sparc_recode_flags_thunk_rcc; + + /* the conditions thunks: */ + const struct tme_recode_conds_thunk *tme_sparc_recode_conds_thunk_icc; + const struct tme_recode_conds_thunk *tme_sparc_recode_conds_thunk_xcc; + const struct tme_recode_conds_thunk *tme_sparc_recode_conds_thunk_rcc; + + /* the read/write thunks: */ + const struct tme_recode_rw_thunk *tme_sparc_recode_rw_thunks[128]; + + /* the current read/write TLB flags: */ + tme_uint32_t tme_sparc_recode_rw_tlb_flags; + + /* the current chain TLB flags: */ + tme_uint32_t tme_sparc_recode_chain_tlb_flags; + + /* the chain return address stack: */ + tme_recode_ras_entry_t _tme_sparc_recode_chain_ras[16]; + tme_uint32_t _tme_sparc_recode_chain_ras_pointer; + + /* the recode cacheable source memories: */ + struct tme_sparc_recode_cacheable tme_sparc_recode_cacheables[TME_SPARC_RECODE_CACHEABLES_MAX]; + + /* the most recently added cacheable: */ + struct tme_sparc_recode_cacheable *tme_sparc_recode_cacheable_first; + + /* the bitmap of active cacheable recode pages: */ + tme_uint8_t *tme_sparc_recode_cacheable_actives; + + /* the recode source hash: */ + /* NB: conceptually, each entry in the recode source address hash is + one tme_sparc_recode_src_key_t and one tme_recode_thunk_off_t. + since these types may be different sizes, to guarantee that the + recode source address hash is packed, each element of this recode + source address hash array covers this many entries: */ +#define TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT \ + ((sizeof(tme_sparc_recode_src_key_t) \ + + (sizeof(tme_recode_thunk_off_t) - 1)) \ + / sizeof(tme_recode_thunk_off_t)) + struct { + + /* the source address hash keys: */ + tme_sparc_recode_src_key_t tme_sparc_recode_src_hash_keys[TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]; + + /* if bit zero is set, the remaining bits of the hash value are + the hit count for the program counter, otherwise, the entire + hash value is the offset of the instructions thunk for the + program counter: */ + tme_recode_thunk_off_t tme_sparc_recode_src_hash_values[TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]; + + } tme_sparc_recode_src_hash[(TME_SPARC_RECODE_SRC_HASH_MODULUS + * TME_SPARC_RECODE_SRC_HASH_SIZE_SET) + / TME_SPARC_RECODE_SRC_HASH_SIZE_ELEMENT]; + + /* an instructions group: */ + struct tme_recode_insns_group tme_sparc_recode_insns_group; + + /* the recode insns buffer: */ + struct tme_recode_insn tme_sparc_recode_insns[TME_RECODE_INSNS_THUNK_INSNS_MAX]; + +#ifdef _TME_SPARC_RECODE_VERIFY + + /* the last PC to replay, or zero if instructions are not being + replayed: */ + tme_recode_uguest_t tme_sparc_recode_verify_replay_last_pc; + + /* the size of the sparc state to verify, and the sparc state total + size: */ + unsigned long tme_sparc_recode_verify_ic_size; + unsigned long tme_sparc_recode_verify_ic_size_total; + +#endif /* _TME_SPARC_RECODE_VERIFY */ + +#endif /* TME_HAVE_RECODE */ #ifdef _TME_SPARC_STATS /* statistics: */ @@ -442,7 +1077,7 @@ struct tme_sparc { tme_uint64_t tme_sparc_stats_insns_total; /* the total number of instructions fetched slowly: */ - tme_uint64_t tme_sparc_stats_fetch_slow; + tme_uint64_t tme_sparc_stats_insns_slow; /* the total number of redispatches: */ tme_uint64_t tme_sparc_stats_redispatches; @@ -450,14 +1085,52 @@ struct tme_sparc { /* the total number of data memory operations: */ tme_uint64_t tme_sparc_stats_memory_total; + /* the total number of ITLB maps: */ + tme_uint64_t tme_sparc_stats_itlb_map; + + /* the total number of DTLB map: */ + tme_uint64_t tme_sparc_stats_dtlb_map; + /* the total number of ITLB fills: */ tme_uint64_t tme_sparc_stats_itlb_fill; /* the total number of DTLB fills: */ tme_uint64_t tme_sparc_stats_dtlb_fill; +#if TME_HAVE_RECODE + + /* the total number of calls to tme_sparc_recode(): */ + tme_uint64_t tme_sparc_stats_recode_calls; + + /* the total number of active recode page invalidations: */ + tme_uint64_t tme_sparc_stats_recode_page_invalids; + + /* the total number of recode source hash probes: */ + tme_uint64_t tme_sparc_stats_recode_source_hash_probes; + + /* the total number of recode source hash misses: */ + tme_uint64_t tme_sparc_stats_recode_source_hash_misses; + + /* the total number of instructions executed in thunks: */ + tme_uint64_t tme_sparc_stats_recode_insns_total; + + /* the total number of various assists: */ + tme_uint64_t tme_sparc_stats_recode_assist; + tme_uint64_t tme_sparc_stats_recode_assist_full; + tme_uint64_t tme_sparc_stats_recode_assist_ld; + tme_uint64_t tme_sparc_stats_recode_assist_st; + + /* the total number of assists by opcode: */ + tme_uint64_t tme_sparc_stats_recode_assist_opcode[128]; + +#endif /* TME_HAVE_RECODE */ + } tme_sparc_stats; -#endif /* _TME_SPARC_STATS */ +#define TME_SPARC_STAT_N(ic, x, n) do { (ic)->tme_sparc_stats.x += (n); } while (/* CONSTCOND */ 0) +#else /* !_TME_SPARC_STATS */ +#define TME_SPARC_STAT_N(ic, x, n) do { } while (/* CONSTCOND */ 0 && (ic) && (n)) +#endif /* !_TME_SPARC_STATS */ +#define TME_SPARC_STAT(ic, x) TME_SPARC_STAT_N(ic, x, 1) }; /* globals: */ @@ -465,21 +1138,31 @@ extern const tme_uint8_t _tme_sparc_cond extern const tme_uint8_t _tme_sparc_conds_fcc[4]; /* prototypes: */ +void tme_sparc_sync_init _TME_P((struct tme_sparc *)); int tme_sparc_new _TME_P((struct tme_sparc *, const char * const *, const void *, char **)); void tme_sparc_redispatch _TME_P((struct tme_sparc *)); void tme_sparc_do_reset _TME_P((struct tme_sparc *)); void tme_sparc_do_idle _TME_P((struct tme_sparc *)); -void tme_sparc32_external_check _TME_P((struct tme_sparc *)); -tme_uint32_t tme_sparc32_fetch_slow _TME_P((struct tme_sparc *, int)); +void tme_sparc32_external_check _TME_P((struct tme_sparc *, int)); +struct tme_sparc_tlb *tme_sparc_itlb_current _TME_P((struct tme_sparc *)); +tme_uint32_t tme_sparc_insn_peek _TME_P((struct tme_sparc *, tme_sparc_ireg_umax_t)); tme_uint32_t tme_sparc_fetch_nearby _TME_P((struct tme_sparc *, long)); void tme_sparc_callout_unlock _TME_P((struct tme_sparc *)); void tme_sparc_callout_relock _TME_P((struct tme_sparc *)); +/* load/store support: */ +void tme_sparc_ls_bus_fault _TME_P((struct tme_sparc *, struct tme_sparc_ls *, int)); +void tme_sparc32_ls_address_map _TME_P((struct tme_sparc *, struct tme_sparc_ls *)); +void tme_sparc32_ls_bus_cycle _TME_P((const struct tme_sparc *, struct tme_sparc_ls *)); +void tme_sparc32_ls_trap _TME_P((struct tme_sparc *, struct tme_sparc_ls *)); + /* trap support: */ -void tme_sparc32_trap_preinstruction _TME_P((struct tme_sparc *, unsigned int)); +void tme_sparc32_trap_preinstruction _TME_P((struct tme_sparc *, tme_uint32_t)); void tme_sparc32_trap _TME_P((struct tme_sparc *, tme_uint32_t)); -tme_uint32_t tme_sparc32_bus_fault _TME_P((struct tme_sparc *, const struct tme_bus_cycle *, unsigned int, int)); +void tme_sparc64_trap_preinstruction _TME_P((struct tme_sparc *, tme_uint32_t)); void tme_sparc64_trap _TME_P((struct tme_sparc *, tme_uint32_t)); +void tme_sparc64_trap_error_state _TME_P((struct tme_sparc *)); +void tme_sparc_nnpc_trap _TME_P((struct tme_sparc *, tme_uint32_t)); /* FPU support: */ int tme_sparc_fpu_new _TME_P((struct tme_sparc *, const char * const *, int *, int *, char **)); @@ -487,33 +1170,78 @@ void tme_sparc_fpu_reset _TME_P((struct void tme_sparc_fpu_usage _TME_P((struct tme_sparc *, char **)); void tme_sparc_fpu_strict _TME_P((struct tme_sparc_bus_connection *, unsigned int)); void tme_sparc_fpu_exception_check _TME_P((struct tme_sparc *)); -int tme_sparc_fpu_fpreg_aligned _TME_P((struct tme_sparc *, unsigned int, unsigned int)); +unsigned int tme_sparc_fpu_fpreg_decode _TME_P((struct tme_sparc *, unsigned int, unsigned int)); void tme_sparc_fpu_fpreg_format _TME_P((struct tme_sparc *, unsigned int, unsigned int)); void tme_sparc_fpu_fpop1 _TME_P((struct tme_sparc *)); void tme_sparc_fpu_fpop2 _TME_P((struct tme_sparc *)); - -/* verification: */ -void tme_sparc_verify_hook _TME_P((void)); -#ifdef _TME_SPARC_VERIFY -void tme_sparc_verify_init _TME_P((void)); -void tme_sparc_verify_begin _TME_P((const struct tme_sparc *, const tme_uint8_t *)); -void tme_sparc_verify_mem_any _TME_P((const struct tme_sparc *, - unsigned int, tme_uint32_t, - tme_uint8_t *, int, int)); -void tme_sparc_verify_end_branch _TME_P((const struct tme_sparc *, tme_uint32_t)); -void tme_sparc_verify_end _TME_P((const struct tme_sparc *, - void (*)(struct tme_sparc *, void *, void *))); -#else /* _TME_SPARC_VERIFY */ -#define tme_sparc_verify_init() do { } while (/* CONSTCOND */ 0) -#define tme_sparc_verify_begin(ic, s) do { } while (/* CONSTCOND */ 0) -#define tme_sparc_verify_mem_any(ic, fc, a, v, c, rw) do { } while (/* CONSTCOND */ 0) -#define tme_sparc_verify_end_branch(ic, pc) do { } while (/* CONSTCOND */ 0) -#define tme_sparc_verify_end(ic, f) do { } while (/* CONSTCOND */ 0) -#define tme_sparc_verify_hook() do { } while (/* CONSTCOND */ 0) -#endif /* _TME_SPARC_VERIFY */ -#define tme_sparc_verify_mem8(ic, fc, a, v, rw) tme_sparc_verify_mem_any(ic, fc, a, (tme_uint8_t *) &(v), -sizeof(tme_uint8_t), rw) -#define tme_sparc_verify_mem16(ic, fc, a, v, rw) tme_sparc_verify_mem_any(ic, fc, a, (tme_uint8_t *) &(v), -sizeof(tme_uint16_t), rw) -#define tme_sparc_verify_mem32(ic, fc, a, v, rw) tme_sparc_verify_mem_any(ic, fc, a, (tme_uint8_t *) &(v), -sizeof(tme_uint32_t), rw) +#ifdef TME_HAVE_INT64_T +void tme_sparc_vis _TME_P((struct tme_sparc *)); +void tme_sparc64_vis_ls_asi_pst _TME_P((struct tme_sparc *, struct tme_sparc_ls *)); +void tme_sparc64_vis_ls_asi_fl _TME_P((struct tme_sparc *, struct tme_sparc_ls *)); +tme_uint32_t tme_sparc64_vis_ls_asi_misaligned _TME_P((struct tme_sparc *, tme_uint32_t)); +#endif /* TME_HAVE_INT64_T */ + +/* timing support: */ +int tme_sparc_timing_loop_ok _TME_P((tme_uint32_t, tme_uint32_t)); +void tme_sparc_timing_loop_start _TME_P((struct tme_sparc *)); +void tme_sparc_timing_loop_finish _TME_P((struct tme_sparc *)); +#if TME_HAVE_RECODE +tme_recode_uguest_t tme_sparc_timing_loop_assist _TME_P((struct tme_ic *, tme_recode_uguest_t, tme_recode_uguest_t)); +#endif /* TME_HAVE_RECODE */ + +/* recode support: */ +void tme_sparc_recode_init _TME_P((struct tme_sparc *)); +#if TME_HAVE_RECODE +tme_recode_thunk_off_t tme_sparc_recode _TME_P((struct tme_sparc *, const struct tme_sparc_tlb *, const tme_shared tme_uint32_t *)); +void tme_sparc_recode_invalidate_all _TME_P((struct tme_sparc *)); +tme_recode_uguest_t tme_sparc32_recode_insn_assist_redispatch _TME_P((struct tme_sparc *)); +tme_uint32_t tme_sparc32_recode_insn_current _TME_P((const struct tme_sparc *)); +void tme_sparc32_recode_chain_tlb_update _TME_P((struct tme_sparc *, const struct tme_sparc_ls *)); +void tme_sparc32_recode_ls_tlb_update _TME_P((struct tme_sparc *, const struct tme_sparc_ls *)); +#if TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 +tme_recode_uguest_t tme_sparc64_recode_insn_assist_redispatch _TME_P((struct tme_sparc *)); +tme_uint32_t tme_sparc64_recode_insn_current _TME_P((const struct tme_sparc *)); +void tme_sparc64_recode_chain_tlb_update _TME_P((struct tme_sparc *, const struct tme_sparc_ls *)); +void tme_sparc64_recode_ls_tlb_update _TME_P((struct tme_sparc *, const struct tme_sparc_ls *)); +#endif /* TME_RECODE_SIZE_GUEST_MAX > TME_RECODE_SIZE_32 */ +#define TME_SPARC_RECODE_VERIFY_MEM_SIZE_MASK (0x7) +#define TME_SPARC_RECODE_VERIFY_MEM_LOAD TME_BIT(3) +#define TME_SPARC_RECODE_VERIFY_MEM_STORE TME_BIT(4) +#define TME_SPARC_RECODE_VERIFY_MEM_CAS TME_BIT(5) +#ifdef _TME_SPARC_RECODE_VERIFY +void tme_sparc_recode_verify_begin _TME_P((struct tme_sparc *)); +void tme_sparc_recode_verify_mem _TME_P((struct tme_sparc *, void *, unsigned int, tme_recode_uguest_t, unsigned int)); +void tme_sparc_recode_verify_mem_load _TME_P((struct tme_sparc *, const void *)); +void tme_sparc_recode_verify_mem_block _TME_P((struct tme_sparc *, unsigned int)); +void tme_sparc_recode_verify_reg_tick _TME_P((struct tme_sparc *, void *)); +void tme_sparc_recode_verify_reg_tick_now _TME_P((struct tme_sparc *, const void *)); +void tme_sparc_recode_verify_end _TME_P((struct tme_sparc *, tme_uint32_t)); +void tme_sparc_recode_verify_end_preinstruction _TME_P((struct tme_sparc *)); +#define tme_sparc_recode_verify_replay_last_pc(ic) ((ic)->tme_sparc_recode_verify_replay_last_pc) +#define TME_SPARC_RECODE_VERIFY_PC_NONE (1) +#endif /* _TME_SPARC_RECODE_VERIFY */ +#else /* !TME_HAVE_RECODE */ +#define tme_sparc_recode_invalidate_all(ic) do { } while (/* CONSTCOND */ 0 && (ic)) +#endif /* !TME_HAVE_RECODE */ +#ifndef _TME_SPARC_RECODE_VERIFY +#define tme_sparc_recode_verify_begin(ic) \ + do { } while (/* CONSTCOND */ 0 && (ic)) +#define tme_sparc_recode_verify_mem(ic, rd, asi, addr, flags) \ + do { } while (/* CONSTCOND */ 0 && (ic) && (rd) && (asi) && (addr)) +#define tme_sparc_recode_verify_mem_load(ic, rd) \ + do { } while (/* CONSTCOND */ 0 && (ic) && (rd)) +#define tme_sparc_recode_verify_mem_block(ic, flags) \ + do { } while (/* CONSTCOND */ 0 && (ic)) +#define tme_sparc_recode_verify_reg_tick(ic, rd) \ + do { } while (/* CONSTCOND */ 0 && (ic) && (rd)) +#define tme_sparc_recode_verify_reg_tick_now(ic, rd) \ + do { } while (/* CONSTCOND */ 0 && (ic) && *(rd)) +#define tme_sparc_recode_verify_end(ic, trap) \ + do { } while (/* CONSTCOND */ 0 && (ic) && (trap)) +#define tme_sparc_recode_verify_end_preinstruction(ic) \ + do { } while (/* CONSTCOND */ 0 && (ic)) +#define tme_sparc_recode_verify_replay_last_pc(ic) (0) +#endif /* !_TME_SPARC_RECODE_VERIFY */ /* instruction functions: */ TME_SPARC_FORMAT3_DECL(tme_sparc32_illegal, tme_uint32_t); @@ -541,6 +1269,24 @@ TME_SPARC_FORMAT3_DECL(tme_sparc32_ticc, TME_SPARC_FORMAT3_DECL(tme_sparc32_stdfq, tme_uint32_t); TME_SPARC_FORMAT3_DECL(tme_sparc32_fpop1, tme_uint32_t); TME_SPARC_FORMAT3_DECL(tme_sparc32_fpop2, tme_uint32_t); +#ifdef TME_HAVE_INT64_T +TME_SPARC_FORMAT3_DECL(tme_sparc64_movcc, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_movr, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_tcc, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_save_restore, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_return, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_saved_restored, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_flushw, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_prefetch, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_rdpr, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_wrpr, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_rdasr, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_wrasr, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_done_retry, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_fpop1, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_fpop2, tme_uint64_t); +TME_SPARC_FORMAT3_DECL(tme_sparc64_illegal_instruction, tme_uint64_t); +#endif /* TME_HAVE_INT64_T */ /* the automatically-generated header information: */ #include