Patch title: Release 81 bulk changes
Abstract:
File: /pliant/language/memory/memory.c
Key:
    Removed line
    Added line
// Copyright  Hubert Tonneau  hubert.tonneau@pliant.cx
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// version 2 along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

/*
abstract
  text "Various easy to understand low level functions dealing with raw memory areas."
*/


#if defined(_i386_) && defined(_WATCOM_)

    ASM_INLINE Int asm_memory_clear(Address address,Int size);
    #pragma aux asm_memory_clear =      \
      "mov edx,ecx"                     \
      "shr ecx,1"                       \
      "shr ecx,1"                       \
      "xor eax,eax"                     \
      "cld"                             \
      "and edx,3"                       \
      "rep stosd"                       \
      "mov ecx,edx"                     \
      "rep stosb"                       \
      parm [edi][ecx]                   \
      modify exact [eax edx edi ecx];

  FUNCTION Void memory_clear(Address address,Int size) {
    check(size>=0);
    asm_memory_clear(address,size); }

#else

  FUNCTION Void memory_clear(Address address,Int size) {
    check(size>=0);
    for(; size>=sizeof(Int); size-=sizeof(Int))
      *(*(Int **)&address)++ = 0;
    for(; size>0; size--)
      *(*(Byte **)&address)++ = 0; }

#endif


static uInt32 seed=0x2C345675;

FUNCTION Void memory_random(Address address,Int size) {
   static uInt32 seed;
   if(G.execution_phase>=phase_free) return;
   for(; size>=sizeof(uInt32); size-=sizeof(uInt32)) {
     *(*(uInt32 **)&address)++ = seed;
     seed=(seed*1103515245)+12345; }
   for(; size>0; size--) {
     *(*(Byte **)&address)++ = (Byte)seed;
     seed=(seed*1103515245)+12345; } }


#if defined(_i386_) && defined(_WATCOM_)

    ASM_INLINE Int asm_memory_copy(Address src,Address dest,Int size);
    #pragma aux asm_memory_copy =       \
      "mov eax,ecx"                     \
      "shr ecx,1"                       \
      "shr ecx,1"                       \
      "cld"                             \
      "and eax,3"                       \
      "rep movsd"                       \
      "mov ecx,eax"                     \
      "rep movsb"                       \
      parm [esi][edi][ecx]              \
      modify exact [eax esi edi ecx];

  FUNCTION Void memory_copy(Address src,Address dest,Int size) {
    check(size>=0);
    asm_memory_copy(src,dest,size); }

#else

  FUNCTION Void memory_copy(Address src,Address dest,Int size) {
    check(size>=0);
    for(; size>=sizeof(Int); size-=sizeof(Int))
      *(*(Int **)&dest)++ = *(*(Int **)&src)++ ;
    for(; size>0; size--)
      *(*(Byte **)&dest)++ = *(*(Byte **)&src)++; }

#endif


FUNCTION Void memory_move(Address src,Address dest,Int size) {
  check(size>=0);
  if(integer_from_address(dest)<=integer_from_address(src) || integer_from_address(dest)>=integer_from_address(src)+size) {
    memory_copy(src,dest,size);
  other
    dest=address_from_integer(integer_from_address(dest)+size);
    src=address_from_integer(integer_from_address(src)+size);
    for(; size>=sizeof(Int); size-=sizeof(Int))
      *(--(*(Int **)&dest)) = *(--(*(Int **)&src)) ;
    for(; size>0; size--)
      *(--(*(Byte **)&dest)) = *(--(*(Byte **)&src)); } }


FUNCTION Int memory_compare(Address area1,Int size1,Address area2,Int size2) {
  Int remain;
  check(size1>=0 && size2>=0);
  remain=minimum(size1,size2);
  while(remain>=sizeof(uInt) && *(uInt *)area1==*(uInt *)area2)
    area1=address_translate(area1,sizeof(uInt)),area2=address_translate(area2,sizeof(uInt)),remain-=sizeof(uInt);
  while(remain>0 && *(Byte *)area1==*(Byte *)area2)
    area1=address_translate(area1,1),area2=address_translate(area2,1),remain--;
  if(remain!=0) {
    return *(Byte *)area1>*(Byte *)area2 ? compare_superior : compare_inferior;
  orif(size1==size2)
    return compare_equal;
  other
    return size1>size2 ? compare_superior : compare_inferior; } }


#if defined(_i386_) && defined(_WATCOM_)

    ASM_INLINE Int asm_memory_different(Address area1,Address area2,Int size);
    #pragma aux asm_memory_different =  \
      "lea eax,[ecx+4]"                 \
      "shr ecx,1"                       \
      "shr ecx,1"                       \
      "cld"                             \
      "repe cmpsd"                      \
      "jne different"                   \
      "mov ecx,eax"                     \
      "and ecx,3"                       \
      "repe cmpsb"                      \
      "jne different"                   \
      "xor eax,eax"                     \
      "different:"                      \
      parm [esi][edi][ecx]              \
      value [eax]                       \
      modify exact [eax esi edi ecx];

  FUNCTION Bool memory_different(Address area1,Int size1,Address area2,Int size2) {
    check(size1>=0 && size2>=0);
    return(size1!=size2 || asm_memory_different(area1,area2,size1)); }

#else

  FUNCTION Bool memory_different(Address area1,Int size1,Address area2,Int size2) {
    check(size1>=0 && size2>=0);
    if(size1!=size2) return true;
    while(size1>=sizeof(uInt) && *(uInt *)area1==*(uInt *)area2)
      area1=address_translate(area1,sizeof(uInt)),area2=address_translate(area2,sizeof(uInt)),size1-=sizeof(uInt);
    while(size1>0 && *(Byte *)area1==*(Byte *)area2)
      area1=address_translate(area1,1),area2=address_translate(area2,1),size1--;
    return size1; }

#endif


FUNCTION Address memory_search(Address address,Int size,Address pattern_address,Int pattern_size) {
  Byte *cur,*stop; Byte c;
  check(pattern_size>0);
  if(pattern_size>size) return null;
  c=((Byte *)pattern_address)[0];
  for(cur=(Byte *)address,stop=(Byte *)address+size+1-pattern_size; cur!=stop; cur++)
    if(*cur==c && !memory_different(cur,pattern_size,pattern_address,pattern_size))
      return cur;
  return null; }