// File: besm6[P]pascal-re/pascompl.cc
// Function: caseStatement()
void caseStatement()
{
    typedef struct CaseClause : public BESM6Obj {
        CaseClause * next;
        Word value;
        int64_t offset;
    } * CaseClausePtr;

    CaseClausePtr allClauses, curClause, clause, old = NULL;
    bool isIntCase;
    bool otherSeen;
    int64_t otherOffset = -1;
    bool itemsEnded, goodMode;
    TypesPtr firstType, itemtype, exprtype;
    Word itemvalue;
    int64_t itemSpan;
    Word expected;
    int64_t startLine, l4var17z, endOfStmt;
    Word minValue, maxValue;

    startLine = lineCnt;
    expression();
    exprtype = curExpr->typ;
    otherSeen = false;
    if (exprtype == AlfaType or
        (exprtype->k == kindScalar || exprtype->k == kindRange))
        (void) formOperator(LOAD);
    else
        error(25); /* errExprNotOfADiscreteType */
    disableNorm();
    l4var17z = 0;
    endOfStmt = 0;
    allClauses = NULL;
    formJump(l4var17z);
    checkSymAndRead(OFSY);
    firstType = NULL;
    goodMode = true;
    do {
        if (not (SY == SEMICOLON || SY == ENDSY)) {
            padToLeft();
            arithMode = 1;
            if (SY == OTHERSY) {
                if (otherSeen)
                    error(73); /* errCaseLabelsIdentical */
                inSymbol();
                otherSeen = true;
                otherOffset = moduleOffset;
            } else do {
                    parseLiteral(itemtype, itemvalue, true);
                    if (itemtype != NULL) {
                        if (firstType == NULL) {
                            firstType = itemtype;
                        } else {
                            if (not typeCheck(itemtype, firstType))
                                error(errConstOfOtherTypeNeeded);
                        } /* 15700 */
                        clause = new CaseClause;
                        clause->value = itemvalue;
                        clause->offset = moduleOffset;
                        curClause = allClauses;
                        while (curClause != NULL) {
                            if (itemvalue == curClause->value) {
                                error(73); /* errCaseLabelsIdentical */
                                break;
                            } else if (itemvalue.i < curClause->value.i) {
                                break;
                            } else {
                                old = curClause;
                                curClause = curClause->next;
                            }
                        } /* 15723 */
                        if (curClause == allClauses) {
                            clause->next = allClauses;
                            allClauses = clause;
                        } else {
                            clause->next = curClause;
                            old->next = clause;
                        }
                        inSymbol();
                    } /* 15735 */
                  itemsEnded = (SY != COMMA);
                  if (not itemsEnded)
                      inSymbol();
                } while (!itemsEnded);
            checkSymAndRead(COLON);
            Statement();
            goodMode = goodMode and (arithMode == 1);
            formJump(endOfStmt);
        } /* 15762 */
        itemsEnded = (SY == ENDSY);
        if (not itemsEnded)
            inSymbol();
    } while (!itemsEnded);
    if (SY != ENDSY) {
        requiredSymErr(ENDSY);
        stmtName = "CASE  ";
        reportStmtType(startLine);
    } else
        inSymbol();
    if (not typeCheck(firstType, exprtype)) {
        error(88); /* errDifferentTypesOfLabelsAndExpr */;
        return;
    }
    padToLeft();
    isIntCase = typeCheck(exprtype, IntegerType);
    if (allClauses != NULL) {
        expected = allClauses->value;
        minValue = expected;
        curClause = allClauses;
        while (curClause != NULL) {
            if (expected == curClause->value and
                exprtype->k == kindScalar) {
                maxValue = expected;
                if (isIntCase) {
                    expected.i = expected.i + 1; // Integers with exponent
                } else {
                    curVal = expected;
                    curVal.ii = curVal.ii + 1; // Integers without exponent
                    expected = curVal;
                }
                curClause = curClause->next;
            } else {
                itemSpan = 34000;
                P0715(0, l4var17z);
                if (firstType->k == kindRange) {
                    itemSpan = std::max(std::abs(firstType->cast<RangeT>().left),
                                        std::abs(firstType->cast<RangeT>().right));
                } else {
                    if (firstType->k == kindScalar)
                        itemSpan = firstType->cast<ScalarT>().numen;
                }
                itemsEnded = (itemSpan < 32000);
                if (itemsEnded) {
                    form1Insn(KATI+14);
                } else {
                    form1Insn(KATX+SP+1);
                }
                minValue.i = (minValue.i - minValue.i); /* WTF? */
                while (allClauses != NULL) {
                    if (itemsEnded) {
                        curVal.i = (minValue.i - allClauses->value.i);
                        curVal.i = curVal.ii;
                        form1Insn(getValueOrAllocSymtab(curVal.i) +
                                  (KUTM+I14));
                        form1Insn(KVZM+I14 + allClauses->offset);
                        minValue = allClauses->value;
                    } else {
                        form1Insn(KXTA+SP+1);
                        curVal = allClauses->value;
                        form2Insn(KAEX + I8 + getFCSToffset(),
                                  InsnTemp[UZA] + allClauses->offset);
                    }
                    allClauses = allClauses->next;
                }
                if (otherSeen)
                    form1Insn(InsnTemp[UJ] + otherOffset);
                goto L16211;
            } /* if 16141 */
        } /* while 16142 */
        if (not otherSeen) {
            otherOffset = moduleOffset;
            formJump(endOfStmt);
        }
        P0715(0, l4var17z);
        curVal = minValue;
        P0715(-(InsnTemp[U1A]+otherOffset), maxValue.i);
        curVal = minValue;
        curVal.i = curVal.ii;
        form1Insn(KATI+14);
        curVal.i = ((moduleOffset + (1)) - curVal.i);
        if (curVal.i < 040000) {
            curVal.i = (curVal.i - 040000);
            curVal.i = allocSymtab(041000000 | (curVal.ii & 077777));
        }
        form1Insn(KUJ+I14 + curVal.i);
        while (allClauses != NULL) {
            padToLeft();
            form1Insn(InsnTemp[UJ] + allClauses->offset);
            allClauses = allClauses->next;
        }
L16211:
        P0715(0, endOfStmt);
        if (not goodMode)
            disableNorm();
        /* 16217 */
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x9e0, %rsp            # imm = 0x9E0
movq $0x0, -0x20(%rbp)
movq $-0x1, -0x30(%rbp)
movq 0x6998e(%rip), %rax     # 0x7ff70
movq %rax, -0x70(%rbp)
callq 0x14e90
movq 0x69b6e(%rip), %rax     # 0x80160
movq (%rax), %rax
movq %rax, -0x50(%rbp)
movb $0x0, -0x22(%rbp)
movq -0x50(%rbp), %rax
cmpq 0x69ab8(%rip), %rax     # 0x800c0
je 0x1661e
movq -0x50(%rbp), %rax
cmpl $0x1, 0x10(%rax)
je 0x1661e
movq -0x50(%rbp), %rax
cmpl $0x2, 0x10(%rax)
jne 0x1663d
leaq -0xf8(%rbp), %rdi
movl $0x2, %esi
callq 0x112d0
leaq -0xf8(%rbp), %rdi
callq 0x21850
jmp 0x16647
movl $0x19, %edi
callq 0x7b40
callq 0x7e00
movq $0x0, -0x78(%rbp)
movq $0x0, -0x80(%rbp)
movq $0x0, -0x8(%rbp)
leaq -0x78(%rbp), %rdi
callq 0x7e70
movl $0x2a, %edi
callq 0xb110
movq $0x0, -0x40(%rbp)
movb $0x1, -0x32(%rbp)
cmpl $0xf, 0x69852(%rip)     # 0x7fedc
je 0x16907
cmpl $0x27, 0x69845(%rip)    # 0x7fedc
je 0x16907
callq 0x7ef0
movq $0x1, 0x698eb(%rip) # 0x7ff98
cmpl $0x31, 0x69828(%rip)    # 0x7fedc
jne 0x166e6
testb $0x1, -0x22(%rbp)
je 0x166c6
movl $0x49, %edi
callq 0x7b40
leaq -0x268(%rbp), %rdi
callq 0x9790
movb $0x1, -0x22(%rbp)
movq 0x6986b(%rip), %rax     # 0x7ff48
movq %rax, -0x30(%rbp)
jmp 0x168b2
jmp 0x166e8
leaq -0x48(%rbp), %rdi
leaq -0x58(%rbp), %rsi
movl $0x1, %edx
callq 0xad20
cmpq $0x0, -0x48(%rbp)
je 0x16880
cmpq $0x0, -0x40(%rbp)
jne 0x16719
movq -0x48(%rbp), %rax
movq %rax, -0x40(%rbp)
jmp 0x1679f
movq -0x48(%rbp), %rsi
movq -0x40(%rbp), %rdx
leaq -0x2b0(%rbp), %rdi
movq %rdi, -0x988(%rbp)
callq 0xb280
movq -0x988(%rbp), %rdi
callq 0x1e950
movb %al, -0x979(%rbp)
jmp 0x16748
movb -0x979(%rbp), %al
xorb $-0x1, %al
movb %al, -0x989(%rbp)
leaq -0x2b0(%rbp), %rdi
callq 0x1e9c0
movb -0x989(%rbp), %al
testb $0x1, %al
jne 0x1676e
jmp 0x1679d
movl $0x7, %edi
callq 0x7b40
jmp 0x1679d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x2b8(%rbp)
movl %eax, -0x2bc(%rbp)
leaq -0x2b0(%rbp), %rdi
callq 0x1e9c0
jmp 0x16ebc
jmp 0x1679f
movl $0x18, %edi
callq 0x1e2e0
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq -0x58(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq 0x69788(%rip), %rcx     # 0x7ff48
movq -0x18(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x8(%rbp), %rax
movq %rax, -0x10(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x1683f
movq -0x10(%rbp), %rsi
addq $0x8, %rsi
leaq -0x58(%rbp), %rdi
callq 0x22a50
testb $0x1, %al
jne 0x167ee
jmp 0x167fa
movl $0x49, %edi
callq 0x7b40
jmp 0x1683f
leaq -0x58(%rbp), %rdi
callq 0x1dfb0
movq %rax, -0x998(%rbp)
movq -0x10(%rbp), %rdi
addq $0x8, %rdi
callq 0x1dfb0
movq %rax, %rcx
movq -0x998(%rbp), %rax
cmpq %rcx, %rax
jge 0x16828
jmp 0x1683f
movq -0x10(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x10(%rbp)
jmp 0x1683d
jmp 0x167d0
movq -0x10(%rbp), %rax
cmpq -0x8(%rbp), %rax
jne 0x1685e
movq -0x8(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x18(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x16874
movq -0x10(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x18(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
leaq -0x430(%rbp), %rdi
callq 0x9790
cmpl $0xe, 0x69655(%rip)     # 0x7fedc
setne %al
andb $0x1, %al
movb %al, -0x31(%rbp)
testb $0x1, -0x31(%rbp)
jne 0x168a1
leaq -0x5a0(%rbp), %rdi
callq 0x9790
jmp 0x168a3
movb -0x31(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x166e8
jmp 0x168b2
movl $0x12, %edi
callq 0xb110
leaq -0x5f8(%rbp), %rdi
callq 0x173f0
leaq -0x5f8(%rbp), %rdi
callq 0x229f0
xorl %eax, %eax
testb $0x1, -0x32(%rbp)
movb %al, -0x999(%rbp)
je 0x168f3
cmpq $0x1, 0x696ae(%rip)     # 0x7ff98
sete %al
movb %al, -0x999(%rbp)
movb -0x999(%rbp), %al
andb $0x1, %al
movb %al, -0x32(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x7e70
cmpl $0x27, 0x695ce(%rip)    # 0x7fedc
sete %al
andb $0x1, %al
movb %al, -0x31(%rbp)
testb $0x1, -0x31(%rbp)
jne 0x16928
leaq -0x768(%rbp), %rdi
callq 0x9790
jmp 0x1692a
movb -0x31(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x16683
cmpl $0x27, 0x6959e(%rip)    # 0x7fedc
je 0x16968
movl $0x27, %edi
callq 0x90f0
leaq 0x6964f(%rip), %rdi     # 0x7ffa0
leaq 0x1ba64(%rip), %rsi     # 0x323bc
callq 0x43f0
movq -0x70(%rbp), %rdi
callq 0x163a0
jmp 0x16974
leaq -0x8d8(%rbp), %rdi
callq 0x9790
movq -0x40(%rbp), %rsi
movq -0x50(%rbp), %rdx
leaq -0x920(%rbp), %rdi
movq %rdi, -0x9a8(%rbp)
callq 0xb280
movq -0x9a8(%rbp), %rdi
callq 0x1e950
movb %al, -0x99a(%rbp)
jmp 0x169a3
movb -0x99a(%rbp), %al
xorb $-0x1, %al
movb %al, -0x9a9(%rbp)
leaq -0x920(%rbp), %rdi
callq 0x1e9c0
movb -0x9a9(%rbp), %al
testb $0x1, %al
jne 0x169c9
jmp 0x169fb
movl $0x58, %edi
callq 0x7b40
jmp 0x16eb3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x2b8(%rbp)
movl %eax, -0x2bc(%rbp)
leaq -0x920(%rbp), %rdi
callq 0x1e9c0
jmp 0x16ebc
callq 0x7ef0
movq -0x50(%rbp), %rsi
movq 0x6969d(%rip), %rdx     # 0x800a8
leaq -0x968(%rbp), %rdi
movq %rdi, -0x9b8(%rbp)
callq 0xb280
movq -0x9b8(%rbp), %rdi
callq 0x1e950
movb %al, -0x9aa(%rbp)
jmp 0x16a32
movb -0x9aa(%rbp), %al
andb $0x1, %al
movb %al, -0x21(%rbp)
leaq -0x968(%rbp), %rdi
callq 0x1e9c0
cmpq $0x0, -0x8(%rbp)
je 0x16eb3
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x10(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x16d2a
movq -0x10(%rbp), %rsi
addq $0x8, %rsi
leaq -0x68(%rbp), %rdi
callq 0x22a50
testb $0x1, %al
jne 0x16a98
jmp 0x16b2d
movq -0x50(%rbp), %rax
cmpl $0x1, 0x10(%rax)
jne 0x16b2d
movq -0x68(%rbp), %rax
movq %rax, -0x90(%rbp)
testb $0x1, -0x21(%rbp)
je 0x16af5
leaq -0x68(%rbp), %rdi
callq 0x1dfb0
movq %rax, %rsi
addq $0x1, %rsi
leaq -0x68(%rbp), %rdi
callq 0x4ad0
jmp 0x16b1d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x2b8(%rbp)
movl %eax, -0x2bc(%rbp)
leaq -0x968(%rbp), %rdi
callq 0x1e9c0
jmp 0x16ebc
movq -0x68(%rbp), %rax
movq %rax, 0x695f0(%rip)     # 0x800f0
movq 0x695e9(%rip), %rax     # 0x800f0
addq $0x1, %rax
movq %rax, 0x695de(%rip)     # 0x800f0
movq 0x695d7(%rip), %rax     # 0x800f0
movq %rax, -0x68(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x10(%rbp)
jmp 0x16d25
movq $0x84d0, -0x60(%rbp)    # imm = 0x84D0
movq -0x78(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edi
callq 0x8910
movq -0x40(%rbp), %rax
cmpl $0x2, 0x10(%rax)
jne 0x16b9a
movq -0x40(%rbp), %rdi
callq 0x1ea10
movq 0x28(%rax), %rdi
callq 0x1e820
movq %rax, -0x970(%rbp)
movq -0x40(%rbp), %rdi
callq 0x1ea10
movq 0x30(%rax), %rdi
callq 0x1e820
movq %rax, -0x978(%rbp)
leaq -0x970(%rbp), %rdi
leaq -0x978(%rbp), %rsi
callq 0x22a90
movq (%rax), %rax
movq %rax, -0x60(%rbp)
jmp 0x16bb7
movq -0x40(%rbp), %rax
cmpl $0x1, 0x10(%rax)
jne 0x16bb5
movq -0x40(%rbp), %rdi
callq 0x1ea60
movq 0x20(%rax), %rax
movq %rax, -0x60(%rbp)
jmp 0x16bb7
cmpq $0x7d00, -0x60(%rbp)    # imm = 0x7D00
setl %al
andb $0x1, %al
movb %al, -0x31(%rbp)
testb $0x1, -0x31(%rbp)
je 0x16bd9
movl $0x2000e, %edi          # imm = 0x2000E
callq 0x7c20
jmp 0x16be3
movl $0xf00001, %edi         # imm = 0xF00001
callq 0x7c20
leaq -0x88(%rbp), %rdi
callq 0x1dfb0
movq %rax, -0x9c0(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x1dfb0
movq -0x9c0(%rbp), %rsi
subq %rax, %rsi
leaq -0x88(%rbp), %rdi
callq 0x4ad0
cmpq $0x0, -0x8(%rbp)
je 0x16d0a
testb $0x1, -0x31(%rbp)
je 0x16cbe
leaq -0x88(%rbp), %rdi
callq 0x1dfb0
movq %rax, -0x9c8(%rbp)
movq -0x8(%rbp), %rdi
addq $0x8, %rdi
callq 0x1dfb0
movq -0x9c8(%rbp), %rsi
subq %rax, %rsi
leaq 0x69492(%rip), %rdi     # 0x800f0
callq 0x4ad0
movq 0x69486(%rip), %rsi     # 0x800f0
leaq 0x6947f(%rip), %rdi     # 0x800f0
callq 0x4ad0
leaq 0x69473(%rip), %rdi     # 0x800f0
callq 0x1dfb0
movq %rax, %rdi
callq 0x8870
movq %rax, %rdi
addq $0xea8000, %rdi         # imm = 0xEA8000
callq 0x7c20
movq -0x8(%rbp), %rax
movq 0x10(%rax), %rdi
addq $0xee0000, %rdi         # imm = 0xEE0000
callq 0x7c20
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x88(%rbp)
jmp 0x16cfa
movl $0xf08001, %edi         # imm = 0xF08001
callq 0x7c20
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x69419(%rip)     # 0x800f0
callq 0x8580
movq %rax, %rdi
addq $0x80a000, %rdi         # imm = 0x80A000
movq 0x6de9b(%rip), %rsi     # 0x84b88
movq -0x8(%rbp), %rax
addq 0x10(%rax), %rsi
callq 0x7da0
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x16c18
testb $0x1, -0x22(%rbp)
je 0x16d20
movq 0x6de81(%rip), %rdi     # 0x84b98
addq -0x30(%rbp), %rdi
callq 0x7c20
jmp 0x16e99
jmp 0x16a73
testb $0x1, -0x22(%rbp)
jne 0x16d44
movq 0x69211(%rip), %rax     # 0x7ff48
movq %rax, -0x30(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x7e70
movq -0x78(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edi
callq 0x8910
movq -0x88(%rbp), %rax
movq %rax, 0x69391(%rip)     # 0x800f0
movq 0x6de2a(%rip), %rcx     # 0x84b90
addq -0x30(%rbp), %rcx
xorl %eax, %eax
subq %rcx, %rax
movq %rax, -0x9d8(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x1dfb0
movq -0x9d8(%rbp), %rdi
movq %rax, %rsi
callq 0x8910
movq -0x88(%rbp), %rax
movq %rax, 0x69351(%rip)     # 0x800f0
movq 0x6934a(%rip), %rsi     # 0x800f0
leaq 0x69343(%rip), %rdi     # 0x800f0
callq 0x4ad0
movl $0x2000e, %edi          # imm = 0x2000E
callq 0x7c20
movq 0x69185(%rip), %rax     # 0x7ff48
addq $0x1, %rax
movq %rax, -0x9d0(%rbp)
leaq 0x6931b(%rip), %rdi     # 0x800f0
callq 0x1dfb0
movq -0x9d0(%rbp), %rsi
subq %rax, %rsi
leaq 0x69305(%rip), %rdi     # 0x800f0
callq 0x4ad0
leaq 0x692f9(%rip), %rdi     # 0x800f0
callq 0x1dfb0
cmpq $0x4000, %rax           # imm = 0x4000
jge 0x16e4f
leaq 0x692e5(%rip), %rdi     # 0x800f0
callq 0x1dfb0
movq %rax, %rsi
subq $0x4000, %rsi           # imm = 0x4000
leaq 0x692cf(%rip), %rdi     # 0x800f0
callq 0x4ad0
movq 0x692c3(%rip), %rdi     # 0x800f0
andq $0x7fff, %rdi           # imm = 0x7FFF
orq $0x840000, %rdi         # imm = 0x840000
callq 0x8390
movq %rax, %rsi
leaq 0x692a6(%rip), %rdi     # 0x800f0
callq 0x4ad0
leaq 0x6929a(%rip), %rdi     # 0x800f0
callq 0x1dfb0
movq %rax, %rdi
addq $0xec0000, %rdi         # imm = 0xEC0000
callq 0x7c20
cmpq $0x0, -0x8(%rbp)
je 0x16e97
callq 0x7ef0
movq 0x6dd1b(%rip), %rdi     # 0x84b98
movq -0x8(%rbp), %rax
addq 0x10(%rax), %rdi
callq 0x7c20
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x16e6a
jmp 0x16e99
movq -0x80(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edi
callq 0x8910
testb $0x1, -0x32(%rbp)
jne 0x16eb1
callq 0x7e00
jmp 0x16eb3
addq $0x9e0, %rsp            # imm = 0x9E0
popq %rbp
retq
movq -0x2b8(%rbp), %rdi
callq 0x44c0
nopl (%rax,%rax)