// File: /workspace/github_c_makefile_star2_O3/ukontainer[P]sqlite-bench/sqlite3.c
// Function: flattenSubquery
static int flattenSubquery(
  Parse *pParse,       /* Parsing context */
  Select *p,           /* The parent or outer SELECT statement */
  int iFrom,           /* Index in p->pSrc->a[] of the inner subquery */
  int isAgg            /* True if outer SELECT uses aggregate functions */
){
  const char *zSavedAuthContext = pParse->zAuthContext;
  Select *pParent;    /* Current UNION ALL term of the other query */
  Select *pSub;       /* The inner query or "subquery" */
  Select *pSub1;      /* Pointer to the rightmost select in sub-query */
  SrcList *pSrc;      /* The FROM clause of the outer query */
  SrcList *pSubSrc;   /* The FROM clause of the subquery */
  int iParent;        /* VDBE cursor number of the pSub result set temp table */
  int iNewParent = -1;/* Replacement table for iParent */
  int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */    
  int i;              /* Loop counter */
  Expr *pWhere;                    /* The WHERE clause */
  struct SrcList_item *pSubitem;   /* The subquery */
  sqlite3 *db = pParse->db;

  /* Check to see if flattening is permitted.  Return 0 if not.
  */
  assert( p!=0 );
  assert( p->pPrior==0 );
  if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0;
  pSrc = p->pSrc;
  assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
  pSubitem = &pSrc->a[iFrom];
  iParent = pSubitem->iCursor;
  pSub = pSubitem->pSelect;
  assert( pSub!=0 );

#ifndef SQLITE_OMIT_WINDOWFUNC
  if( p->pWin || pSub->pWin ) return 0;                  /* Restriction (25) */
#endif

  pSubSrc = pSub->pSrc;
  assert( pSubSrc );
  /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
  ** not arbitrary expressions, we allowed some combining of LIMIT and OFFSET
  ** because they could be computed at compile-time.  But when LIMIT and OFFSET
  ** became arbitrary expressions, we were forced to add restrictions (13)
  ** and (14). */
  if( pSub->pLimit && p->pLimit ) return 0;              /* Restriction (13) */
  if( pSub->pLimit && pSub->pLimit->pRight ) return 0;   /* Restriction (14) */
  if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
    return 0;                                            /* Restriction (15) */
  }
  if( pSubSrc->nSrc==0 ) return 0;                       /* Restriction (7)  */
  if( pSub->selFlags & SF_Distinct ) return 0;           /* Restriction (4)  */
  if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){
     return 0;         /* Restrictions (8)(9) */
  }
  if( p->pOrderBy && pSub->pOrderBy ){
     return 0;                                           /* Restriction (11) */
  }
  if( isAgg && pSub->pOrderBy ) return 0;                /* Restriction (16) */
  if( pSub->pLimit && p->pWhere ) return 0;              /* Restriction (19) */
  if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){
     return 0;         /* Restriction (21) */
  }
  if( pSub->selFlags & (SF_Recursive) ){
    return 0; /* Restrictions (22) */
  }

  /*
  ** If the subquery is the right operand of a LEFT JOIN, then the
  ** subquery may not be a join itself (3a). Example of why this is not
  ** allowed:
  **
  **         t1 LEFT OUTER JOIN (t2 JOIN t3)
  **
  ** If we flatten the above, we would get
  **
  **         (t1 LEFT OUTER JOIN t2) JOIN t3
  **
  ** which is not at all the same thing.
  **
  ** If the subquery is the right operand of a LEFT JOIN, then the outer
  ** query cannot be an aggregate. (3c)  This is an artifact of the way
  ** aggregates are processed - there is no mechanism to determine if
  ** the LEFT JOIN table should be all-NULL.
  **
  ** See also tickets #306, #350, and #3300.
  */
  if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
    isLeftJoin = 1;
    if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){
      /*  (3a)             (3c)     (3b) */
      return 0;
    }
  }
#ifdef SQLITE_EXTRA_IFNULLROW
  else if( iFrom>0 && !isAgg ){
    /* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for
    ** every reference to any result column from subquery in a join, even
    ** though they are not necessary.  This will stress-test the OP_IfNullRow 
    ** opcode. */
    isLeftJoin = -1;
  }
