/* ** Title: MMXString ** SCCSid: %W% %E% %U% ** CCid: %W% %E% %U% ** Author: Informix Software, Inc. ** Created: 06/11/1998 14:49 ** Description: This is the generated 'C' file for the MMXString DataBlade. ** Comments: Generated for project MMXString.3.6 */ /* ** The following is placed here to insure ** that name "mangling" does not occur. */ #ifdef __cplusplus extern "C" { #endif /* Standard library includes. */ #include #include #include #include /* Used by Informix GLS routines. */ #include /* Include when accessing the Informix API. */ #include /* This is the project include file. */ #include "MMXString.h" /* Prototype for the mmx version of strstr */ char *strstrmmx(const char *TxtBuff, const char *SearchStr); /* {{FUNCTION(7ae5c360-1f23-11d1-a42c-00a0c9220c70) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** Contains ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine Contains (lvarchar,lvarchar) returns boolean. ** ** Parameters: ** ** Return value: ** ** mi_integer ** ** History: ** ** 06/30/1998 - Generated by BladeSmith Version 3.60.630 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT mi_integer Contains ( mi_lvarchar * srchString, mi_lvarchar * txtBuffer, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { MI_CONNECTION * Gen_Con; /* The connection handle. */ mi_integer Gen_RetVal; /* The return value. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ mi_string *csrchBuffer; mi_string *csrchString; char *locsrchString; /* ------ }}Your_Declarations (#0000) END ------ */ /* Use the NULL connection. */ Gen_Con = NULL; /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ /* ** Write to the trace file indicating ** that MMXStringSearch has been called. */ DBDK_TRACE_ENTER( "Contains" ); csrchBuffer = mi_lvarchar_to_string(txtBuffer); csrchString = mi_lvarchar_to_string(srchString); if( Gen_IsMMXMachine() ) { /* MMX Machine use MMX version. */ locsrchString = strstrmmx(csrchBuffer, csrchString); } else { /* Non MMX Machine use C version. */ locsrchString = strstr( csrchBuffer, csrchString ); } if( locsrchString == NULL ) { Gen_RetVal = 0; } else { Gen_RetVal=1; } DBDK_TRACE_EXIT( "Contains" ); /* ------ }}Your_Code (#BD8C) END ------ */ /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#UHPSEVO7) */ /* strstrmmx */ char *strstrmmx(const char *TxtBuff, const char *SearchStr) { _int64 mask = 0x07; /* ** Case where the null is within ** the first two characters. */ if( SearchStr[0] == '\0' || SearchStr[1] == '\0' ) { return strstr( TxtBuff , SearchStr ); } __asm { //Initialization mov edi,SearchStr ; save addr of searchstr mov esi,TxtBuff ; save addr of txtbuffer xor ecx,ecx ; zero ecx to indicate continue movq mm0,dword ptr[edi] ; load the first 8 char from searchstr movd mm7,esi ; alignment code punpcklbw mm0,mm0 ; start the propagation of searchstr[0] punpcklwd mm0,mm0 pand mm7,mask ; find offset of TxtBuff from 8 byte lea edx,[edi+2] ; save searchstr[2] address movq mm1, mm0 ; copy of SearchStr movq mm4,dword ptr[esi] ; copy the next 8 byts of text buffer into mm4 punpckldq mm0,mm0 ; finish propagating searchstr[0] into whole mmx reg punpckhdq mm1,mm1 ; finish propagating searchstr[1] into whole mmx reg movq mm2,mm0 ; save propagate searchstr[0] to mm2 for later recovery psllq mm7,3 pxor mm5,mm5 movq mm3,mm1 ; save propagate searchstr[1] to mm3 for later recovery psllq mm4,mm7 ; shift first 8 bytes by offset and esi,0FFFFFFF8h ; align TxtBuff pointer ; end alignment code MATCH_2_CHARS: pcmpeqb mm0,mm4 ; compare 8 bytes of searchstr[0] to txtbuffer pcmpeqb mm1,mm4 ; compare 8 bytes of searchstr[1] to txtbuffer movq mm6,mm0 ; copy of results of searchstr[0] compare psllq mm0,8 ; shift left 1 byte to line up with searchstr[1] por mm0,mm5 ; combine the current searchstr[0] with the last byte of the previous compare psrlq mm6,56 ; save the last byte of searchstr[0] pand mm0,mm1 ; compare searchstr[0] and searchstr[1] lea edi,[esi+1] ; copy textbuffer just in case we will do byte by byte compare packsswb mm0,mm0 ; reduce to 32bits push ecx ; ecx indicates stop (1) or continue (0) ; 1 penalty cycle on PPMT movd eax,mm0 ; copy ldword of quad compare into eax movq mm5,mm6 ; save last byte of searchstr[0] for next iteration test eax,eax ; set flags jz NO_MATCH_FOUND FIND_MATCHES: test al,1000b ; does this byte have info if not then advance 4 bits for next byte jz NEXT_BYTE ; no match found for this byte ; scalar asm*****************************/ mov ecx,edi ; copy address of text buffer to ecx push edx ; save searchstr[2] address cuz we are clobbering it mainlupe: mov bl,[edx] ; copy searchstr[i] to bl inc edx or bl,bl ; if we've reached the end of search str, we've jz short success ; found the first matching substring mov bh,[ecx] ; copy textbuffer[i] to bh inc ecx cmp bl,bh ; characters match? je short mainlupe ; failed comparison. recover pointer to searchstr+1 ; and work on next byte pop edx jmp NEXT_BYTE success: lea eax,[edi-2] ; since edi contains textbuffer+2 we must give proper address in buffer pop ecx pop ecx jmp DONE ; ************************************/ NEXT_BYTE: shr eax,4 ; shift right 4 bits inc edi ; inc textbuffer offset cmp eax,08h ; do we have any more info to process jae FIND_MATCHES NO_MATCH_FOUND: ; no match for the quad words add esi,8 ; advance the text buffer by 8 pop ecx ; load remaining size of buffer test ecx,ecx ; have we reached the end of the text buffer? jnz DONE_NOT_FOUND ; if ecx is not zero, quit movq mm4,dword ptr[esi] ; copy the next 8 byts of text buffer into mm4 psubb mm0,mm0 ; zero out mm0 movq mm1,mm4 ; copy text pcmpeqb mm1,mm0 ; compare text with zero packsswb mm1,mm1 ; pack to 32bits movq mm0,mm2 ; copy SearchStr[0] movd ecx,mm1 ; store in ecx movq mm1,mm3 ; copy SearchStr[1] jmp MATCH_2_CHARS DONE_NOT_FOUND: xor eax,eax ; no match found DONE: emms } } //eax is returned #ifdef __cplusplus } #endif