forked from thargor6/mb3d
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMemUtils.pas
277 lines (237 loc) · 6.23 KB
/
MemUtils.pas
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
///////////////////////////////////////////////////////////////////////////////////////////////
//
// MemUtils.pas
// --------------------------
// Changed: 2005-01-27
// Maintain: Michael Vinther | mv@logicnet·dk
//
// Assembler optimized routines requires minimum 486 processor
//
// Last change: ReplaceChar moved to StringUtils
//
unit MemUtils;
interface
uses Monitor, SysUtils;
type
TIntegerArray = array[0..32767] of Integer;
PIntegerArray = ^TIntegerArray;
TCardinalArray = array[0..32767] of Cardinal;
PCardinalArray = ^TCardinalArray;
Int64Split = packed record
Lo : Cardinal;
Hi : Integer;
end;
TAssignObject = class(TMonitorObject)
public
// All descendants of Assign and AssignTo should call inherited if
// supplied with an unsupported object type
procedure Assign(Other: TObject); virtual;
procedure AssignTo(Other: TObject); virtual;
end;
// Find byte in buffer, return position or -1 if not found
function FastLocateByte(const Where; Start, BSize: Integer; What: Word): Integer; assembler; pascal;
// Find 2 bytes in buffer, return position or -1 if not found
function FastLocate2Bytes(const Where; Start, BSize: Integer; What: Word): Integer; assembler; pascal;
// Find 4 bytes in buffer at DWord boundaries. Return position or -1 if not found >>>> UNTESTED <<<<
function FastLocateDWord(var Where; BSize: Integer; What: LongInt): Integer; assembler; register;
// Fill dest with sizeof zeros
procedure ZeroMem(var Dest; SizeOf: integer ); assembler; register;
procedure FillDWord(var Dest; Count: Integer; Value: Cardinal); assembler; register;
// Reverse byte order
function GetSwap2(A: Word): Word; assembler; register;
function GetSwap4(A: Cardinal): Cardinal; assembler; register;
procedure Swap4(var A: Cardinal); assembler; register;
procedure SwapDWords(var A,B); assembler; register;
function AllocMem(Size: Cardinal): Pointer;
// Like FreeMem, but checks for nil and set to nil after freeing
procedure FreeAndNilData(var P);
implementation
procedure FreeAndNilData(var P);
var
Ptr : Pointer;
begin
if Assigned(Pointer(P)) then
begin
Ptr:=Pointer(P);
Pointer(P):=nil;
FreeMem(Ptr);
end;
end;
function AllocMem(Size: Cardinal): Pointer;
begin
GetMem(Result,Size);
ZeroMem(Result^,Size);
end;
// Find byte in buffer, return position or -1 if not found
function FastLocateByte(const Where; Start, BSize: Integer; What: Word): Integer; assembler; pascal;
asm
push edi
mov ecx, [bsize]
sub ecx, [start]
jz @notfound // No data to search
mov edi, [where]
add edi, [start]
mov ax, [what]
@search:
repne scasb
je @found
@notfound:
mov eax, -1
jmp @end
@found:
mov eax, edi
dec eax
sub eax, [where]
@end:
pop edi
end;
function FastLocate2Bytes(const where; start, bsize: integer; what: word):integer; assembler; pascal; far;
asm
push edi
mov ecx, [bsize]
sub ecx, [start]
jz @notfound // No data to search
mov edi, [where]
add edi, [start]
mov ax, [what]
@search:
repne scasb
je @found
@notfound:
mov eax, -1
jmp @end
@found:
cmp [edi], ah
jne @search
mov eax, edi
dec eax
sub eax, [where]
@end:
pop edi
end;
function FastLocateDWord(var Where; BSize: Integer; What: LongInt): Integer; assembler; register;
asm
{eax=where; edx=bsize; ecx=what}
push edi
mov edi, eax
mov eax, ecx
mov ecx, edx
mov edx, edi
{edi=where; edx=where; eax=what; ecx=bsize}
@search:
repne scasd
je @found
@notfound:
mov eax, -1
jmp @end
@found:
mov eax, edi
sub eax, edx
shr eax, 2
dec eax
@end:
pop edi
end;
procedure ZeroMem( var dest; sizeof: integer ); assembler; register;
asm
{ eax=dest; edx=sizeof }
push edi { protect edi }
mov edi, eax { edi=@dest }
xor eax, eax { eax=0 }
{ calc. no. of dwords to store and store them }
mov ecx, edx
shr ecx, 2
rep stosd
{ calc. no. of missing words and store them (actually this is bit 1) }
mov ecx, edx
bt ecx, 1
jnc @stobyte
stosw
{ calc. no. of missing bytes and store them (actually this is bit 0) }
@stobyte:
bt ecx, 0
jnc @ende
stosb
{ memory block should be zeroed }
@ende:
pop edi
end;
// Like FillChar, just with DWords
procedure FillDWord(var Dest; Count: Integer; Value: Cardinal); assembler; register;
asm
// eax=Dest; edx=Count; ecx=Value
push edi // protect edi
mov edi, eax // edi=@dest
mov eax, ecx // eax=Value
mov ecx, edx
rep stosd
pop edi
end;
// Like standard fillchar
procedure FastFillChar( var dest; sizeof: integer; fill: byte ); assembler; register;
asm
{ eax=dest; edx=sizeof; cl=fill }
push edi { protect edi }
mov edi, eax { edi=@dest }
mov ch, cl
mov ax, cx
bswap eax
mov ax, cx
{ calc. no. of dwords to store and store them }
mov ecx, edx
shr ecx, 2
rep stosd
{ calc. no. of missing words and store them (actually this is bit 1) }
mov ecx, edx
bt ecx, 1
jnc @stobyte
stosw
{ calc. no. of missing bytes and store them (actually this is bit 0) }
@stobyte:
bt ecx, 0
jnc @ende
stosb
{ memory block should be zeroed }
@ende:
pop edi
end;
function GetSwap2(A: Word): Word; assembler; register;
asm
mov cl, al
mov al, ah
mov ah, cl
end;
// Reverse byte order
procedure Swap4(var A: Cardinal); assembler; register;
asm
mov ecx, [eax]
bswap ecx
mov [eax], ecx
end;
function GetSwap4(A: Cardinal): Cardinal; assembler; register;
asm
bswap eax
end;
procedure SwapDWords(var A,B); assembler; register;
asm
push ebx
mov ebx, [eax]
mov ecx, [edx]
mov [eax], ecx
mov [edx], ebx
pop ebx
end;
//==============================================================================================================================
// TAssignObject
//==============================================================================================================================
procedure TAssignObject.Assign(Other: TObject);
begin
if Other is TAssignObject then TAssignObject(Other).AssignTo(Self)
else raise Exception.Create('Cannot assign '+Other.ClassName+' to '+ClassName);
end;
procedure TAssignObject.AssignTo(Other: TObject);
begin
if Other is TAssignObject then TAssignObject(Other).Assign(Self)
else raise Exception.Create('Cannot assign '+ClassName+' to '+Other.ClassName);
end;
end.