#endif

  /* Restriction (17): If the sub-query is a compound SELECT, then it must
  ** use only the UNION ALL operator. And none of the simple select queries
  ** that make up the compound SELECT are allowed to be aggregate or distinct
  ** queries.
  */
  if( pSub->pPrior ){
    if( pSub->pOrderBy ){
      return 0;  /* Restriction (20) */
    }
    if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
      return 0; /* (17d1), (17d2), or (17d3) */
    }
    for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
      testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
      testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
      assert( pSub->pSrc!=0 );
      assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
      if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0    /* (17b) */
       || (pSub1->pPrior && pSub1->op!=TK_ALL)                 /* (17a) */
       || pSub1->pSrc->nSrc<1                                  /* (17c) */
      ){
        return 0;
      }
      testcase( pSub1->pSrc->nSrc>1 );
    }

    /* Restriction (18). */
    if( p->pOrderBy ){
      int ii;
      for(ii=0; ii<p->pOrderBy->nExpr; ii++){
        if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
      }
    }
  }

  /* Ex-restriction (23):
  ** The only way that the recursive part of a CTE can contain a compound
  ** subquery is for the subquery to be one term of a join.  But if the
  ** subquery is a join, then the flattening has already been stopped by
  ** restriction (17d3)
  */
  assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 );

  /***** If we reach this point, flattening is permitted. *****/
  SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
                   pSub->selId, pSub, iFrom));

  /* Authorize the subquery */
  pParse->zAuthContext = pSubitem->zName;
  TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0);
  testcase( i==SQLITE_DENY );
  pParse->zAuthContext = zSavedAuthContext;

  /* If the sub-query is a compound SELECT statement, then (by restrictions
  ** 17 and 18 above) it must be a UNION ALL and the parent query must 
  ** be of the form:
  **
  **     SELECT <expr-list> FROM (<sub-query>) <where-clause> 
  **
  ** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block
  ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or 
  ** OFFSET clauses and joins them to the left-hand-side of the original
  ** using UNION ALL operators. In this case N is the number of simple
  ** select statements in the compound sub-query.
  **
  ** Example:
  **
  **     SELECT a+1 FROM (
  **        SELECT x FROM tab
  **        UNION ALL
  **        SELECT y FROM tab
  **        UNION ALL
  **        SELECT abs(z*2) FROM tab2
  **     ) WHERE a!=5 ORDER BY 1
  **
  ** Transformed into:
  **
  **     SELECT x+1 FROM tab WHERE x+1!=5
  **     UNION ALL
  **     SELECT y+1 FROM tab WHERE y+1!=5
  **     UNION ALL
  **     SELECT abs(z*2)+1 FROM tab2 WHERE abs(z*2)+1!=5
  **     ORDER BY 1
  **
  ** We call this the "compound-subquery flattening".
  */
  for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){
    Select *pNew;
    ExprList *pOrderBy = p->pOrderBy;
    Expr *pLimit = p->pLimit;
    Select *pPrior = p->pPrior;
    p->pOrderBy = 0;
    p->pSrc = 0;
    p->pPrior = 0;
    p->pLimit = 0;
    pNew = sqlite3SelectDup(db, p, 0);
    p->pLimit = pLimit;
    p->pOrderBy = pOrderBy;
    p->pSrc = pSrc;
    p->op = TK_ALL;
    if( pNew==0 ){
      p->pPrior = pPrior;
    }else{
      pNew->pPrior = pPrior;
      if( pPrior ) pPrior->pNext = pNew;
      pNew->pNext = p;
      p->pPrior = pNew;
      SELECTTRACE(2,pParse,p,("compound-subquery flattener"
                              " creates %u as peer\n",pNew->selId));
    }
    if( db->mallocFailed ) return 1;
  }

  /* Begin flattening the iFrom-th entry of the FROM clause 
  ** in the outer query.
  */
  pSub = pSub1 = pSubitem->pSelect;

  /* Delete the transient table structure associated with the
  ** subquery
  */
  sqlite3DbFree(db, pSubitem->zDatabase);
  sqlite3DbFree(db, pSubitem->zName);
  sqlite3DbFree(db, pSubitem->zAlias);
  pSubitem->zDatabase = 0;
  pSubitem->zName = 0;
  pSubitem->zAlias = 0;
  pSubitem->pSelect = 0;

  /* Defer deleting the Table object associated with the
  ** subquery until code generation is
  ** complete, since there may still exist Expr.pTab entries that
  ** refer to the subquery even after flattening.  Ticket #3346.
  **
  ** pSubitem->pTab is always non-NULL by test restrictions and tests above.
  */
  if( ALWAYS(pSubitem->pTab!=0) ){
    Table *pTabToDel = pSubitem->pTab;
    if( pTabToDel->nTabRef==1 ){
      Parse *pToplevel = sqlite3ParseToplevel(pParse);
      pTabToDel->pNextZombie = pToplevel->pZombieTab;
      pToplevel->pZombieTab = pTabToDel;
    }else{
      pTabToDel->nTabRef--;
    }
    pSubitem->pTab = 0;
  }

  /* The following loop runs once for each term in a compound-subquery
  ** flattening (as described above).  If we are doing a different kind
  ** of flattening - a flattening other than a compound-subquery flattening -
  ** then this loop only runs once.
  **
  ** This loop moves all of the FROM elements of the subquery into the
  ** the FROM clause of the outer query.  Before doing this, remember
  ** the cursor number for the original outer query FROM element in
  ** iParent.  The iParent cursor will never be used.  Subsequent code
  ** will scan expressions looking for iParent references and replace
  ** those references with expressions that resolve to the subquery FROM
  ** elements we are now copying in.
  */
  for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
    int nSubSrc;
    u8 jointype = 0;
    pSubSrc = pSub->pSrc;     /* FROM clause of subquery */
    nSubSrc = pSubSrc->nSrc;  /* Number of terms in subquery FROM clause */
    pSrc = pParent->pSrc;     /* FROM clause of the outer query */

    if( pSrc ){
      assert( pParent==p );  /* First time through the loop */
      jointype = pSubitem->fg.jointype;
    }else{
      assert( pParent!=p );  /* 2nd and subsequent times through the loop */
      pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
      if( pSrc==0 ){
        assert( db->mallocFailed );
        break;
      }
    }

    /* The subquery uses a single slot of the FROM clause of the outer
    ** query.  If the subquery has more than one element in its FROM clause,
    ** then expand the outer query to make space for it to hold all elements
    ** of the subquery.
    **
    ** Example:
    **
    **    SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB;
    **
    ** The outer query has 3 slots in its FROM clause.  One slot of the
    ** outer query (the middle slot) is used by the subquery.  The next
    ** block of code will expand the outer query FROM clause to 4 slots.
    ** The middle slot is expanded to two slots in order to make space
    ** for the two elements in the FROM clause of the subquery.
    */
    if( nSubSrc>1 ){
      pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1);
      if( db->mallocFailed ){
        break;
      }
    }

    /* Transfer the FROM clause terms from the subquery into the
    ** outer query.
    */
    for(i=0; i<nSubSrc; i++){
      sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing);
      assert( pSrc->a[i+iFrom].fg.isTabFunc==0 );
      pSrc->a[i+iFrom] = pSubSrc->a[i];
      iNewParent = pSubSrc->a[i].iCursor;
      memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
    }
    pSrc->a[iFrom].fg.jointype = jointype;
  
    /* Now begin substituting subquery result set expressions for 
    ** references to the iParent in the outer query.
    ** 
    ** Example:
    **
    **   SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
    **   \                     \_____________ subquery __________/          /
    **    \_____________________ outer query ______________________________/
    **
    ** We look at every expression in the outer query and every place we see
    ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
    */
    if( pSub->pOrderBy ){
      /* At this point, any non-zero iOrderByCol values indicate that the
      ** ORDER BY column expression is identical to the iOrderByCol'th
      ** expression returned by SELECT statement pSub. Since these values
      ** do not necessarily correspond to columns in SELECT statement pParent,
      ** zero them before transfering the ORDER BY clause.
      **
      ** Not doing this may cause an error if a subsequent call to this
      ** function attempts to flatten a compound sub-query into pParent
      ** (the only way this can happen is if the compound sub-query is
      ** currently part of pSub->pSrc). See ticket [d11a6e908f].  */
      ExprList *pOrderBy = pSub->pOrderBy;
      for(i=0; i<pOrderBy->nExpr; i++){
        pOrderBy->a[i].u.x.iOrderByCol = 0;
      }
      assert( pParent->pOrderBy==0 );
      pParent->pOrderBy = pOrderBy;
      pSub->pOrderBy = 0;
    }
    pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
    if( isLeftJoin>0 ){
      setJoinExpr(pWhere, iNewParent);
    }
    pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
    if( db->mallocFailed==0 ){
      SubstContext x;
      x.pParse = pParse;
      x.iTable = iParent;
      x.iNewTable = iNewParent;
      x.isLeftJoin = isLeftJoin;
      x.pEList = pSub->pEList;
      substSelect(&x, pParent, 0);
    }
  
    /* The flattened query is distinct if either the inner or the
    ** outer query is distinct. 
    */
    pParent->selFlags |= pSub->selFlags & SF_Distinct;
  
    /*
    ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
    **
    ** One is tempted to try to add a and b to combine the limits.  But this
    ** does not work if either limit is negative.
    */
    if( pSub->pLimit ){
      pParent->pLimit = pSub->pLimit;
      pSub->pLimit = 0;
    }
  }

  /* Finially, delete what is left of the subquery and return
  ** success.
  */
  sqlite3SelectDelete(db, pSub1);

