mirror of
https://github.com/SDL-Hercules-390/hyperion.git
synced 2026-04-13 07:25:22 +02:00
Original/legacy cmpsc.c implementation moved to altcmpsc.dll module. Refer to Release Notes and/or README.CMPSC documents for more details.
234 lines
10 KiB
C
234 lines
10 KiB
C
/* CMPSCMEM.H (c) Copyright "Fish" (David B. Trout), 2012-2014 */
|
|
/* Compression Call Memory Access Functions */
|
|
/* */
|
|
/* Released under "The Q Public License Version 1" */
|
|
/* (http://www.hercules-390.org/herclic.html) as modifications to */
|
|
/* Hercules. */
|
|
|
|
#ifndef _CMPSCMEM_H_
|
|
#define _CMPSCMEM_H_ // Code to be compiled ONLY ONCE goes after here
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Operand memory access control block
|
|
|
|
struct MEMBLK // Operand memory access control block
|
|
{
|
|
REGS* regs; // Pointer to register context
|
|
U64 vpagebeg; // MADDR virtual base address
|
|
U8* maddr[2]; // Operand page MADDRs
|
|
int arn; // Operand register number
|
|
U8 pkey; // PSW key
|
|
};
|
|
typedef struct MEMBLK MEMBLK;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// (simple helper macros with more descriptive names)
|
|
|
|
#define U16_ALIGNED( addr ) likely(!((addr) & 1))
|
|
#define U32_ALIGNED( addr ) likely(!((addr) & 3))
|
|
#define U64_ALIGNED( addr ) likely(!((addr) & 7))
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// fetch/store hw/fw/dw/noswap compatibility macros for utility
|
|
|
|
#if defined( NOT_HERC ) // (building tool utility not Hercules?)
|
|
|
|
#if defined( OPTION_STRICT_ALIGNMENT )
|
|
static INLINE U16 fetch_hw_noswap( void* ptr )
|
|
{
|
|
U16 value;
|
|
memcpy( &value, (U8*)ptr, 2 );
|
|
return value;
|
|
}
|
|
static INLINE void store_hw_noswap( void* ptr, U16 value )
|
|
{
|
|
memcpy( (U8*)ptr, (U8*)&value, 2 );
|
|
}
|
|
#else
|
|
#define fetch_hw_noswap( p ) (*(U16*)(uintptr_t)(p))
|
|
#define store_hw_noswap( p, v ) (*(U16*)(uintptr_t)(p) = (U16)(v))
|
|
#endif
|
|
|
|
#define fetch_hw( p ) CSWAP16(fetch_hw_noswap((void*)(uintptr_t)(p)))
|
|
#define store_hw( p, v ) store_hw_noswap((void*)(uintptr_t)(p),CSWAP16((v)))
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#if defined( OPTION_STRICT_ALIGNMENT )
|
|
static INLINE U32 fetch_fw_noswap( void* ptr )
|
|
{
|
|
U32 value;
|
|
memcpy( &value, (U8*)ptr, 4 );
|
|
return value;
|
|
}
|
|
static INLINE void store_fw_noswap( void* ptr, U32 value )
|
|
{
|
|
memcpy( (U8*)ptr, (U8*)&value, 4 );
|
|
}
|
|
#else
|
|
#define fetch_fw_noswap( p ) (*(U32*)(uintptr_t)(p))
|
|
#define store_fw_noswap( p, v ) (*(U32*)(uintptr_t)(p) = (U32)(v))
|
|
#endif
|
|
|
|
#define fetch_fw( p ) CSWAP32(fetch_fw_noswap((p)))
|
|
#define store_fw( p, v ) store_fw_noswap((p),CSWAP32((v)))
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#if defined( OPTION_STRICT_ALIGNMENT )
|
|
static INLINE U64 fetch_dw_noswap( void* ptr )
|
|
{
|
|
U64 value;
|
|
memcpy( &value, (U8*)ptr, 8 );
|
|
return value;
|
|
}
|
|
static INLINE void store_dw_noswap( void* ptr, U64 value )
|
|
{
|
|
memcpy( (U8*)ptr, (U8*)&value, 8 );
|
|
}
|
|
#else
|
|
#define fetch_dw_noswap( p ) (*(U64*)(uintptr_t)(p))
|
|
#define store_dw_noswap( p, v ) (*(U64*)(uintptr_t)(p) = (U64)(v))
|
|
#endif
|
|
|
|
#define fetch_dw( p ) CSWAP64(fetch_dw_noswap((p)))
|
|
#define store_dw( p, v ) store_dw_noswap((p),CSWAP64((v)))
|
|
|
|
#endif // defined( NOT_HERC )
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#endif // _CMPSCMEM_H_ // Place all 'ARCH_DEP' code after this statement
|
|
|
|
#undef NOCROSSPAGE
|
|
#undef CROSSPAGE
|
|
#define NOCROSSPAGE(a,n) likely(((int)((a) & PAGEFRAME_BYTEMASK)) <= (PAGEFRAME_BYTEMASK-(n)))
|
|
#define CROSSPAGE(a,n) unlikely(((int)((a) & PAGEFRAME_BYTEMASK)) > (PAGEFRAME_BYTEMASK-(n)))
|
|
#undef LASTBYTEOFPAGE
|
|
#define LASTBYTEOFPAGE(a) unlikely(((a) & PAGEFRAME_BYTEMASK) == PAGEFRAME_BYTEMASK)
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// MEMBLK helper macros
|
|
|
|
#undef MEMBLK_FIRSTPAGE // (is address in first page?)
|
|
#define MEMBLK_FIRSTPAGE( pMEMBLK, pOp ) \
|
|
\
|
|
likely((pOp) < ((pMEMBLK)->vpagebeg + PAGEFRAME_PAGESIZE))
|
|
|
|
#undef MEMBLK_BUMP // (bump to next page if needed)
|
|
#define MEMBLK_BUMP( pMEMBLK, pOp ) \
|
|
\
|
|
do if (!MEMBLK_FIRSTPAGE((pMEMBLK),(pOp))) \
|
|
{ \
|
|
(pMEMBLK)->vpagebeg += PAGEFRAME_PAGESIZE; \
|
|
(pMEMBLK)->maddr[0] = (pMEMBLK)->maddr[1]; \
|
|
(pMEMBLK)->maddr[1] = 0; \
|
|
} \
|
|
while (0)
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// fetch/store hw/fw/dw/chars compatibility macros for utility
|
|
|
|
#if defined( NOT_HERC ) // (building utility and not Hercules?)
|
|
|
|
#undef vfetchb
|
|
#undef vstoreb
|
|
#undef vfetch2
|
|
#undef vstore2
|
|
#undef vfetch4
|
|
#undef vstore4
|
|
#undef vfetch8
|
|
#undef vstore8
|
|
#undef vfetchc
|
|
#undef vstorec
|
|
|
|
#define vfetchb( addr, arn, regs ) (*(U8*)(uintptr_t)(addr))
|
|
#define vstoreb( byt, addr, arn, regs ) (*(U8*)(uintptr_t)(addr)) = ((U8)byt)
|
|
#define vfetch2( addr, arn, regs ) fetch_hw((addr))
|
|
#define vstore2( val, addr, arn, regs ) store_hw((addr),(val))
|
|
#define vfetch4( addr, arn, regs ) fetch_fw((addr))
|
|
#define vstore4( val, addr, arn, regs ) store_fw((addr),(val))
|
|
#define vfetch8( addr, arn, regs ) fetch_dw((addr))
|
|
#define vstore8( val, addr, arn, regs ) store_dw((addr),(val))
|
|
#define vfetchc( dst, len, addr, arn, regs ) memcpy( (U8*)(uintptr_t)(dst), (U8*)(uintptr_t)(addr), (len)+1 )
|
|
#define vstorec( src, len, addr, arn, regs ) memcpy( (U8*)(uintptr_t)(addr), (U8*)(uintptr_t)(src), (len)+1 )
|
|
|
|
#undef wfetchb
|
|
#undef wfetch2
|
|
#undef wfetch4
|
|
#undef wfetch8
|
|
#undef wfetchc
|
|
#undef wstoreb
|
|
#undef wstore2
|
|
#undef wstore4
|
|
#undef wstore8
|
|
#undef wstorec
|
|
|
|
#define wfetchb( addr, arn, regs ) vfetchb( (addr), (arn), (regs) )
|
|
#define wfetch2( addr, arn, regs ) vfetch2( (addr), (arn), (regs) )
|
|
#define wfetch4( addr, arn, regs ) vfetch4( (addr), (arn), (regs) )
|
|
#define wfetch8( addr, arn, regs ) vfetch8( (addr), (arn), (regs) )
|
|
#define wfetchc( dst, len, addr, arn, regs ) vfetchc( (dst), (len), (addr), (arn), (regs) )
|
|
#define wstoreb( byt, addr, arn, regs ) vstoreb( (byt), (addr), (arn), (regs) )
|
|
#define wstore2( val, addr, arn, regs ) vstore2( (val), (addr), (arn), (regs) )
|
|
#define wstore4( val, addr, arn, regs ) vstore4( (val), (addr), (arn), (regs) )
|
|
#define wstore8( val, addr, arn, regs ) vstore8( (val), (addr), (arn), (regs) )
|
|
#define wstorec( src, len, addr, arn, regs ) vstorec( (src), (len), (addr), (arn), (regs) )
|
|
|
|
#endif // defined( NOT_HERC )
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Operand fetch/store functions
|
|
|
|
extern U8 (CMPSC_FASTCALL ARCH_DEP( cmpsc_vfetchb ))( VADR addr, MEMBLK* pMEMBLK );
|
|
extern U16 (CMPSC_FASTCALL ARCH_DEP( cmpsc_vfetch2 ))( VADR addr, MEMBLK* pMEMBLK );
|
|
extern U32 (CMPSC_FASTCALL ARCH_DEP( cmpsc_vfetch4 ))( VADR addr, MEMBLK* pMEMBLK );
|
|
extern U64 (CMPSC_FASTCALL ARCH_DEP( cmpsc_vfetch8 ))( VADR addr, MEMBLK* pMEMBLK );
|
|
extern void (CMPSC_FASTCALL ARCH_DEP( cmpsc_vfetchc ))( U8* dst, U16 len, VADR addr, MEMBLK* pMEMBLK );
|
|
extern void (CMPSC_FASTCALL ARCH_DEP( cmpsc_vstoreb ))( U8 byt, VADR addr, MEMBLK* pMEMBLK );
|
|
extern void (CMPSC_FASTCALL ARCH_DEP( cmpsc_vstore2 ))( U16 val, VADR addr, MEMBLK* pMEMBLK );
|
|
extern void (CMPSC_FASTCALL ARCH_DEP( cmpsc_vstore4 ))( U32 val, VADR addr, MEMBLK* pMEMBLK );
|
|
extern void (CMPSC_FASTCALL ARCH_DEP( cmpsc_vstore8 ))( U64 val, VADR addr, MEMBLK* pMEMBLK );
|
|
extern void (CMPSC_FASTCALL ARCH_DEP( cmpsc_vstorec ))( U8* src, U16 len, VADR addr, MEMBLK* pMEMBLK );
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Operand fetch/store macros to call above operand fetch/store functions
|
|
|
|
#undef fetch_op_b
|
|
#undef fetch_op_hw
|
|
#undef fetch_op_fw
|
|
#undef fetch_op_dw
|
|
#undef fetch_op_str
|
|
|
|
#define fetch_op_b( p, pMEMBLK ) ARCH_DEP( cmpsc_vfetchb )( (VADR)(p),(pMEMBLK))
|
|
#define fetch_op_hw( p, pMEMBLK ) ARCH_DEP( cmpsc_vfetch2 )( (VADR)(p),(pMEMBLK))
|
|
#define fetch_op_fw( p, pMEMBLK ) ARCH_DEP( cmpsc_vfetch4 )( (VADR)(p),(pMEMBLK))
|
|
#define fetch_op_dw( p, pMEMBLK ) ARCH_DEP( cmpsc_vfetch8 )( (VADR)(p),(pMEMBLK))
|
|
#define fetch_op_str( dst, len, p, pMEMBLK ) ARCH_DEP( cmpsc_vfetchc )((dst),(len),(VADR)(p),(pMEMBLK))
|
|
|
|
#undef store_op_b
|
|
#undef store_op_hw
|
|
#undef store_op_fw
|
|
#undef store_op_dw
|
|
#undef store_op_str
|
|
|
|
#define store_op_b( byt, p, pMEMBLK ) ARCH_DEP( cmpsc_vstoreb )((byt), (VADR)(p),(pMEMBLK))
|
|
#define store_op_hw( val, p, pMEMBLK ) ARCH_DEP( cmpsc_vstore2 )((val), (VADR)(p),(pMEMBLK))
|
|
#define store_op_fw( val, p, pMEMBLK ) ARCH_DEP( cmpsc_vstore4 )((val), (VADR)(p),(pMEMBLK))
|
|
#define store_op_dw( val, p, pMEMBLK ) ARCH_DEP( cmpsc_vstore8 )((val), (VADR)(p),(pMEMBLK))
|
|
#define store_op_str( src, len, p, pMEMBLK ) ARCH_DEP( cmpsc_vstorec )((src),(len),(VADR)(p),(pMEMBLK))
|
|
|
|
#undef fetch_dct_hw
|
|
#define fetch_dct_hw( p, pCMPSCBLK ) ARCH_DEP( wfetch2 )((VADR)(p), (pCMPSCBLK)->r2, (pCMPSCBLK)->regs)
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Helper functions to build pCMPSCBLK from REGS or vice-versa
|
|
|
|
extern void (CMPSC_FASTCALL ARCH_DEP( cmpsc_SetREGS ))( CMPSCBLK* pCMPSCBLK, REGS* regs, int r1, int r2 );
|
|
extern void (CMPSC_FASTCALL ARCH_DEP( cmpsc_SetCMPSC ))( CMPSCBLK* pCMPSCBLK, REGS* regs, int r1, int r2 );
|
|
|
|
#if defined( NOT_HERC ) // (called by the testing tool utility)
|
|
extern void (CMPSC_FASTCALL ARCH_DEP( util_cmpsc_SetREGS ))( CMPSCBLK* pCMPSCBLK, REGS* regs, int r1, int r2, U8 expand, U8 zeropad );
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|