Files
org-hyperion-cules/cmpscmem.h
Fish (David B. Trout) d4a1b5e109 New 2012 CMPSC instruction implementation is now the default:
Original/legacy cmpsc.c implementation moved to altcmpsc.dll module.

Refer to Release Notes and/or README.CMPSC documents for more details.
2014-12-29 17:17:01 -08:00

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
///////////////////////////////////////////////////////////////////////////////