#if SELECTTRACE_ENABLED
  if( sqlite3SelectTrace & 0x100 ){
    SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
    sqlite3TreeViewSelect(0, p, 0);
  }
#endif

  return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq (%rdi), %rbx
xorl %r13d, %r13d
testb $0x1, 0x5c(%rbx)
jne 0x45a8b6
cmpq $0x0, 0x70(%rsi)
jne 0x45a8b6
movl %edx, %r14d
movq 0x28(%rsi), %r12
movslq %edx, %rax
imulq $0x70, %rax, %r11
movq 0x30(%r12,%r11), %rbp
cmpq $0x0, 0x70(%rbp)
je 0x45a8c8
movl %r13d, %eax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rdi, %r15
movq 0x150(%rdi), %r9
movl 0x48(%r12,%r11), %eax
movq 0x28(%rbp), %r10
movq 0x60(%rbp), %r8
testq %r8, %r8
je 0x45a8fd
cmpq $0x0, 0x60(%rsi)
jne 0x45a8b6
cmpq $0x0, 0x18(%r8)
jne 0x45a8b6
movl 0xc(%rsi), %edx
btl $0x8, %edx
jb 0x45a8b6
jmp 0x45a900
movl 0xc(%rsi), %edx
movl (%r10), %edi
testl %edi, %edi
je 0x45a8b6
movq %r9, 0x28(%rsp)
movl 0xc(%rbp), %r9d
testb $0x1, %r9b
jne 0x45a8b6
testq %r8, %r8
je 0x45a926
testl %ecx, %ecx
jne 0x45a8b6
cmpl $0x1, (%r12)
jg 0x45a8b6
movl %eax, 0x44(%rsp)
movq 0x48(%rsi), %rax
testq %rax, %rax
je 0x45a93e
cmpq $0x0, 0x48(%rbp)
jne 0x45a8b6
testl %ecx, %ecx
je 0x45a94d
cmpq $0x0, 0x48(%rbp)
jne 0x45a8b6
testq %r8, %r8
je 0x45a978
cmpq $0x0, 0x30(%rsi)
jne 0x45a8b6
movl %edx, %r8d
andl $0x1, %r8d
andl $0x2000, %r9d           # imm = 0x2000
orl %r8d, %r9d
testl %r9d, %r9d
je 0x45a983
jmp 0x45a8b6
btl $0xd, %r9d
jb 0x45a8b6
leaq (%r12,%r11), %r8
addq $0x8, %r8
movq %r8, 0x10(%rsp)
movb 0x3c(%r8), %r8b
xorl %r9d, %r9d
movb %r8b, 0x7(%rsp)
testb $0x20, %r8b
jne 0x45aa17
cmpq $0x0, 0x50(%rbp)
movq %rsi, 0x8(%rsp)
movq %r11, 0x18(%rsp)
je 0x45aa6f
testl %ecx, %ecx
setne %cl
cmpq $0x0, 0x48(%rbp)
setne %sil
orb %cl, %dl
orb %sil, %dl
xorl %r13d, %r13d
testb $0x1, %dl
jne 0x45a8b6
cmpl $0x1, (%r12)
jne 0x45a8b6
movq %rbp, %rcx
testq %rcx, %rcx
je 0x45aa44
testb $0x9, 0xc(%rcx)
jne 0x45a8b6
movq 0x50(%rcx), %rdx
testq %rdx, %rdx
je 0x45aa06
cmpb $0x7c, 0x8(%rcx)
jne 0x45a8b6
movq 0x28(%rcx), %rcx
cmpl $0x0, (%rcx)
movq %rdx, %rcx
jg 0x45a9e4
jmp 0x45a8b6
xorl %r13d, %r13d
testl %ecx, %ecx
jne 0x45a8b6
cmpl $0x1, %edi
jg 0x45a8b6
movq 0x28(%r10), %rdi
cmpl $0x0, 0x54(%rdi)
jne 0x45a8b6
movl $0x1, %r9d
jmp 0x45a9a2
testq %rax, %rax
je 0x45aa6f
movslq (%rax), %rcx
testq %rcx, %rcx
jle 0x45aa6f
shlq $0x5, %rcx
xorl %r13d, %r13d
xorl %edx, %edx
cmpw $0x0, 0x24(%rax,%rdx)
je 0x45a8b6
addq $0x20, %rdx
cmpq %rdx, %rcx
jne 0x45aa5a
movl %r9d, 0x3c(%rsp)
movq 0x10(%rsp), %rax
movq 0x10(%rax), %rax
movq %rax, 0x150(%r15)
movq %r15, %rdi
movl $0x15, %esi
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x453d2a
movq 0x8(%rsp), %r8
movq 0x28(%rsp), %rax
movq %rax, 0x150(%r15)
movq 0x50(%rbp), %r13
testq %r13, %r13
je 0x45ab49
leaq 0x48(%r8), %rax
movq %rax, 0x28(%rsp)
movq 0x48(%r8), %rax
movq %rax, 0x20(%rsp)
movq 0x50(%r8), %rbp
movq 0x60(%r8), %rax
movq %rax, 0x30(%rsp)
xorl %eax, %eax
movq %rax, 0x28(%r8)
movq %rax, 0x60(%r8)
movq 0x28(%rsp), %rax
pxor %xmm0, %xmm0
movdqu %xmm0, (%rax)
movq %rbx, %rdi
movq %r8, %rsi
xorl %edx, %edx
callq 0x452660
movq 0x8(%rsp), %r8
movq 0x30(%rsp), %rcx
movq %rcx, 0x60(%r8)
movq 0x20(%rsp), %rcx
movq %rcx, 0x48(%r8)
movq %r12, 0x28(%r8)
movb $0x7c, 0x8(%r8)
testq %rax, %rax
je 0x45ab32
movq %rbp, 0x50(%rax)
testq %rbp, %rbp
je 0x45ab2b
movq %rax, 0x58(%rbp)
movq %r8, 0x58(%rax)
movq %rax, %rbp
movq %rbp, 0x50(%r8)
cmpb $0x0, 0x61(%rbx)
jne 0x45b15d
movq 0x50(%r13), %r13
testq %r13, %r13
jne 0x45aad5
movq 0x10(%rsp), %rax
movq 0x8(%rax), %rsi
movq 0x28(%rax), %rax
movq %rax, 0x48(%rsp)
testq %rsi, %rsi
je 0x45ab6d
movq %rbx, %rdi
callq 0x415f0a
movq 0x8(%rsp), %r8
movl %r14d, %ebp
movq 0x10(%rsp), %rax
movq 0x10(%rax), %rsi
testq %rsi, %rsi
je 0x45ab8b
movq %rbx, %rdi
callq 0x415f0a
movq 0x8(%rsp), %r8
movq 0x10(%rsp), %rax
leaq 0x8(%rax), %r14
movq 0x18(%rax), %rsi
testq %rsi, %rsi
je 0x45abaa
movq %rbx, %rdi
callq 0x415f0a
movq 0x8(%rsp), %r8
xorl %eax, %eax
movq 0x10(%rsp), %rcx
movq %rax, 0x28(%rcx)
movq %rax, 0x10(%r14)
pxor %xmm0, %xmm0
movdqu %xmm0, (%r14)
movq 0x20(%rcx), %rax
testq %rax, %rax
movl %ebp, %r14d
movq 0x18(%rsp), %rsi
je 0x45ac0f
movl 0x3c(%rax), %ecx
cmpl $0x1, %ecx
jne 0x45abfd
movq 0xa0(%r15), %rcx
testq %rcx, %rcx
cmoveq %r15, %rcx
movq 0x170(%rcx), %rdx
movq %rdx, 0x78(%rax)
movq %rax, 0x170(%rcx)
jmp 0x45ac02
decl %ecx
movl %ecx, 0x3c(%rax)
movq 0x10(%rsp), %rax
movq $0x0, 0x20(%rax)
testq %r8, %r8
je 0x45b13b
incl %r14d
movl $0xffffffff, %r13d      # imm = 0xFFFFFFFF
movdqa 0xf57c6(%rip), %xmm10   # 0x5503f0
pcmpeqd %xmm11, %xmm11
movdqa 0xf57c8(%rip), %xmm12   # 0x550400
movq 0x48(%rsp), %rax
movq %rax, 0x20(%rsp)
movl %r14d, 0x40(%rsp)
movq 0x20(%rsp), %rax
movq 0x28(%rax), %r12
movl (%r12), %ebp
movq 0x28(%r8), %rcx
testq %rcx, %rcx
movq %r8, 0x8(%rsp)
je 0x45ac71
movq 0x10(%rsp), %rax
movb 0x3c(%rax), %al
movq %rax, 0x30(%rsp)
jmp 0x45acb9
movq $0x0, 0x30(%rsp)
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x44453c
movdqa 0xf576f(%rip), %xmm12   # 0x550400
pcmpeqd %xmm11, %xmm11
movdqa 0xf5751(%rip), %xmm10   # 0x5503f0
movq 0x18(%rsp), %rsi
movq 0x8(%rsp), %r8
movq %rax, 0x28(%r8)
testq %rax, %rax
je 0x45b13b
movq %rax, %rcx
cmpl $0x2, %ebp
jl 0x45aceb
leal -0x1(%rbp), %edx
movq %rbx, %rdi
movq %rcx, %rsi
movl %r14d, %ecx
callq 0x461331
movq 0x18(%rsp), %rsi
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x28(%rax)
cmpb $0x0, 0x61(%rbx)
je 0x45acf4
jmp 0x45b13b
cmpl $0x1, %ebp
jne 0x45ad9a
movq %rcx, 0x50(%rsp)
leaq (%rcx,%rsi), %rax
movq %rax, 0x28(%rsp)
movl $0x8, %r14d
movq 0x28(%rsp), %rax
leaq (%rax,%r14), %r13
movq 0x50(%rax,%r14), %rsi
movq %rbx, %rdi
callq 0x43857e
pxor %xmm0, %xmm0
leaq (%r12,%r14), %rsi
movl $0xe, %ecx
movq %r13, %rdi
rep  movsq (%rsi), %es:(%rdi)
movl 0x40(%r12,%r14), %r13d
movdqu %xmm0, (%r12,%r14)
movdqu %xmm0, 0x10(%r12,%r14)
movdqu %xmm0, 0x20(%r12,%r14)
movdqu %xmm0, 0x30(%r12,%r14)
movdqu %xmm0, 0x50(%r12,%r14)
movdqu %xmm0, 0x60(%r12,%r14)
movdqu %xmm0, 0x40(%r12,%r14)
addq $0x70, %r14
decq %rbp
jne 0x45ad08
movl 0x40(%rsp), %r14d
movq 0x8(%rsp), %r8
movq 0x18(%rsp), %rsi
movdqa 0xf5669(%rip), %xmm10   # 0x5503f0
pcmpeqd %xmm11, %xmm11
movdqa 0xf566b(%rip), %xmm12   # 0x550400
movq 0x50(%rsp), %rcx
movq 0x30(%rsp), %rax
movb %al, 0x44(%rcx,%rsi)
movq 0x20(%rsp), %r12
movq 0x48(%r12), %rax
testq %rax, %rax
je 0x45b057
movslq (%rax), %rdx
testq %rdx, %rdx
jle 0x45b04a
leal 0x7(%rdx), %ecx
decq %rdx
movq %rdx, %xmm0
pshufd $0x44, %xmm0, %xmm0     # xmm0 = xmm0[0,1,0,1]
shrl $0x3, %ecx
shlq $0x8, %rcx
pxor %xmm10, %xmm0
xorl %edx, %edx
movdqa 0xf55f8(%rip), %xmm1    # 0x5503e0
movdqa 0xf55e0(%rip), %xmm2    # 0x5503d0
movdqa 0xf55c8(%rip), %xmm3    # 0x5503c0
movdqa 0xf55b0(%rip), %xmm4    # 0x5503b0
movdqa %xmm1, %xmm5
pxor %xmm10, %xmm5
movdqa %xmm5, %xmm7
pcmpgtd %xmm0, %xmm7
pshufd $0xa0, %xmm7, %xmm6     # xmm6 = xmm7[0,0,2,2]
pshuflw $0xe8, %xmm6, %xmm8     # xmm8 = xmm6[0,2,2,3,4,5,6,7]
pcmpeqd %xmm0, %xmm5
pshufd $0xf5, %xmm5, %xmm5     # xmm5 = xmm5[1,1,3,3]
pshuflw $0xe8, %xmm5, %xmm9     # xmm9 = xmm5[0,2,2,3,4,5,6,7]
pand %xmm8, %xmm9
pshufd $0xf5, %xmm7, %xmm7     # xmm7 = xmm7[1,1,3,3]
pshuflw $0xe8, %xmm7, %xmm8     # xmm8 = xmm7[0,2,2,3,4,5,6,7]
por %xmm9, %xmm8
pxor %xmm11, %xmm8
packssdw %xmm8, %xmm8
movd %xmm8, %esi
testb $0x1, %sil
je 0x45ae5c
movw $0x0, 0x24(%rax,%rdx)
pand %xmm6, %xmm5
por %xmm7, %xmm5
packssdw %xmm5, %xmm5
pxor %xmm11, %xmm5
packssdw %xmm5, %xmm5
movd %xmm5, %esi
shrl $0x10, %esi
testb $0x1, %sil
je 0x45ae85
movw $0x0, 0x44(%rax,%rdx)
movdqa %xmm2, %xmm6
pxor %xmm10, %xmm6
movdqa %xmm6, %xmm7
pcmpgtd %xmm0, %xmm7
pshufd $0xa0, %xmm7, %xmm5     # xmm5 = xmm7[0,0,2,2]
pcmpeqd %xmm0, %xmm6
pshufd $0xf5, %xmm6, %xmm6     # xmm6 = xmm6[1,1,3,3]
movdqa %xmm6, %xmm8
pand %xmm5, %xmm8
pshufd $0xf5, %xmm7, %xmm7     # xmm7 = xmm7[1,1,3,3]
por %xmm7, %xmm8
packssdw %xmm8, %xmm8
pxor %xmm11, %xmm8
packssdw %xmm8, %xmm8
pextrw $0x2, %xmm8, %esi
testb $0x1, %sil
je 0x45aeda
movw $0x0, 0x64(%rax,%rdx)
pshufhw $0x84, %xmm5, %xmm5     # xmm5 = xmm5[0,1,2,3,4,5,4,6]
pshufhw $0x84, %xmm6, %xmm6     # xmm6 = xmm6[0,1,2,3,4,5,4,6]
pand %xmm5, %xmm6
pshufhw $0x84, %xmm7, %xmm5     # xmm5 = xmm7[0,1,2,3,4,5,4,6]
por %xmm6, %xmm5
pxor %xmm11, %xmm5
packssdw %xmm5, %xmm5
pextrw $0x3, %xmm5, %esi
testb $0x1, %sil
je 0x45af0f
movw $0x0, 0x84(%rax,%rdx)
movdqa %xmm3, %xmm5
pxor %xmm10, %xmm5
movdqa %xmm5, %xmm7
pcmpgtd %xmm0, %xmm7
pshufd $0xa0, %xmm7, %xmm6     # xmm6 = xmm7[0,0,2,2]
pshuflw $0xe8, %xmm6, %xmm8     # xmm8 = xmm6[0,2,2,3,4,5,6,7]
pcmpeqd %xmm0, %xmm5
pshufd $0xf5, %xmm5, %xmm5     # xmm5 = xmm5[1,1,3,3]
pshuflw $0xe8, %xmm5, %xmm9     # xmm9 = xmm5[0,2,2,3,4,5,6,7]
pand %xmm8, %xmm9
pshufd $0xf5, %xmm7, %xmm7     # xmm7 = xmm7[1,1,3,3]
pshuflw $0xe8, %xmm7, %xmm8     # xmm8 = xmm7[0,2,2,3,4,5,6,7]
por %xmm9, %xmm8
pxor %xmm11, %xmm8
packssdw %xmm8, %xmm8
pextrw $0x4, %xmm8, %esi
testb $0x1, %sil
je 0x45af6f
movw $0x0, 0xa4(%rax,%rdx)
pand %xmm6, %xmm5
por %xmm7, %xmm5
packssdw %xmm5, %xmm5
pxor %xmm11, %xmm5
packssdw %xmm5, %xmm5
pextrw $0x5, %xmm5, %esi
testb $0x1, %sil
je 0x45af99
movw $0x0, 0xc4(%rax,%rdx)
movdqa %xmm4, %xmm6
pxor %xmm10, %xmm6
movdqa %xmm6, %xmm7
pcmpgtd %xmm0, %xmm7
pshufd $0xa0, %xmm7, %xmm5     # xmm5 = xmm7[0,0,2,2]
pcmpeqd %xmm0, %xmm6
pshufd $0xf5, %xmm6, %xmm6     # xmm6 = xmm6[1,1,3,3]
movdqa %xmm6, %xmm8
pand %xmm5, %xmm8
pshufd $0xf5, %xmm7, %xmm7     # xmm7 = xmm7[1,1,3,3]
por %xmm7, %xmm8
packssdw %xmm8, %xmm8
pxor %xmm11, %xmm8
packssdw %xmm8, %xmm8
pextrw $0x6, %xmm8, %esi
testb $0x1, %sil
je 0x45aff1
movw $0x0, 0xe4(%rax,%rdx)
pshufhw $0x84, %xmm5, %xmm5     # xmm5 = xmm5[0,1,2,3,4,5,4,6]
pshufhw $0x84, %xmm6, %xmm6     # xmm6 = xmm6[0,1,2,3,4,5,4,6]
pand %xmm5, %xmm6
pshufhw $0x84, %xmm7, %xmm5     # xmm5 = xmm7[0,1,2,3,4,5,4,6]
por %xmm6, %xmm5
pxor %xmm11, %xmm5
packssdw %xmm5, %xmm5
pextrw $0x7, %xmm5, %esi
testb $0x1, %sil
je 0x45b026
movw $0x0, 0x104(%rax,%rdx)
paddq %xmm12, %xmm1
paddq %xmm12, %xmm2
paddq %xmm12, %xmm3
paddq %xmm12, %xmm4
addq $0x100, %rdx            # imm = 0x100
cmpq %rdx, %rcx
jne 0x45ae00
movq %rax, 0x48(%r8)
movq $0x0, 0x48(%r12)
movq 0x30(%r12), %rsi
testq %rsi, %rsi
je 0x45b077
movq %rbx, %rdi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x452376
movq 0x8(%rsp), %r8
movq %rax, %rbp
jmp 0x45b079
xorl %ebp, %ebp
testb $0x20, 0x7(%rsp)
je 0x45b090
movq %rbp, %rdi
movl %r13d, %esi
callq 0x4586b0
movq 0x8(%rsp), %r8
movq 0x30(%r8), %rdx
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x458727
movq 0x8(%rsp), %r8
movq %rax, 0x30(%r8)
cmpb $0x0, 0x61(%rbx)
jne 0x45b0e5
movq %r15, 0x58(%rsp)
movl 0x44(%rsp), %eax
movl %eax, 0x60(%rsp)
movl %r13d, 0x64(%rsp)
movl 0x3c(%rsp), %eax
movl %eax, 0x68(%rsp)
movq (%r12), %rax
movq %rax, 0x70(%rsp)
leaq 0x58(%rsp), %rdi
movq %r8, %rsi
xorl %edx, %edx
callq 0x461571
movq 0x8(%rsp), %r8
movl 0xc(%r12), %eax
andl $0x1, %eax
orl %eax, 0xc(%r8)
movq 0x60(%r12), %rax
testq %rax, %rax
je 0x45b108
movq %rax, 0x60(%r8)
movq $0x0, 0x60(%r12)
movq 0x50(%r8), %r8
movq 0x50(%r12), %r12
movq %r12, 0x20(%rsp)
testq %r8, %r8
movq 0x18(%rsp), %rsi
movdqa 0xf52c9(%rip), %xmm10   # 0x5503f0
pcmpeqd %xmm11, %xmm11
movdqa 0xf52cb(%rip), %xmm12   # 0x550400
jne 0x45ac47
movq 0x48(%rsp), %rsi
testq %rsi, %rsi
je 0x45b15d
movl $0x1, %r13d
movq %rbx, %rdi
movl $0x1, %edx
callq 0x43832f
jmp 0x45a8b6
movl $0x1, %r13d
jmp 0x45a8b6