// File: /workspace/github_c_makefile_star2_O1/genometools[P]genometools/src/external/sqlite-3.33.0/sqlite3.c
// Function: windowCodeRangeTest
static void windowCodeRangeTest(
  WindowCodeArg *p,
  int op,                         /* OP_Ge, OP_Gt, or OP_Le */
  int csr1,                       /* Cursor number for cursor 1 */
  int regVal,                     /* Register containing non-negative number */
  int csr2,                       /* Cursor number for cursor 2 */
  int lbl                         /* Jump destination if condition is true */
){
  Parse *pParse = p->pParse;
  Vdbe *v = sqlite3GetVdbe(pParse);
  ExprList *pOrderBy = p->pMWin->pOrderBy;  /* ORDER BY clause for window */
  int reg1 = sqlite3GetTempReg(pParse);     /* Reg. for csr1.peerVal+regVal */
  int reg2 = sqlite3GetTempReg(pParse);     /* Reg. for csr2.peerVal */
  int regString = ++pParse->nMem;           /* Reg. for constant value '' */
  int arith = OP_Add;                       /* OP_Add or OP_Subtract */
  int addrGe;                               /* Jump destination */

  assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
  assert( pOrderBy && pOrderBy->nExpr==1 );
  if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_DESC ){
    switch( op ){
      case OP_Ge: op = OP_Le; break;
      case OP_Gt: op = OP_Lt; break;
      default: assert( op==OP_Le ); op = OP_Ge; break;
    }
    arith = OP_Subtract;
  }

  /* Read the peer-value from each cursor into a register */
  windowReadPeerValues(p, csr1, reg1);
  windowReadPeerValues(p, csr2, reg2);

  VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl",
      reg1, (arith==OP_Add ? "+" : "-"), regVal,
      ((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2
  ));

  /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
  ** This block adds (or subtracts for DESC) the numeric value in regVal
  ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
  ** then leave reg1 as it is. In pseudo-code, this is implemented as:
  **
  **   if( reg1>='' ) goto addrGe;
  **   reg1 = reg1 +/- regVal
  **   addrGe:
  **
  ** Since all strings and blobs are greater-than-or-equal-to an empty string,
  ** the add/subtract is skipped for these, as required. If reg1 is a NULL,
  ** then the arithmetic is performed, but since adding or subtracting from
  ** NULL is always NULL anyway, this case is handled as required too.  */
  sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
  addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
  VdbeCoverage(v);
  sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
  sqlite3VdbeJumpHere(v, addrGe);

  /* If the BIGNULL flag is set for the ORDER BY, then it is required to
  ** consider NULL values to be larger than all other values, instead of
  ** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this
  ** (and adding that capability causes a performance regression), so
  ** instead if the BIGNULL flag is set then cases where either reg1 or
  ** reg2 are NULL are handled separately in the following block. The code
  ** generated is equivalent to:
  **
  **   if( reg1 IS NULL ){
  **     if( op==OP_Ge ) goto lbl;
  **     if( op==OP_Gt && reg2 IS NOT NULL ) goto lbl;
  **     if( op==OP_Le && reg2 IS NULL ) goto lbl;
  **   }else if( reg2 IS NULL ){
  **     if( op==OP_Le ) goto lbl;
  **   }
  **
  ** Additionally, if either reg1 or reg2 are NULL but the jump to lbl is
  ** not taken, control jumps over the comparison operator coded below this
  ** block.  */
  if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_BIGNULL ){
    /* This block runs if reg1 contains a NULL. */
    int addr = sqlite3VdbeAddOp1(v, OP_NotNull, reg1); VdbeCoverage(v);
    switch( op ){
      case OP_Ge:
        sqlite3VdbeAddOp2(v, OP_Goto, 0, lbl);
        break;
      case OP_Gt:
        sqlite3VdbeAddOp2(v, OP_NotNull, reg2, lbl);
        VdbeCoverage(v);
        break;
      case OP_Le:
        sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl);
        VdbeCoverage(v);
        break;
      default: assert( op==OP_Lt ); /* no-op */ break;
    }
    sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);

    /* This block runs if reg1 is not NULL, but reg2 is. */
    sqlite3VdbeJumpHere(v, addr);
    sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); VdbeCoverage(v);
    if( op==OP_Gt || op==OP_Ge ){
      sqlite3VdbeChangeP2(v, -1, sqlite3VdbeCurrentAddr(v)+1);
    }
  }

  /* Compare registers reg2 and reg1, taking the jump if required. Note that
  ** control skips over this test if the BIGNULL flag is set and either
  ** reg1 or reg2 contain a NULL value.  */
  sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
  sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);

  assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le );
  testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge);
  testcase(op==OP_Lt); VdbeCoverageIf(v, op==OP_Lt);
  testcase(op==OP_Le); VdbeCoverageIf(v, op==OP_Le);
  testcase(op==OP_Gt); VdbeCoverageIf(v, op==OP_Gt);
  sqlite3ReleaseTempReg(pParse, reg1);
  sqlite3ReleaseTempReg(pParse, reg2);

  VdbeModuleComment((v, "CodeRangeTest: end"));
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl %r9d, %ebp
movl %r8d, 0x18(%rsp)
movl %ecx, 0x1c(%rsp)
movl %edx, 0x14(%rsp)
movl %esi, %r15d
movq %rdi, %r14
movq (%rdi), %rbx
movq %rbx, %rdi
callq 0x2c5ddf
movq %rax, %r12
movq 0x8(%r14), %rax
movq 0x18(%rax), %rcx
movb 0x1f(%rbx), %al
testb %al, %al
je 0x2e8744
decb %al
movb %al, 0x1f(%rbx)
movzbl %al, %eax
movl 0xd4(%rbx,%rax,4), %edx
jmp 0x2e874e
movl 0x38(%rbx), %eax
incl %eax
movl %eax, %edx
movl %eax, 0x38(%rbx)
movb 0x1f(%rbx), %al
testb %al, %al
movl %ebp, 0xc(%rsp)
je 0x2e876b
decb %al
movb %al, 0x1f(%rbx)
movzbl %al, %eax
movl 0xd4(%rbx,%rax,4), %r13d
jmp 0x2e8776
movl 0x38(%rbx), %r13d
incl %r13d
movl %r13d, 0x38(%rbx)
movl 0x38(%rbx), %ebp
incl %ebp
movl %ebp, 0x38(%rbx)
movq %rcx, 0x20(%rsp)
movzbl 0x18(%rcx), %eax
xorl %ecx, %ecx
cmpl $0x36, %r15d
sete %cl
xorl $0x39, %ecx
cmpl $0x39, %r15d
movl $0x37, %esi
cmovnel %ecx, %esi
andl $0x1, %eax
leal 0x69(%rax), %ecx
movl %ecx, 0x10(%rsp)
testl %eax, %eax
cmovel %r15d, %esi
movl %esi, 0x8(%rsp)
movq %r14, %rdi
movl 0x14(%rsp), %esi
movl %edx, %r15d
callq 0x2e89fc
movq %r14, %rdi
movl 0x18(%rsp), %esi
movl %r13d, %edx
callq 0x2e89fc
movq %r12, %rdi
movl $0x73, %esi
xorl %edx, %edx
movl %ebp, %ecx
xorl %r8d, %r8d
callq 0x2b200c
leaq 0xeb0a4(%rip), %rdx     # 0x3d3890
movq %r12, %rdi
movl %eax, %esi
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
callq 0x285198
movq %r12, %rdi
movl $0x39, %esi
movl %ebp, %edx
xorl %ecx, %ecx
movl %r15d, %r8d
callq 0x2b200c
movl %eax, %ebp
movq %r12, %rdi
movl 0x10(%rsp), %esi
movl 0x1c(%rsp), %edx
movl %r15d, %ecx
movl %r15d, %r8d
callq 0x2b200c
movl 0x90(%r12), %eax
movq (%r12), %rcx
cmpb $0x0, 0x61(%rcx)
je 0x2e8842
leaq 0x1e1648(%rip), %rcx    # 0x4c9e88
jmp 0x2e885d
leal -0x1(%rax), %ecx
testl %ebp, %ebp
cmovnsl %ebp, %ecx
movslq %ecx, %rcx
leaq (%rcx,%rcx,2), %rcx
shlq $0x3, %rcx
addq 0x88(%r12), %rcx
movl 0xc(%rsp), %ebp
movl %eax, 0x8(%rcx)
movq 0x20(%rsp), %rax
testb $0x2, 0x18(%rax)
movl 0x8(%rsp), %esi
je 0x2e8983
movl %r13d, %r14d
movq %r12, %rdi
movl $0x33, %esi
movl %r15d, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x2b200c
movl 0x8(%rsp), %ecx
movl %eax, %r13d
cmpl $0x36, %ecx
je 0x2e88bb
cmpl $0x37, %ecx
je 0x2e88b1
cmpl $0x39, %ecx
jne 0x2e88d0
movq %r12, %rdi
movl $0xb, %esi
xorl %edx, %edx
jmp 0x2e88c6
movq %r12, %rdi
movl $0x32, %esi
jmp 0x2e88c3
movq %r12, %rdi
movl $0x33, %esi
movl %r14d, %edx
movl %ebp, %ecx
xorl %r8d, %r8d
callq 0x2b200c
movl 0x90(%r12), %ecx
addl $0x3, %ecx
movq %r12, %rdi
movl $0xb, %esi
xorl %edx, %edx
xorl %r8d, %r8d
callq 0x2b200c
movl 0x90(%r12), %eax
movq (%r12), %rcx
cmpb $0x0, 0x61(%rcx)
je 0x2e8908
leaq 0x1e1582(%rip), %rcx    # 0x4c9e88
jmp 0x2e8925
leal -0x1(%rax), %ecx
testl %r13d, %r13d
cmovnsl %r13d, %ecx
movslq %ecx, %rcx
leaq (%rcx,%rcx,2), %rcx
shlq $0x3, %rcx
addq 0x88(%r12), %rcx
movl %eax, 0x8(%rcx)
movq %r12, %rdi
movl $0x32, %esi
movl %r14d, %r13d
movl %r14d, %edx
movl %ebp, %ecx
xorl %r8d, %r8d
callq 0x2b200c
movl 0x8(%rsp), %esi
cmpl $0x39, %esi
je 0x2e894e
cmpl $0x36, %esi
jne 0x2e8983
movslq 0x90(%r12), %rcx
leal 0x1(%rcx), %eax
movq (%r12), %rdx
cmpb $0x0, 0x61(%rdx)
je 0x2e896c
leaq 0x1e151e(%rip), %rcx    # 0x4c9e88
jmp 0x2e8980
movq 0x88(%r12), %rdx
leaq (%rcx,%rcx,2), %rcx
leaq (%rdx,%rcx,8), %rcx
addq $-0x18, %rcx
movl %eax, 0x8(%rcx)
movq %r12, %rdi
movl %r13d, %edx
movl %ebp, %ecx
movl %r15d, %r8d
callq 0x2b200c
movslq 0x90(%r12), %rax
testq %rax, %rax
jle 0x2e89b3
movq 0x88(%r12), %rcx
leaq (%rax,%rax,2), %rax
movw $0x80, -0x16(%rcx,%rax,8)
testl %r15d, %r15d
je 0x2e89d0
movzbl 0x1f(%rbx), %eax
cmpq $0x7, %rax
ja 0x2e89d0
leal 0x1(%rax), %ecx
movb %cl, 0x1f(%rbx)
movl %r15d, 0xd4(%rbx,%rax,4)
testl %r13d, %r13d
je 0x2e89ed
movzbl 0x1f(%rbx), %eax
cmpq $0x7, %rax
ja 0x2e89ed
leal 0x1(%rax), %ecx
movb %cl, 0x1f(%rbx)
movl %r13d, 0xd4(%rbx,%rax,4)
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq