1*4a5d661aSToomas Soome/* match.S -- x86 assembly version of the zlib longest_match() function. 2*4a5d661aSToomas Soome * Optimized for the Intel 686 chips (PPro and later). 3*4a5d661aSToomas Soome * 4*4a5d661aSToomas Soome * Copyright (C) 1998, 2007 Brian Raiter <breadbox@muppetlabs.com> 5*4a5d661aSToomas Soome * 6*4a5d661aSToomas Soome * This software is provided 'as-is', without any express or implied 7*4a5d661aSToomas Soome * warranty. In no event will the author be held liable for any damages 8*4a5d661aSToomas Soome * arising from the use of this software. 9*4a5d661aSToomas Soome * 10*4a5d661aSToomas Soome * Permission is granted to anyone to use this software for any purpose, 11*4a5d661aSToomas Soome * including commercial applications, and to alter it and redistribute it 12*4a5d661aSToomas Soome * freely, subject to the following restrictions: 13*4a5d661aSToomas Soome * 14*4a5d661aSToomas Soome * 1. The origin of this software must not be misrepresented; you must not 15*4a5d661aSToomas Soome * claim that you wrote the original software. If you use this software 16*4a5d661aSToomas Soome * in a product, an acknowledgment in the product documentation would be 17*4a5d661aSToomas Soome * appreciated but is not required. 18*4a5d661aSToomas Soome * 2. Altered source versions must be plainly marked as such, and must not be 19*4a5d661aSToomas Soome * misrepresented as being the original software. 20*4a5d661aSToomas Soome * 3. This notice may not be removed or altered from any source distribution. 21*4a5d661aSToomas Soome */ 22*4a5d661aSToomas Soome 23*4a5d661aSToomas Soome#ifndef NO_UNDERLINE 24*4a5d661aSToomas Soome#define match_init _match_init 25*4a5d661aSToomas Soome#define longest_match _longest_match 26*4a5d661aSToomas Soome#endif 27*4a5d661aSToomas Soome 28*4a5d661aSToomas Soome#define MAX_MATCH (258) 29*4a5d661aSToomas Soome#define MIN_MATCH (3) 30*4a5d661aSToomas Soome#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) 31*4a5d661aSToomas Soome#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) 32*4a5d661aSToomas Soome 33*4a5d661aSToomas Soome/* stack frame offsets */ 34*4a5d661aSToomas Soome 35*4a5d661aSToomas Soome#define chainlenwmask 0 /* high word: current chain len */ 36*4a5d661aSToomas Soome /* low word: s->wmask */ 37*4a5d661aSToomas Soome#define window 4 /* local copy of s->window */ 38*4a5d661aSToomas Soome#define windowbestlen 8 /* s->window + bestlen */ 39*4a5d661aSToomas Soome#define scanstart 16 /* first two bytes of string */ 40*4a5d661aSToomas Soome#define scanend 12 /* last two bytes of string */ 41*4a5d661aSToomas Soome#define scanalign 20 /* dword-misalignment of string */ 42*4a5d661aSToomas Soome#define nicematch 24 /* a good enough match size */ 43*4a5d661aSToomas Soome#define bestlen 28 /* size of best match so far */ 44*4a5d661aSToomas Soome#define scan 32 /* ptr to string wanting match */ 45*4a5d661aSToomas Soome 46*4a5d661aSToomas Soome#define LocalVarsSize (36) 47*4a5d661aSToomas Soome/* saved ebx 36 */ 48*4a5d661aSToomas Soome/* saved edi 40 */ 49*4a5d661aSToomas Soome/* saved esi 44 */ 50*4a5d661aSToomas Soome/* saved ebp 48 */ 51*4a5d661aSToomas Soome/* return address 52 */ 52*4a5d661aSToomas Soome#define deflatestate 56 /* the function arguments */ 53*4a5d661aSToomas Soome#define curmatch 60 54*4a5d661aSToomas Soome 55*4a5d661aSToomas Soome/* All the +zlib1222add offsets are due to the addition of fields 56*4a5d661aSToomas Soome * in zlib in the deflate_state structure since the asm code was first written 57*4a5d661aSToomas Soome * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). 58*4a5d661aSToomas Soome * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). 59*4a5d661aSToomas Soome * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). 60*4a5d661aSToomas Soome */ 61*4a5d661aSToomas Soome 62*4a5d661aSToomas Soome#define zlib1222add (8) 63*4a5d661aSToomas Soome 64*4a5d661aSToomas Soome#define dsWSize (36+zlib1222add) 65*4a5d661aSToomas Soome#define dsWMask (44+zlib1222add) 66*4a5d661aSToomas Soome#define dsWindow (48+zlib1222add) 67*4a5d661aSToomas Soome#define dsPrev (56+zlib1222add) 68*4a5d661aSToomas Soome#define dsMatchLen (88+zlib1222add) 69*4a5d661aSToomas Soome#define dsPrevMatch (92+zlib1222add) 70*4a5d661aSToomas Soome#define dsStrStart (100+zlib1222add) 71*4a5d661aSToomas Soome#define dsMatchStart (104+zlib1222add) 72*4a5d661aSToomas Soome#define dsLookahead (108+zlib1222add) 73*4a5d661aSToomas Soome#define dsPrevLen (112+zlib1222add) 74*4a5d661aSToomas Soome#define dsMaxChainLen (116+zlib1222add) 75*4a5d661aSToomas Soome#define dsGoodMatch (132+zlib1222add) 76*4a5d661aSToomas Soome#define dsNiceMatch (136+zlib1222add) 77*4a5d661aSToomas Soome 78*4a5d661aSToomas Soome 79*4a5d661aSToomas Soome.file "match.S" 80*4a5d661aSToomas Soome 81*4a5d661aSToomas Soome.globl match_init, longest_match 82*4a5d661aSToomas Soome 83*4a5d661aSToomas Soome.text 84*4a5d661aSToomas Soome 85*4a5d661aSToomas Soome/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ 86*4a5d661aSToomas Soome.cfi_sections .debug_frame 87*4a5d661aSToomas Soome 88*4a5d661aSToomas Soomelongest_match: 89*4a5d661aSToomas Soome 90*4a5d661aSToomas Soome.cfi_startproc 91*4a5d661aSToomas Soome/* Save registers that the compiler may be using, and adjust %esp to */ 92*4a5d661aSToomas Soome/* make room for our stack frame. */ 93*4a5d661aSToomas Soome 94*4a5d661aSToomas Soome pushl %ebp 95*4a5d661aSToomas Soome .cfi_def_cfa_offset 8 96*4a5d661aSToomas Soome .cfi_offset ebp, -8 97*4a5d661aSToomas Soome pushl %edi 98*4a5d661aSToomas Soome .cfi_def_cfa_offset 12 99*4a5d661aSToomas Soome pushl %esi 100*4a5d661aSToomas Soome .cfi_def_cfa_offset 16 101*4a5d661aSToomas Soome pushl %ebx 102*4a5d661aSToomas Soome .cfi_def_cfa_offset 20 103*4a5d661aSToomas Soome subl $LocalVarsSize, %esp 104*4a5d661aSToomas Soome .cfi_def_cfa_offset LocalVarsSize+20 105*4a5d661aSToomas Soome 106*4a5d661aSToomas Soome/* Retrieve the function arguments. %ecx will hold cur_match */ 107*4a5d661aSToomas Soome/* throughout the entire function. %edx will hold the pointer to the */ 108*4a5d661aSToomas Soome/* deflate_state structure during the function's setup (before */ 109*4a5d661aSToomas Soome/* entering the main loop). */ 110*4a5d661aSToomas Soome 111*4a5d661aSToomas Soome movl deflatestate(%esp), %edx 112*4a5d661aSToomas Soome movl curmatch(%esp), %ecx 113*4a5d661aSToomas Soome 114*4a5d661aSToomas Soome/* uInt wmask = s->w_mask; */ 115*4a5d661aSToomas Soome/* unsigned chain_length = s->max_chain_length; */ 116*4a5d661aSToomas Soome/* if (s->prev_length >= s->good_match) { */ 117*4a5d661aSToomas Soome/* chain_length >>= 2; */ 118*4a5d661aSToomas Soome/* } */ 119*4a5d661aSToomas Soome 120*4a5d661aSToomas Soome movl dsPrevLen(%edx), %eax 121*4a5d661aSToomas Soome movl dsGoodMatch(%edx), %ebx 122*4a5d661aSToomas Soome cmpl %ebx, %eax 123*4a5d661aSToomas Soome movl dsWMask(%edx), %eax 124*4a5d661aSToomas Soome movl dsMaxChainLen(%edx), %ebx 125*4a5d661aSToomas Soome jl LastMatchGood 126*4a5d661aSToomas Soome shrl $2, %ebx 127*4a5d661aSToomas SoomeLastMatchGood: 128*4a5d661aSToomas Soome 129*4a5d661aSToomas Soome/* chainlen is decremented once beforehand so that the function can */ 130*4a5d661aSToomas Soome/* use the sign flag instead of the zero flag for the exit test. */ 131*4a5d661aSToomas Soome/* It is then shifted into the high word, to make room for the wmask */ 132*4a5d661aSToomas Soome/* value, which it will always accompany. */ 133*4a5d661aSToomas Soome 134*4a5d661aSToomas Soome decl %ebx 135*4a5d661aSToomas Soome shll $16, %ebx 136*4a5d661aSToomas Soome orl %eax, %ebx 137*4a5d661aSToomas Soome movl %ebx, chainlenwmask(%esp) 138*4a5d661aSToomas Soome 139*4a5d661aSToomas Soome/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ 140*4a5d661aSToomas Soome 141*4a5d661aSToomas Soome movl dsNiceMatch(%edx), %eax 142*4a5d661aSToomas Soome movl dsLookahead(%edx), %ebx 143*4a5d661aSToomas Soome cmpl %eax, %ebx 144*4a5d661aSToomas Soome jl LookaheadLess 145*4a5d661aSToomas Soome movl %eax, %ebx 146*4a5d661aSToomas SoomeLookaheadLess: movl %ebx, nicematch(%esp) 147*4a5d661aSToomas Soome 148*4a5d661aSToomas Soome/* register Bytef *scan = s->window + s->strstart; */ 149*4a5d661aSToomas Soome 150*4a5d661aSToomas Soome movl dsWindow(%edx), %esi 151*4a5d661aSToomas Soome movl %esi, window(%esp) 152*4a5d661aSToomas Soome movl dsStrStart(%edx), %ebp 153*4a5d661aSToomas Soome lea (%esi,%ebp), %edi 154*4a5d661aSToomas Soome movl %edi, scan(%esp) 155*4a5d661aSToomas Soome 156*4a5d661aSToomas Soome/* Determine how many bytes the scan ptr is off from being */ 157*4a5d661aSToomas Soome/* dword-aligned. */ 158*4a5d661aSToomas Soome 159*4a5d661aSToomas Soome movl %edi, %eax 160*4a5d661aSToomas Soome negl %eax 161*4a5d661aSToomas Soome andl $3, %eax 162*4a5d661aSToomas Soome movl %eax, scanalign(%esp) 163*4a5d661aSToomas Soome 164*4a5d661aSToomas Soome/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ 165*4a5d661aSToomas Soome/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ 166*4a5d661aSToomas Soome 167*4a5d661aSToomas Soome movl dsWSize(%edx), %eax 168*4a5d661aSToomas Soome subl $MIN_LOOKAHEAD, %eax 169*4a5d661aSToomas Soome subl %eax, %ebp 170*4a5d661aSToomas Soome jg LimitPositive 171*4a5d661aSToomas Soome xorl %ebp, %ebp 172*4a5d661aSToomas SoomeLimitPositive: 173*4a5d661aSToomas Soome 174*4a5d661aSToomas Soome/* int best_len = s->prev_length; */ 175*4a5d661aSToomas Soome 176*4a5d661aSToomas Soome movl dsPrevLen(%edx), %eax 177*4a5d661aSToomas Soome movl %eax, bestlen(%esp) 178*4a5d661aSToomas Soome 179*4a5d661aSToomas Soome/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ 180*4a5d661aSToomas Soome 181*4a5d661aSToomas Soome addl %eax, %esi 182*4a5d661aSToomas Soome movl %esi, windowbestlen(%esp) 183*4a5d661aSToomas Soome 184*4a5d661aSToomas Soome/* register ush scan_start = *(ushf*)scan; */ 185*4a5d661aSToomas Soome/* register ush scan_end = *(ushf*)(scan+best_len-1); */ 186*4a5d661aSToomas Soome/* Posf *prev = s->prev; */ 187*4a5d661aSToomas Soome 188*4a5d661aSToomas Soome movzwl (%edi), %ebx 189*4a5d661aSToomas Soome movl %ebx, scanstart(%esp) 190*4a5d661aSToomas Soome movzwl -1(%edi,%eax), %ebx 191*4a5d661aSToomas Soome movl %ebx, scanend(%esp) 192*4a5d661aSToomas Soome movl dsPrev(%edx), %edi 193*4a5d661aSToomas Soome 194*4a5d661aSToomas Soome/* Jump into the main loop. */ 195*4a5d661aSToomas Soome 196*4a5d661aSToomas Soome movl chainlenwmask(%esp), %edx 197*4a5d661aSToomas Soome jmp LoopEntry 198*4a5d661aSToomas Soome 199*4a5d661aSToomas Soome.balign 16 200*4a5d661aSToomas Soome 201*4a5d661aSToomas Soome/* do { 202*4a5d661aSToomas Soome * match = s->window + cur_match; 203*4a5d661aSToomas Soome * if (*(ushf*)(match+best_len-1) != scan_end || 204*4a5d661aSToomas Soome * *(ushf*)match != scan_start) continue; 205*4a5d661aSToomas Soome * [...] 206*4a5d661aSToomas Soome * } while ((cur_match = prev[cur_match & wmask]) > limit 207*4a5d661aSToomas Soome * && --chain_length != 0); 208*4a5d661aSToomas Soome * 209*4a5d661aSToomas Soome * Here is the inner loop of the function. The function will spend the 210*4a5d661aSToomas Soome * majority of its time in this loop, and majority of that time will 211*4a5d661aSToomas Soome * be spent in the first ten instructions. 212*4a5d661aSToomas Soome * 213*4a5d661aSToomas Soome * Within this loop: 214*4a5d661aSToomas Soome * %ebx = scanend 215*4a5d661aSToomas Soome * %ecx = curmatch 216*4a5d661aSToomas Soome * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) 217*4a5d661aSToomas Soome * %esi = windowbestlen - i.e., (window + bestlen) 218*4a5d661aSToomas Soome * %edi = prev 219*4a5d661aSToomas Soome * %ebp = limit 220*4a5d661aSToomas Soome */ 221*4a5d661aSToomas SoomeLookupLoop: 222*4a5d661aSToomas Soome andl %edx, %ecx 223*4a5d661aSToomas Soome movzwl (%edi,%ecx,2), %ecx 224*4a5d661aSToomas Soome cmpl %ebp, %ecx 225*4a5d661aSToomas Soome jbe LeaveNow 226*4a5d661aSToomas Soome subl $0x00010000, %edx 227*4a5d661aSToomas Soome js LeaveNow 228*4a5d661aSToomas SoomeLoopEntry: movzwl -1(%esi,%ecx), %eax 229*4a5d661aSToomas Soome cmpl %ebx, %eax 230*4a5d661aSToomas Soome jnz LookupLoop 231*4a5d661aSToomas Soome movl window(%esp), %eax 232*4a5d661aSToomas Soome movzwl (%eax,%ecx), %eax 233*4a5d661aSToomas Soome cmpl scanstart(%esp), %eax 234*4a5d661aSToomas Soome jnz LookupLoop 235*4a5d661aSToomas Soome 236*4a5d661aSToomas Soome/* Store the current value of chainlen. */ 237*4a5d661aSToomas Soome 238*4a5d661aSToomas Soome movl %edx, chainlenwmask(%esp) 239*4a5d661aSToomas Soome 240*4a5d661aSToomas Soome/* Point %edi to the string under scrutiny, and %esi to the string we */ 241*4a5d661aSToomas Soome/* are hoping to match it up with. In actuality, %esi and %edi are */ 242*4a5d661aSToomas Soome/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ 243*4a5d661aSToomas Soome/* initialized to -(MAX_MATCH_8 - scanalign). */ 244*4a5d661aSToomas Soome 245*4a5d661aSToomas Soome movl window(%esp), %esi 246*4a5d661aSToomas Soome movl scan(%esp), %edi 247*4a5d661aSToomas Soome addl %ecx, %esi 248*4a5d661aSToomas Soome movl scanalign(%esp), %eax 249*4a5d661aSToomas Soome movl $(-MAX_MATCH_8), %edx 250*4a5d661aSToomas Soome lea MAX_MATCH_8(%edi,%eax), %edi 251*4a5d661aSToomas Soome lea MAX_MATCH_8(%esi,%eax), %esi 252*4a5d661aSToomas Soome 253*4a5d661aSToomas Soome/* Test the strings for equality, 8 bytes at a time. At the end, 254*4a5d661aSToomas Soome * adjust %edx so that it is offset to the exact byte that mismatched. 255*4a5d661aSToomas Soome * 256*4a5d661aSToomas Soome * We already know at this point that the first three bytes of the 257*4a5d661aSToomas Soome * strings match each other, and they can be safely passed over before 258*4a5d661aSToomas Soome * starting the compare loop. So what this code does is skip over 0-3 259*4a5d661aSToomas Soome * bytes, as much as necessary in order to dword-align the %edi 260*4a5d661aSToomas Soome * pointer. (%esi will still be misaligned three times out of four.) 261*4a5d661aSToomas Soome * 262*4a5d661aSToomas Soome * It should be confessed that this loop usually does not represent 263*4a5d661aSToomas Soome * much of the total running time. Replacing it with a more 264*4a5d661aSToomas Soome * straightforward "rep cmpsb" would not drastically degrade 265*4a5d661aSToomas Soome * performance. 266*4a5d661aSToomas Soome */ 267*4a5d661aSToomas SoomeLoopCmps: 268*4a5d661aSToomas Soome movl (%esi,%edx), %eax 269*4a5d661aSToomas Soome xorl (%edi,%edx), %eax 270*4a5d661aSToomas Soome jnz LeaveLoopCmps 271*4a5d661aSToomas Soome movl 4(%esi,%edx), %eax 272*4a5d661aSToomas Soome xorl 4(%edi,%edx), %eax 273*4a5d661aSToomas Soome jnz LeaveLoopCmps4 274*4a5d661aSToomas Soome addl $8, %edx 275*4a5d661aSToomas Soome jnz LoopCmps 276*4a5d661aSToomas Soome jmp LenMaximum 277*4a5d661aSToomas SoomeLeaveLoopCmps4: addl $4, %edx 278*4a5d661aSToomas SoomeLeaveLoopCmps: testl $0x0000FFFF, %eax 279*4a5d661aSToomas Soome jnz LenLower 280*4a5d661aSToomas Soome addl $2, %edx 281*4a5d661aSToomas Soome shrl $16, %eax 282*4a5d661aSToomas SoomeLenLower: subb $1, %al 283*4a5d661aSToomas Soome adcl $0, %edx 284*4a5d661aSToomas Soome 285*4a5d661aSToomas Soome/* Calculate the length of the match. If it is longer than MAX_MATCH, */ 286*4a5d661aSToomas Soome/* then automatically accept it as the best possible match and leave. */ 287*4a5d661aSToomas Soome 288*4a5d661aSToomas Soome lea (%edi,%edx), %eax 289*4a5d661aSToomas Soome movl scan(%esp), %edi 290*4a5d661aSToomas Soome subl %edi, %eax 291*4a5d661aSToomas Soome cmpl $MAX_MATCH, %eax 292*4a5d661aSToomas Soome jge LenMaximum 293*4a5d661aSToomas Soome 294*4a5d661aSToomas Soome/* If the length of the match is not longer than the best match we */ 295*4a5d661aSToomas Soome/* have so far, then forget it and return to the lookup loop. */ 296*4a5d661aSToomas Soome 297*4a5d661aSToomas Soome movl deflatestate(%esp), %edx 298*4a5d661aSToomas Soome movl bestlen(%esp), %ebx 299*4a5d661aSToomas Soome cmpl %ebx, %eax 300*4a5d661aSToomas Soome jg LongerMatch 301*4a5d661aSToomas Soome movl windowbestlen(%esp), %esi 302*4a5d661aSToomas Soome movl dsPrev(%edx), %edi 303*4a5d661aSToomas Soome movl scanend(%esp), %ebx 304*4a5d661aSToomas Soome movl chainlenwmask(%esp), %edx 305*4a5d661aSToomas Soome jmp LookupLoop 306*4a5d661aSToomas Soome 307*4a5d661aSToomas Soome/* s->match_start = cur_match; */ 308*4a5d661aSToomas Soome/* best_len = len; */ 309*4a5d661aSToomas Soome/* if (len >= nice_match) break; */ 310*4a5d661aSToomas Soome/* scan_end = *(ushf*)(scan+best_len-1); */ 311*4a5d661aSToomas Soome 312*4a5d661aSToomas SoomeLongerMatch: movl nicematch(%esp), %ebx 313*4a5d661aSToomas Soome movl %eax, bestlen(%esp) 314*4a5d661aSToomas Soome movl %ecx, dsMatchStart(%edx) 315*4a5d661aSToomas Soome cmpl %ebx, %eax 316*4a5d661aSToomas Soome jge LeaveNow 317*4a5d661aSToomas Soome movl window(%esp), %esi 318*4a5d661aSToomas Soome addl %eax, %esi 319*4a5d661aSToomas Soome movl %esi, windowbestlen(%esp) 320*4a5d661aSToomas Soome movzwl -1(%edi,%eax), %ebx 321*4a5d661aSToomas Soome movl dsPrev(%edx), %edi 322*4a5d661aSToomas Soome movl %ebx, scanend(%esp) 323*4a5d661aSToomas Soome movl chainlenwmask(%esp), %edx 324*4a5d661aSToomas Soome jmp LookupLoop 325*4a5d661aSToomas Soome 326*4a5d661aSToomas Soome/* Accept the current string, with the maximum possible length. */ 327*4a5d661aSToomas Soome 328*4a5d661aSToomas SoomeLenMaximum: movl deflatestate(%esp), %edx 329*4a5d661aSToomas Soome movl $MAX_MATCH, bestlen(%esp) 330*4a5d661aSToomas Soome movl %ecx, dsMatchStart(%edx) 331*4a5d661aSToomas Soome 332*4a5d661aSToomas Soome/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ 333*4a5d661aSToomas Soome/* return s->lookahead; */ 334*4a5d661aSToomas Soome 335*4a5d661aSToomas SoomeLeaveNow: 336*4a5d661aSToomas Soome movl deflatestate(%esp), %edx 337*4a5d661aSToomas Soome movl bestlen(%esp), %ebx 338*4a5d661aSToomas Soome movl dsLookahead(%edx), %eax 339*4a5d661aSToomas Soome cmpl %eax, %ebx 340*4a5d661aSToomas Soome jg LookaheadRet 341*4a5d661aSToomas Soome movl %ebx, %eax 342*4a5d661aSToomas SoomeLookaheadRet: 343*4a5d661aSToomas Soome 344*4a5d661aSToomas Soome/* Restore the stack and return from whence we came. */ 345*4a5d661aSToomas Soome 346*4a5d661aSToomas Soome addl $LocalVarsSize, %esp 347*4a5d661aSToomas Soome .cfi_def_cfa_offset 20 348*4a5d661aSToomas Soome popl %ebx 349*4a5d661aSToomas Soome .cfi_def_cfa_offset 16 350*4a5d661aSToomas Soome popl %esi 351*4a5d661aSToomas Soome .cfi_def_cfa_offset 12 352*4a5d661aSToomas Soome popl %edi 353*4a5d661aSToomas Soome .cfi_def_cfa_offset 8 354*4a5d661aSToomas Soome popl %ebp 355*4a5d661aSToomas Soome .cfi_def_cfa_offset 4 356*4a5d661aSToomas Soome.cfi_endproc 357*4a5d661aSToomas Soomematch_init: ret 358