Thread View: borland.public.delphi.basm
9 messages
9 total messages
Started by Mamede Milanez
Sat, 14 Sep 2002 03:23
MMX functions
Author: Mamede Milanez
Date: Sat, 14 Sep 2002 03:23
Date: Sat, 14 Sep 2002 03:23
69 lines
1551 bytes
1551 bytes
Can someone help me translating this codes from C to delphi (6) ?
Thanks
static BOOL hasMMX()
{
BOOL found;
_asm
{
mov found, 0
mov eax, 1
CPUID
test edx, 0x800000
jz MMX_notfound
mov found, 1
MMX_notfound:
}
return found;
}
static void memcpyMMX(void *dst, void *src, int count)
{
count >>= 3;
_asm
{
mov esi, src
mov edi, dst
mov ecx, count
__L2:
movq mm0, [esi]
movq [edi], mm0
add esi, 8
add edi, 8
dec ecx
jnz __L2
emms
}
}
Re: MMX functions
Author: Pascal Willener
Date: Sat, 14 Sep 2002 13:02
Date: Sat, 14 Sep 2002 13:02
85 lines
1770 bytes
1770 bytes
Hi
Look at:
movq mm0, [esi]
movq [edi], mm0
Why are you copying them around like this?
To the mmx register and back...
cya
"Mamede Milanez" <mamede@enter-net.com.br> wrote in message
news:3d829f3d@newsgroups.borland.com...
> Can someone help me translating this codes from C to delphi (6) ?
>
> Thanks
>
> static BOOL hasMMX()
>
> {
>
> BOOL found;
>
> _asm
>
> {
>
> mov found, 0
>
> mov eax, 1
>
> CPUID
>
> test edx, 0x800000
>
> jz MMX_notfound
>
> mov found, 1
>
> MMX_notfound:
>
> }
>
> return found;
>
> }
>
> static void memcpyMMX(void *dst, void *src, int count)
>
> {
>
> count >>= 3;
>
> _asm
>
> {
>
> mov esi, src
>
> mov edi, dst
>
> mov ecx, count
>
> __L2:
>
> movq mm0, [esi]
>
> movq [edi], mm0
>
> add esi, 8
>
> add edi, 8
>
> dec ecx
>
> jnz __L2
>
> emms
>
> }
>
> }
>
>
>
Re: MMX functions
Author: Pascal Willener
Date: Sat, 14 Sep 2002 13:05
Date: Sat, 14 Sep 2002 13:05
93 lines
2170 bytes
2170 bytes
Oops was sleeping, lol
edi and esi *g*
cya
"Pascal Willener" <zerob@gmx.net> wrote in message
news:3d833349$1@newsgroups.borland.com...
> Hi
>
> Look at:
> movq mm0, [esi]
> movq [edi], mm0
>
> Why are you copying them around like this?
> To the mmx register and back...
>
> cya
>
> "Mamede Milanez" <mamede@enter-net.com.br> wrote in message
> news:3d829f3d@newsgroups.borland.com...
> > Can someone help me translating this codes from C to delphi (6) ?
> >
> > Thanks
> >
> > static BOOL hasMMX()
> >
> > {
> >
> > BOOL found;
> >
> > _asm
> >
> > {
> >
> > mov found, 0
> >
> > mov eax, 1
> >
> > CPUID
> >
> > test edx, 0x800000
> >
> > jz MMX_notfound
> >
> > mov found, 1
> >
> > MMX_notfound:
> >
> > }
> >
> > return found;
> >
> > }
> >
> > static void memcpyMMX(void *dst, void *src, int count)
> >
> > {
> >
> > count >>= 3;
> >
> > _asm
> >
> > {
> >
> > mov esi, src
> >
> > mov edi, dst
> >
> > mov ecx, count
> >
> > __L2:
> >
> > movq mm0, [esi]
> >
> > movq [edi], mm0
> >
> > add esi, 8
> >
> > add edi, 8
> >
> > dec ecx
> >
> > jnz __L2
> >
> > emms
> >
> > }
> >
> > }
> >
> >
> >
>
>
Re: MMX functions
Author: Mamede Milanez
Date: Mon, 16 Sep 2002 02:53
Date: Mon, 16 Sep 2002 02:53
102 lines
2658 bytes
2658 bytes
Thanks, but how would be this codes on delphi?
[]s
"Pascal Willener" <zerob@gmx.net> escreveu na mensagem
news:3d83341c@newsgroups.borland.com...
> Oops was sleeping, lol
> edi and esi *g*
>
> cya
> "Pascal Willener" <zerob@gmx.net> wrote in message
> news:3d833349$1@newsgroups.borland.com...
> > Hi
> >
> > Look at:
> > movq mm0, [esi]
> > movq [edi], mm0
> >
> > Why are you copying them around like this?
> > To the mmx register and back...
> >
> > cya
> >
> > "Mamede Milanez" <mamede@enter-net.com.br> wrote in message
> > news:3d829f3d@newsgroups.borland.com...
> > > Can someone help me translating this codes from C to delphi (6) ?
> > >
> > > Thanks
> > >
> > > static BOOL hasMMX()
> > >
> > > {
> > >
> > > BOOL found;
> > >
> > > _asm
> > >
> > > {
> > >
> > > mov found, 0
> > >
> > > mov eax, 1
> > >
> > > CPUID
> > >
> > > test edx, 0x800000
> > >
> > > jz MMX_notfound
> > >
> > > mov found, 1
> > >
> > > MMX_notfound:
> > >
> > > }
> > >
> > > return found;
> > >
> > > }
> > >
> > > static void memcpyMMX(void *dst, void *src, int count)
> > >
> > > {
> > >
> > > count >>= 3;
> > >
> > > _asm
> > >
> > > {
> > >
> > > mov esi, src
> > >
> > > mov edi, dst
> > >
> > > mov ecx, count
> > >
> > > __L2:
> > >
> > > movq mm0, [esi]
> > >
> > > movq [edi], mm0
> > >
> > > add esi, 8
> > >
> > > add edi, 8
> > >
> > > dec ecx
> > >
> > > jnz __L2
> > >
> > > emms
> > >
> > > }
> > >
> > > }
> > >
> > >
> > >
> >
> >
>
>
Re: MMX functions
Author: Will DeWitt
Date: Mon, 16 Sep 2002 09:01
Date: Mon, 16 Sep 2002 09:01
38 lines
1728 bytes
1728 bytes
Barely tested, but should work-- function hasMMX: longbool; asm PUSH EBX MOV EAX, 1 CPUID MOV EAX, EDX AND EAX, $00800000 POP EBX end; procedure memcpyMMX(dst, src: pointer; count: longword); register; asm // On entry-- // EAX = dst // EDX = src // ECX = count SHR ECX, 3 @@__L2: MOVQ MM0, QWORD PTR [EDX] MOVQ QWORD PTR [EAX], MM0 ADD EDX, 8 ADD EAX, 8 DEC ECX JNZ @@__L2 EMMS end; ---- Note that memcpyMMX doesn't do any alignment checks, doesn't handle data that's not a multiple of the value being moved, and probably could use vast improvements. But you only asked for the code you showed to be translated to Delphi. This was tested in Delphi 7, but I see no reason it shouldn't work in Delphi 6. Will
Re: MMX functions
Author: Mamede Milanez
Date: Mon, 16 Sep 2002 23:26
Date: Mon, 16 Sep 2002 23:26
54 lines
2388 bytes
2388 bytes
Thank you very much Will. You sad that it cam be imporoved. How ? I will use this function to copy buffers from a memory addres to another addres. This buffer conteins raw image (320*240*3) bytes. It was captured from a video capture card. Can it be improved?? Mamede "Will DeWitt" <edge@NO.SPAM_boink.net> escreveu na mensagem news:3d859dec@newsgroups.borland.com... > Barely tested, but should work-- > > function hasMMX: longbool; > asm > PUSH EBX > MOV EAX, 1 > CPUID > MOV EAX, EDX > AND EAX, $00800000 > POP EBX > end; > > procedure memcpyMMX(dst, src: pointer; count: longword); register; > asm > // On entry-- > // EAX = dst > // EDX = src > // ECX = count > SHR ECX, 3 > @@__L2: > MOVQ MM0, QWORD PTR [EDX] > MOVQ QWORD PTR [EAX], MM0 > ADD EDX, 8 > ADD EAX, 8 > DEC ECX > JNZ @@__L2 > EMMS > end; > > ---- > > Note that memcpyMMX doesn't do any alignment checks, doesn't handle data > that's not a multiple of the value being moved, and probably could use vast > improvements. But you only asked for the code you showed to be translated > to Delphi. This was tested in Delphi 7, but I see no reason it shouldn't > work in Delphi 6. > > Will > > > >
Re: MMX functions
Author: Hagen Reddmann
Date: Tue, 17 Sep 2002 17:35
Date: Tue, 17 Sep 2002 17:35
3 lines
1089 bytes
1089 bytes
Yes, let see it, especialy I'm interessted in SSE2 :) Hagen
Re: MMX functions
Author: Pascal Willener
Date: Tue, 17 Sep 2002 18:40
Date: Tue, 17 Sep 2002 18:40
14 lines
1437 bytes
1437 bytes
Im interested to. Maybe you could contribute this code to the project started in the "Work to do" thread. cya "Hagen Reddmann" <HaReddmann@T-Online.de> wrote in message news:3d876a8e$1@newsgroups.borland.com... > Yes, let see it, especialy I'm interessted in SSE2 :) > > Hagen > > >
Re: MMX functions
Author: John O'Harrow
Date: Tue, 17 Sep 2002 19:44
Date: Tue, 17 Sep 2002 19:44
224 lines
7976 bytes
7976 bytes
Ok, here are my current Pentium and Athlon optimised move procedures (again,
for non-overlapping moves only). Both procedures take full advantage of
prefetching and are much faster than the standard move and the simple MMX
based move I previously posted. For large data moves, these routines are
approx 200% faster than the Borland's standard move procedure. Obviously
you will need to detect the type of processor elsewhere and call the
appropriate procedure.
I am not yet satisfied with my SSE or 3D-NOW versions, but I will happily
post them when they have been fully optimised and tested.
When I get the time, I plan to write an "all-singing all-dancing" version
which detects the processors capability and calls the most appropriate
version, while also allowing for overlapping source/destination, .
It is also worth noting that the Borland's standard move command is
generally faster than any of these optimised moves where only a small amount
of data (less than a few hundred bytes) is to be moved.
John O'Harrow
{Note - PentiumFastMove is only Valid for Non-Overlapping Source/Dest}
procedure PentiumFastMove(const Source; var Dest; Count : Integer);
{$IFDEF PurePascal}
begin
Move(Source, Dest, Count);
end;
{$ELSE}
asm {Copy via MMX Registers with Prefetch, approx. 200% Faster}
push ebx
push esi
push edi
push ebp
sub esp, 2048 {Initialise 2K Local Buffer}
mov edi, edx {EDI = Dest}
mov esi, eax {ESI = Source}
mov ebx, ecx {EBX = Count}
mov ebp, esp {EBP = Buffer}
mov eax, ecx {EAX = Count}
and eax, $7FF {EAX = Count MOD 2K}
shr ebx, 11 {EBX = Count DIV 2K}
jz @Remainder {Jump if Count < 2K}
{Copy EBX Blocks of 2K via Local Buffer}
@loop2k:
{Copy 2K Block into Local Buffer}
mov edx, ebp {EDX = Buffer}
mov ecx, 32 {32 Loops of 64 Bytes}
@loopMemToL1:
prefetchnta [ESI+64] {Prefetch Next loop, Non-Temporal}
prefetchnta [ESI+96]
movq mm1, [ESI ] {Read In Source Data}
movq mm2, [ESI +8]
movq mm3, [ESI+16]
movq mm4, [ESI+24]
movq mm5, [ESI+32]
movq mm6, [ESI+40]
movq mm7, [ESI+48]
movq mm0, [ESI+56]
movq [EDX ], mm1
movq [EDX+ 8], mm2
movq [EDX+16], mm3
movq [EDX+24], mm4
movq [EDX+32], mm5
movq [EDX+40], mm6
movq [EDX+48], mm7
movq [EDX+56], mm0
add esi, 64
add edx, 64
dec ecx
jnz @loopMemToL1
{Copy 2K Block from Local Buffer}
mov edx, ebp {EDX = Buffer}
mov ecx, 32 {32 Loops of 64 Bytes}
@loopL1ToMem:
movq mm1, [EDX ] {Store into L1 Cache}
movq mm2, [EDX +8]
movq mm3, [EDX+16]
movq mm4, [EDX+24]
movq mm5, [EDX+32]
movq mm6, [EDX+40]
movq mm7, [EDX+48]
movq mm0, [EDX+56]
movntq [EDI ], mm1
movntq [EDI +8], mm2
movntq [EDI+16], mm3
movntq [EDI+24], mm4
movntq [EDI+32], mm5
movntq [EDI+40], mm6
movntq [EDI+48], mm7
movntq [EDI+56], mm0
add edx, 64
add edi, 64
dec ecx
jnz @loopL1ToMem
dec ebx {Decrement Block Counter}
jnz @loop2k {Repeat for each 2K Block}
test eax, eax {Remainder = 0?}
jz @Done {Yes - Finished}
@Remainder: {EAX = Bytes Left to Move (0..2047)}
mov ecx, eax
shr ecx, 2
and eax, 3
rep movsd
mov ecx, eax
rep movsb
@Done:
emms {Empty MMX State}
add ebp, 2048
mov esp, ebp
pop ebp
pop edi
pop esi
pop ebx
end; {PentiumFastMove}
{$ENDIF}
{Note - AthlonFastMove is only Valid for Non-Overlapping Source/Dest}
procedure AthlonFastMove(const Source; var Dest; Count : Integer);
{$IFDEF PurePascal}
begin
Move(Source, Dest, Count);
end;
{$ELSE}
const
CACHEBLOCK = $400;
asm {Copy via MMX Registers with Prefetch, approx. 200% Faster}
push ebx
push esi
push edi
mov edi, edx {EDI = Dest}
mov esi, eax {ESI = Source}
mov edx, ecx {EDX = Count}
shr ecx, 3 {ECX = No of QWORD's}
and ecx, $FFFFFC00 {ECX = No of 8K Blocks of QWORD's to Block
Move * 8}
jz @Remainder1 {None - Jump}
{Move 8K Blocks}
lea esi, [esi+ecx*8]
lea edi, [edi+ecx*8]
neg ecx
@mainloop:
mov eax, CACHEBLOCK / 16 {prefetch loop is unrolled 2X}
add ecx, CACHEBLOCK {move up to end of block}
@prefetchloop:
mov ebx, [esi+ecx*8- 64] {read one address in this cache line}
mov ebx, [esi+ecx*8-128] {and one in the previous line}
sub ecx, 16 {16 QWORDS = 2 64-byte cache lines}
dec eax
jnz @prefetchloop
mov eax, CACHEBLOCK / 8
@writeloop:
movq mm0, [esi+ecx*8 ]
movq mm1, [esi+ecx*8+ 8]
movq mm2, [esi+ecx*8+16]
movq mm3, [esi+ecx*8+24]
movq mm4, [esi+ecx*8+32]
movq mm5, [esi+ecx*8+40]
movq mm6, [esi+ecx*8+48]
movq mm7, [esi+ecx*8+56]
movntq [edi+ecx*8 ], mm0
movntq [edi+ecx*8+ 8], mm1
movntq [edi+ecx*8+16], mm2
movntq [edi+ecx*8+24], mm3
movntq [edi+ecx*8+32], mm4
movntq [edi+ecx*8+40], mm5
movntq [edi+ecx*8+48], mm6
movntq [edi+ecx*8+56], mm7
add ecx, 8
dec eax
jnz @writeloop
or ecx, ecx
jnz @mainloop
sfence {Flush Write Buffer}
emms {Empty MMX State}
@Remainder1:
mov ecx, edx {ECX = Original Count}
and ecx, $1FFF {ECX = No of Remaining Bytes (0..8191)}
shr ecx, 3 {ECX = No of QWORD's Left (0..1023)}
and ecx, $FFFFFFF8 {ECX = No of 64 Byte Blocks to Block Move *
8}
jz @Remainder2
lea esi, [esi+ecx*8]
lea edi, [edi+ecx*8]
neg ecx
{Move 64 Byte Blocks}
@copyloop:
prefetchnta [esi+ecx*8+512]
movq mm0, [esi+ecx*8 ]
movq mm1, [esi+ecx*8+ 8]
movq mm2, [esi+ecx*8+16]
movq mm3, [esi+ecx*8+24]
movq mm4, [esi+ecx*8+32]
movq mm5, [esi+ecx*8+40]
movq mm6, [esi+ecx*8+48]
movq mm7, [esi+ecx*8+56]
movntq [edi+ecx*8 ], mm0
movntq [edi+ecx*8+ 8], mm1
movntq [edi+ecx*8+16], mm2
movntq [edi+ecx*8+24], mm3
movntq [edi+ecx*8+32], mm4
movntq [edi+ecx*8+40], mm5
movntq [edi+ecx*8+48], mm6
movntq [edi+ecx*8+56], mm7
add ecx, 8
jnz @copyloop
sfence
emms
@Remainder2:
mov ecx, edx
and ecx, $3F {ECX = No of Bytes Left to Move (0..63)}
rep movsb
pop edi
pop esi
pop ebx
end; {AthlonFastMove}
{$ENDIF}
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads