mirror of
https://github.com/phabrics/Run-Sun3-SunOS-4.1.1.git
synced 2026-04-29 11:02:59 -04:00
207 lines
8.7 KiB
C
207 lines
8.7 KiB
C
/* $Id: recode-address.c,v 1.1 2010/02/07 14:07:25 fredette Exp $ */
|
|
|
|
/* libtme/recode-rws.c - generic support for recode reads and writes: */
|
|
|
|
/*
|
|
* Copyright (c) 2008 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.
|
|
*/
|
|
|
|
#include <tme/common.h>
|
|
_TME_RCSID("$Id: recode-address.c,v 1.1 2010/02/07 14:07:25 fredette Exp $");
|
|
|
|
#if TME_HAVE_RECODE
|
|
|
|
/* includes: */
|
|
#include "recode-impl.h"
|
|
|
|
/* this generic function checks an address type: */
|
|
void
|
|
tme_recode_address_type_check(const struct tme_recode_ic *ic,
|
|
const struct tme_recode_address_type *address_type)
|
|
{
|
|
tme_uint32_t address_mask_tlb_index_one;
|
|
|
|
/* the address size can't be bigger than the guest register size: */
|
|
assert (address_type->tme_recode_address_type_size
|
|
<= ic->tme_recode_ic_reg_size);
|
|
|
|
/* the minimum alignment must be a power of two: */
|
|
/* NB: this is a value in bytes, not a TME_RECODE_SIZE_: */
|
|
assert (address_type->tme_recode_address_type_align_min > 0
|
|
&& (address_type->tme_recode_address_type_align_min
|
|
& (address_type->tme_recode_address_type_align_min - 1)) == 0);
|
|
|
|
/* the TLB page size must be a power of two: */
|
|
assert (ic->tme_recode_ic_tlb_page_size > 0
|
|
&& (ic->tme_recode_ic_tlb_page_size
|
|
& (ic->tme_recode_ic_tlb_page_size - 1)) == 0);
|
|
|
|
/* the TLB index address mask must be some number of consecutive
|
|
one bits, all greater than or equal to the TLB page size: */
|
|
address_mask_tlb_index_one
|
|
= (address_type->tme_recode_address_type_mask_tlb_index
|
|
& (0 - address_type->tme_recode_address_type_mask_tlb_index));
|
|
assert (address_mask_tlb_index_one != 0
|
|
&& (((address_type->tme_recode_address_type_mask_tlb_index
|
|
+ address_mask_tlb_index_one)
|
|
& address_type->tme_recode_address_type_mask_tlb_index)
|
|
== 0));
|
|
assert (address_mask_tlb_index_one
|
|
>= ic->tme_recode_ic_tlb_page_size);
|
|
}
|
|
|
|
/* this generic function returns zero if two address types are the
|
|
same: */
|
|
int
|
|
tme_recode_address_type_compare(const struct tme_recode_ic *ic,
|
|
const struct tme_recode_address_type *address_type,
|
|
const struct tme_recode_address_type *address_type_other)
|
|
{
|
|
return (TRUE
|
|
|
|
/* compare ic offset of the context register: */
|
|
&& ((address_type_other->tme_recode_address_type_context_ic_offset < 0)
|
|
? (address_type->tme_recode_address_type_context_ic_offset < 0)
|
|
: (address_type_other->tme_recode_address_type_context_ic_offset
|
|
== address_type->tme_recode_address_type_context_ic_offset))
|
|
|
|
/* compare context register size: */
|
|
&& ((address_type_other->tme_recode_address_type_context_ic_offset < 0)
|
|
|| (address_type_other->tme_recode_address_type_context_size
|
|
== address_type->tme_recode_address_type_context_size))
|
|
|
|
/* compare address size: */
|
|
&& (address_type_other->tme_recode_address_type_size
|
|
== address_type->tme_recode_address_type_size)
|
|
|
|
/* compare address signedness: */
|
|
&& ((address_type->tme_recode_address_type_size
|
|
== ic->tme_recode_ic_reg_size)
|
|
|| (!address_type_other->tme_recode_address_type_signed
|
|
== !address_type->tme_recode_address_type_signed))
|
|
|
|
/* compare minimum alignment: */
|
|
&& (address_type_other->tme_recode_address_type_align_min
|
|
== address_type->tme_recode_address_type_align_min)
|
|
|
|
/* compare the fixed TLB flags: */
|
|
&& (address_type_other->tme_recode_address_type_tlb_flags
|
|
== address_type->tme_recode_address_type_tlb_flags)
|
|
|
|
/* compare ic offset of the TLB flags mask: */
|
|
&& (address_type_other->tme_recode_address_type_tlb_flags_ic_offset
|
|
== address_type->tme_recode_address_type_tlb_flags_ic_offset)
|
|
|
|
/* compare TLB index mask: */
|
|
&& (address_type_other->tme_recode_address_type_mask_tlb_index
|
|
== address_type->tme_recode_address_type_mask_tlb_index)
|
|
|
|
/* compare ic offset of TLB zero: */
|
|
&& (address_type_other->tme_recode_address_type_tlb0_ic_offset
|
|
== address_type->tme_recode_address_type_tlb0_ic_offset)
|
|
|
|
);
|
|
}
|
|
|
|
/* this returns the recode TLB type for an address type: */
|
|
void
|
|
tme_recode_address_type_tlb_type(const struct tme_recode_ic *ic,
|
|
const struct tme_recode_address_type *address_type,
|
|
struct tme_recode_tlb_type *tlb_type)
|
|
{
|
|
unsigned long tlb_offset_memory;
|
|
unsigned long tlb_offset_page;
|
|
unsigned long tlb_offset_flags;
|
|
unsigned long tlb_offset_token;
|
|
unsigned long tlb_offset_context;
|
|
unsigned long tlb_sizeof;
|
|
|
|
/* get information about this guest's recode TLB entries: */
|
|
#define _TME_RECODE_TLB_INFO_Cn_Am_KEY(csize, asize) (((csize) * (TME_RECODE_SIZE_GUEST_MAX + 1)) + (asize))
|
|
#define _TME_RECODE_TLB_INFO_C0_Am_KEY(asize) _TME_RECODE_TLB_INFO_Cn_Am_KEY(TME_RECODE_SIZE_GUEST_MAX + 1, asize)
|
|
switch (address_type->tme_recode_address_type_context_ic_offset < 0
|
|
? _TME_RECODE_TLB_INFO_C0_Am_KEY(ic->tme_recode_ic_reg_size)
|
|
: _TME_RECODE_TLB_INFO_Cn_Am_KEY(address_type->tme_recode_address_type_context_size,
|
|
ic->tme_recode_ic_reg_size)) {
|
|
default: abort();
|
|
#define _TME_RECODE_TLB_INFO_OFFSETOF(csize,asize,field) \
|
|
(((tme_uint8_t *) \
|
|
&(((struct _TME_CONCAT4(tme_recode_tlb_c,csize,_a,asize) *) 0) \
|
|
->_TME_CONCAT5(tme_recode_tlb_c,csize,_a,asize,field))) \
|
|
- (tme_uint8_t *) 0)
|
|
#define _TME_RECODE_TLB_INFO(csize,asize) \
|
|
do { \
|
|
tlb_offset_memory = _TME_RECODE_TLB_INFO_OFFSETOF(csize,asize,_memory); \
|
|
tlb_offset_page = _TME_RECODE_TLB_INFO_OFFSETOF(csize,asize,_page); \
|
|
tlb_offset_flags = _TME_RECODE_TLB_INFO_OFFSETOF(csize,asize,_flags); \
|
|
tlb_offset_token = _TME_RECODE_TLB_INFO_OFFSETOF(csize,asize,_token); \
|
|
tlb_sizeof = sizeof(struct _TME_CONCAT4(tme_recode_tlb_c,csize,_a,asize)); \
|
|
} while (/* CONSTCOND */ 0)
|
|
#define _TME_RECODE_TLB_INFO_Cn_Am(csize,asize) \
|
|
do { \
|
|
_TME_RECODE_TLB_INFO(csize,asize); \
|
|
tlb_offset_context = _TME_RECODE_TLB_INFO_OFFSETOF(csize,asize,_context); \
|
|
} while (/* CONSTCOND */ 0)
|
|
#define _TME_RECODE_TLB_INFO_Am(asize) \
|
|
do { \
|
|
_TME_RECODE_TLB_INFO(0,asize); \
|
|
tlb_offset_context = 0; \
|
|
} while (/* CONSTCOND */ 0)
|
|
|
|
#ifdef TME_RECODE_SIZE_128
|
|
#if TME_RECODE_SIZE_GUEST_MAX >= TME_RECODE_SIZE_128
|
|
case _TME_RECODE_TLB_INFO_Cn_Am_KEY(TME_RECODE_SIZE_16, TME_RECODE_SIZE_128):
|
|
_TME_RECODE_TLB_INFO_Cn_Am(16,128);
|
|
break;
|
|
#endif /* TME_RECODE_SIZE_GUEST_MAX >= TME_RECODE_SIZE_128 */
|
|
#endif /* TME_RECODE_SIZE_128 */
|
|
#ifdef TME_RECODE_SIZE_64
|
|
#if TME_RECODE_SIZE_GUEST_MAX >= TME_RECODE_SIZE_64
|
|
case _TME_RECODE_TLB_INFO_Cn_Am_KEY(TME_RECODE_SIZE_16, TME_RECODE_SIZE_64):
|
|
_TME_RECODE_TLB_INFO_Cn_Am(16,64);
|
|
break;
|
|
#endif /* TME_RECODE_SIZE_GUEST_MAX >= TME_RECODE_SIZE_64 */
|
|
#endif /* TME_RECODE_SIZE_64 */
|
|
case _TME_RECODE_TLB_INFO_Cn_Am_KEY(TME_RECODE_SIZE_16, TME_RECODE_SIZE_32):
|
|
_TME_RECODE_TLB_INFO_Cn_Am(16,32);
|
|
break;
|
|
}
|
|
|
|
/* return the information: */
|
|
tlb_type->tme_recode_tlb_type_offset_memory = tlb_offset_memory;
|
|
tlb_type->tme_recode_tlb_type_offset_page = tlb_offset_page;
|
|
tlb_type->tme_recode_tlb_type_offset_flags = tlb_offset_flags;
|
|
tlb_type->tme_recode_tlb_type_offset_token = tlb_offset_token;
|
|
tlb_type->tme_recode_tlb_type_offset_context = tlb_offset_context;
|
|
tlb_type->tme_recode_tlb_type_sizeof = tlb_sizeof;
|
|
}
|
|
|
|
#endif /* TME_HAVE_RECODE */
|