-
Notifications
You must be signed in to change notification settings - Fork 92
/
cmpscmem.h
218 lines (178 loc) · 9.83 KB
/
cmpscmem.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/* 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?)
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 );
}
#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)))
// ----------------------------------------------------------------------------
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 );
}
#define fetch_fw( p ) CSWAP32(fetch_fw_noswap((p)))
#define store_fw( p, v ) store_fw_noswap((p),CSWAP32((v)))
// ----------------------------------------------------------------------------
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 );
}
#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
///////////////////////////////////////////////////////////////////////////////