🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.delphi.basm
9 messages
9 total messages Started by Mamede Milanez Sat, 14 Sep 2002 03:23
MMX functions
#159
Author: Mamede Milanez
Date: Sat, 14 Sep 2002 03:23
69 lines
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
#161
Author: Pascal Willener
Date: Sat, 14 Sep 2002 13:02
85 lines
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
#162
Author: Pascal Willener
Date: Sat, 14 Sep 2002 13:05
93 lines
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
#170
Author: Mamede Milanez
Date: Mon, 16 Sep 2002 02:53
102 lines
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
#173
Author: Will DeWitt
Date: Mon, 16 Sep 2002 09:01
38 lines
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
#182
Author: Mamede Milanez
Date: Mon, 16 Sep 2002 23:26
54 lines
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
#12
Author: Hagen Reddmann
Date: Tue, 17 Sep 2002 17:35
3 lines
1089 bytes
Yes, let see it, especialy I'm interessted in SSE2 :)

Hagen
Re: MMX functions
#10
Author: Pascal Willener
Date: Tue, 17 Sep 2002 18:40
14 lines
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
#13
Author: John O'Harrow
Date: Tue, 17 Sep 2002 19:44
224 lines
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