mirror of
https://github.com/phabrics/Run-Sun3-SunOS-4.1.1.git
synced 2026-04-29 19:12:58 -04:00
291 lines
12 KiB
C
291 lines
12 KiB
C
/* $Id: sparc.h,v 1.3 2010/06/05 19:37:56 fredette Exp $ */
|
|
|
|
/* tme/ic/sparc.h - public header file for SPARC emulation */
|
|
|
|
/*
|
|
* Copyright (c) 2005 Matt Fredette
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by Matt Fredette.
|
|
* 4. The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef _TME_IC_SPARC_H
|
|
#define _TME_IC_SPARC_H
|
|
|
|
#include <tme/common.h>
|
|
_TME_RCSID("$Id: sparc.h,v 1.3 2010/06/05 19:37:56 fredette Exp $");
|
|
|
|
/* includes: */
|
|
#include <tme/element.h>
|
|
#include <tme/generic/bus.h>
|
|
|
|
/* macros: */
|
|
|
|
/* the sparc32 address spaces: */
|
|
#define TME_SPARC32_ASI_UI (0x08)
|
|
#define TME_SPARC32_ASI_SI (0x09)
|
|
#define TME_SPARC32_ASI_UD (0x0A)
|
|
#define TME_SPARC32_ASI_SD (0x0B)
|
|
|
|
/* common sparc64 address space identifier flags: */
|
|
#define TME_SPARC64_ASI_FLAG_SECONDARY (0x01)
|
|
#define TME_SPARC64_ASI_FLAG_NO_FAULT (0x02)
|
|
#define TME_SPARC64_ASI_FLAG_LITTLE (0x08)
|
|
#define TME_SPARC64_ASI_FLAG_UNRESTRICTED (0x80)
|
|
|
|
/* the sparc address space masks: */
|
|
/* bits 24 through 31 must be zero - except when
|
|
TME_SPARC_ASI_MASK_FLAG_UNDEF is set, which is what makes an ASI
|
|
mask undefined.
|
|
|
|
bits 16 through 23 are the original ASI.
|
|
|
|
ASIs are divided into two categories: special and normal. an
|
|
address space mask from a special ASI never matches an address
|
|
space mask from a normal ASI, and vice-versa.
|
|
|
|
if bit 15 is set, the ASI is special. an address space mask from a
|
|
special ASI never matches an address space mask from a different
|
|
ASI.
|
|
|
|
if bit 15 is clear, the ASI is normal. an address space mask from
|
|
a normal ASI may match address space masks from different normal
|
|
ASIs.
|
|
|
|
each of the bits eight through 14 identifies an address
|
|
translation. an address translation is usually the combination of
|
|
an address space with privilege.
|
|
|
|
an address space mask generated by a memory instruction has exactly
|
|
one of these bits set, since the instruction's ASI+privilege
|
|
combination can translate addresses in only one way. an address
|
|
space mask generated from an MMU mapping has at least one of these
|
|
bits set, for the ASI+privilege from the instruction that caused
|
|
the mapping lookup. if the same mapping is also valid for other
|
|
ASI+privilege combinations that can be added to the address space
|
|
mask, the bits for their address translations can also be set.
|
|
|
|
the meanings of the address translation bits must be consistent
|
|
across all normal ASIs, since these bits are the only ones that are
|
|
significant when address masks from two normal ASIs are compared.
|
|
since an address mask from a special ASI can never match an address
|
|
mask from a different ASI, the address translation bits for a
|
|
special ASI are effectively unique to that ASI, and so there are
|
|
only two of them - privileged and nonprivileged.
|
|
|
|
bits zero through seven are available for ASI-specific use, and
|
|
they never affect ASI mask comparison: */
|
|
#define TME_SPARC_ASI_MASK_FLAG_SPECIAL TME_BIT(15)
|
|
#define TME_SPARC_ASI_MASK_FLAG_UNDEF TME_BIT(24)
|
|
#define TME_SPARC_ASI_MASK_RAW(asi) \
|
|
(((tme_uint32_t) (asi)) \
|
|
* (TME_SPARC_ASI_MASK_FLAG_SPECIAL * 2))
|
|
#define TME_SPARC_ASI_MASK(asi, xlat) \
|
|
(TME_SPARC_ASI_MASK_RAW(asi) \
|
|
+ TME_BIT(8 + (xlat)))
|
|
#define TME_SPARC_ASI_MASK_SPECIAL(asi, priv) \
|
|
(TME_SPARC_ASI_MASK(asi, (priv) != 0) \
|
|
+ TME_SPARC_ASI_MASK_FLAG_SPECIAL)
|
|
#define TME_SPARC_ASI_MASK_WHICH(asi_mask) \
|
|
((asi_mask) \
|
|
/ (TME_SPARC_ASI_MASK_FLAG_SPECIAL * 2))
|
|
#define TME_SPARC_ASI_MASK_FLAGS_AVAIL \
|
|
(TME_SPARC_ASI_MASK(0, 0) - 1)
|
|
|
|
/* this evaluates to nonzero iff the two ASI masks overlap: */
|
|
/* NB: asi_mask0 must be a single ASI mask from a memory instruction
|
|
(in other words, it must have exactly one address translation bit
|
|
set), and it may also have TME_SPARC_ASI_MASK_FLAG_UNDEF set. .
|
|
if asi_mask1 is a binary-OR of multiple ASI masks, either all of
|
|
them must be for normal ASIs, or all of them must be for the same
|
|
special ASI. asi_mask1 must not have TME_SPARC_ASI_MASK_FLAG_UNDEF
|
|
set: */
|
|
#define TME_SPARC_ASI_MASK_OVERLAP(asi_mask0, asi_mask1) \
|
|
((((asi_mask0) \
|
|
^ (asi_mask1)) \
|
|
& ((((tme_uint32_t) \
|
|
(tme_int32_t) \
|
|
(tme_int16_t) \
|
|
(asi_mask0)) \
|
|
| TME_SPARC_ASI_MASK_FLAG_SPECIAL \
|
|
| TME_SPARC_ASI_MASK_FLAG_UNDEF) \
|
|
& (0 - TME_SPARC_ASI_MASK(0, 0)))) == 0)
|
|
|
|
/* this evaluates to nonzero iff this TLB entry allows access to an
|
|
ASI, given by mask: */
|
|
#define TME_SPARC_TLB_ASI_MASK_OK(tlb, asi_mask) \
|
|
TME_SPARC_ASI_MASK_OVERLAP(asi_mask, (tlb)->tme_sparc_tlb_asi_mask)
|
|
|
|
/* sparc32 has four required address translations, corresponding to
|
|
the four required ASIs: supervisor data, supervisor instruction,
|
|
user data, user instruction. all normal ASIs must use one of these
|
|
address translations, and so you must specify one of the required
|
|
ASIs to build an address space mask for a normal ASI: */
|
|
/* NB: this assumes that the four required ASIs are dense, and start
|
|
with TME_SPARC32_ASI_UI: */
|
|
#define TME_SPARC32_ASI_MASK(asi, asi_required) \
|
|
TME_SPARC_ASI_MASK(asi, (asi_required) - TME_SPARC32_ASI_UI)
|
|
|
|
/* sparc32 address space mask flags: */
|
|
#define TME_SPARC32_ASI_MASK_FLAG_SPECIAL (0x01)
|
|
|
|
/* for convenience we also provide the address space masks for the
|
|
sparc32 required ASIs here: */
|
|
#define TME_SPARC32_ASI_MASK_UI TME_SPARC32_ASI_MASK(TME_SPARC32_ASI_UI, TME_SPARC32_ASI_UI)
|
|
#define TME_SPARC32_ASI_MASK_SI TME_SPARC32_ASI_MASK(TME_SPARC32_ASI_SI, TME_SPARC32_ASI_SI)
|
|
#define TME_SPARC32_ASI_MASK_UD TME_SPARC32_ASI_MASK(TME_SPARC32_ASI_UD, TME_SPARC32_ASI_UD)
|
|
#define TME_SPARC32_ASI_MASK_SD TME_SPARC32_ASI_MASK(TME_SPARC32_ASI_SD, TME_SPARC32_ASI_SD)
|
|
|
|
/* sparc64 address space masks use the common sparc64 address space
|
|
identifier flags for address space mask flags, plus these other
|
|
address space mask flags. these other flags can't conflict with
|
|
the common flags (which are essentially architected), and the same
|
|
flag value (common or other) may have different names and meanings
|
|
in an ASI mask from an instruction and one from a TLB entry: */
|
|
#define TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS (0x04)
|
|
#define TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER (0x10)
|
|
#define TME_SPARC64_ASI_MASK_FLAG_SPECIAL (0x20)
|
|
#define TME_SPARC64_ASI_MASK_FLAG_TLB_SIDE_EFFECTS (0x40)
|
|
#define TME_SPARC64_ASI_MASK_FLAG_TLB_UNCACHEABLE (TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS)
|
|
|
|
/* sparc64 has five architected address translations: privileged
|
|
primary, privileged secondary, nonprivileged primary, nonprivileged
|
|
secondary, and nucleus. all of these are required, except for
|
|
nucleus. all normal ASIs must use one of these translations.
|
|
|
|
however, note that sparc64 address translation, by itself, doesn't
|
|
depend on privilege - the architected mapping from ASI to context
|
|
doesn't consider it. only address protection depends on privilege.
|
|
(this isn't necessarily true on sparc32 - a sparc32 without a
|
|
reference MMU could translate addresses completely differently for
|
|
its different architected ASIs.)
|
|
|
|
this means that a sparc64 normal ASI's address translation check
|
|
will be done completely by the context comparison, leaving only
|
|
privilege to be represented as generic sparc address space mask
|
|
address translations: */
|
|
#define TME_SPARC64_ASI_MASK_USER TME_SPARC_ASI_MASK(0 /* asi */, 0)
|
|
#define TME_SPARC64_ASI_MASK_PRIV TME_SPARC_ASI_MASK(0 /* asi */, 1)
|
|
#define TME_SPARC64_ASI_MASK(asi, asi_mask_flags) \
|
|
((asi_mask_flags) \
|
|
+ TME_SPARC_ASI_MASK(asi, \
|
|
(((asi_mask_flags) \
|
|
& TME_SPARC64_ASI_MASK_FLAG_INSN_AS_IF_USER) == 0)))
|
|
|
|
/* for convenience, we provide macros to build address space masks for
|
|
the architected ASIs given ASI mask flags here: */
|
|
#define TME_SPARC64_ASI_MASK_NUCLEUS(asi_flag_little) \
|
|
TME_SPARC64_ASI_MASK(0x04 + (asi_flag_little), \
|
|
(TME_SPARC64_ASI_MASK_FLAG_INSN_NUCLEUS + (asi_flag_little)))
|
|
#define TME_SPARC64_ASI_MASK_REQUIRED_UNRESTRICTED(asi_flags) \
|
|
TME_SPARC64_ASI_MASK(TME_SPARC64_ASI_FLAG_UNRESTRICTED \
|
|
+ ((asi_flags) \
|
|
& (TME_SPARC64_ASI_FLAG_SECONDARY \
|
|
+ TME_SPARC64_ASI_FLAG_NO_FAULT \
|
|
+ TME_SPARC64_ASI_FLAG_LITTLE)), \
|
|
asi_flags)
|
|
|
|
/* these busy and unbusy a TLB entry: */
|
|
#define tme_sparc_tlb_busy(tlb) \
|
|
tme_bus_tlb_busy(&(tlb)->tme_sparc_tlb_bus_tlb)
|
|
#define tme_sparc_tlb_unbusy(tlb) \
|
|
tme_bus_tlb_unbusy(&(tlb)->tme_sparc_tlb_bus_tlb)
|
|
|
|
/* the minimum and maximum IPL levels: */
|
|
#define TME_SPARC_IPL_NONE (0)
|
|
#define TME_SPARC_IPL_MIN (1)
|
|
#define TME_SPARC_IPL_MAX (15)
|
|
#define TME_SPARC_IPL_NMI (15)
|
|
|
|
/* this indexes an sparc bus router array for an sparc with a port size
|
|
of 8 * (2 ^ siz_lg2) bits: */
|
|
#define TME_SPARC_BUS_ROUTER_INDEX(siz_lg2, cycle_size, address)\
|
|
((( \
|
|
/* by the maximum cycle size: */ \
|
|
((cycle_size) - 1) \
|
|
\
|
|
/* by the address alignment: */ \
|
|
<< siz_lg2) \
|
|
+ ((address) & ((1 << (siz_lg2)) - 1))) \
|
|
\
|
|
/* factor in the size of the generic bus router array: */ \
|
|
* TME_BUS_ROUTER_SIZE(siz_lg2))
|
|
|
|
/* this gives the number of entries that must be in a generic bus
|
|
router array for a device with a bus size of 8 * (2 ^ siz_lg2)
|
|
bits: */
|
|
#define TME_SPARC_BUS_ROUTER_SIZE(siz_lg2) \
|
|
TME_SPARC_BUS_ROUTER_INDEX(siz_lg2, (1 << (siz_lg2)) + 1, 0)
|
|
|
|
/* structures: */
|
|
|
|
/* an sparc TLB entry: */
|
|
struct tme_sparc_tlb {
|
|
|
|
/* the generic bus TLB associated with this TLB entry: */
|
|
struct tme_bus_tlb tme_sparc_tlb_bus_tlb;
|
|
#define tme_sparc_tlb_addr_first tme_sparc_tlb_bus_tlb.tme_bus_tlb_addr_first
|
|
#define tme_sparc_tlb_addr_last tme_sparc_tlb_bus_tlb.tme_bus_tlb_addr_last
|
|
#define tme_sparc_tlb_bus_rwlock tme_sparc_tlb_bus_tlb.tme_bus_tlb_rwlock
|
|
#define tme_sparc_tlb_cycles_ok tme_sparc_tlb_bus_tlb.tme_bus_tlb_cycles_ok
|
|
#define tme_sparc_tlb_addr_offset tme_sparc_tlb_bus_tlb.tme_bus_tlb_addr_offset
|
|
#define tme_sparc_tlb_addr_shift tme_sparc_tlb_bus_tlb.tme_bus_tlb_addr_shift
|
|
#define tme_sparc_tlb_emulator_off_read tme_sparc_tlb_bus_tlb.tme_bus_tlb_emulator_off_read
|
|
#define tme_sparc_tlb_emulator_off_write tme_sparc_tlb_bus_tlb.tme_bus_tlb_emulator_off_write
|
|
|
|
/* any link for this TLB entry: */
|
|
tme_uint32_t tme_sparc_tlb_link;
|
|
|
|
/* the context for this TLB entry: */
|
|
tme_bus_context_t tme_sparc_tlb_context;
|
|
|
|
/* an ASI mask: */
|
|
tme_uint32_t tme_sparc_tlb_asi_mask;
|
|
};
|
|
|
|
/* an sparc bus connection: */
|
|
struct tme_sparc_bus_connection {
|
|
|
|
/* a generic bus connection: */
|
|
struct tme_bus_connection tme_sparc_bus_connection;
|
|
|
|
/* the sparc interrupt function: */
|
|
int (*tme_sparc_bus_interrupt) _TME_P((struct tme_sparc_bus_connection *, unsigned int));
|
|
|
|
/* the sparc TLB entry filler: */
|
|
int (*tme_sparc_bus_tlb_fill) _TME_P((struct tme_sparc_bus_connection *, struct tme_sparc_tlb *,
|
|
tme_uint32_t, tme_bus_addr_t, unsigned int));
|
|
|
|
/* the sparc FPU strict-compliance enabler: */
|
|
void (*tme_sparc_bus_fpu_strict) _TME_P((struct tme_sparc_bus_connection *, unsigned int));
|
|
};
|
|
|
|
/* globals: */
|
|
extern _tme_const tme_bus_lane_t tme_sparc_router_32[];
|
|
|
|
#endif /* !_TME_IC_SPARC_H */
|