// File: karel-brinda[P]ococo/ext/htslib/cram/cram_decode.c
// Function: cram_decode_slice_xref
static int cram_decode_slice_xref(cram_slice *s, int required_fields) {
    int rec;

    if (!(required_fields & (SAM_RNEXT | SAM_PNEXT | SAM_TLEN))) {
	for (rec = 0; rec < s->hdr->num_records; rec++) {
	    cram_record *cr = &s->crecs[rec];

	    cr->tlen = 0;
	    cr->mate_pos = 0;
	    cr->mate_ref_id = -1;
	}

	return 0;
    }

    for (rec = 0; rec < s->hdr->num_records; rec++) {
	cram_record *cr = &s->crecs[rec];

	if (cr->mate_line >= 0) {
	    if (cr->mate_line < s->hdr->num_records) {
		/*
		 * On the first read, loop through computing lengths.
		 * It's not perfect as we have one slice per reference so we
		 * cannot detect when TLEN should be zero due to seqs that
		 * map to multiple references.
		 *
		 * We also cannot set tlen correct when it spans a slice for
		 * other reasons. This may make tlen too small. Should we
		 * fix this by forcing TLEN to be stored verbatim in such cases?
		 *
		 * Or do we just admit defeat and output 0 for tlen? It's the
		 * safe option...
		 */
		if (cr->tlen == INT_MIN) {
		    int id1 = rec, id2 = rec;
		    int aleft = cr->apos, aright = cr->aend;
		    int tlen;
		    int ref = cr->ref_id;

		    // number of segments starting at the same point.
		    int left_cnt = 0;

		    do {
			if (aleft > s->crecs[id2].apos)
			    aleft = s->crecs[id2].apos, left_cnt = 1;
			else if (aleft == s->crecs[id2].apos)
			    left_cnt++;
			if (aright < s->crecs[id2].aend)
			    aright = s->crecs[id2].aend;
			if (s->crecs[id2].mate_line == -1) {
			    s->crecs[id2].mate_line = rec;
			    break;
			}
			if (s->crecs[id2].mate_line <= id2 ||
                            s->crecs[id2].mate_line >= s->hdr->num_records)
			    return -1;
			id2 = s->crecs[id2].mate_line;

			if (s->crecs[id2].ref_id != ref)
			    ref = -1;
		    } while (id2 != id1);

		    if (ref != -1) {
			tlen = aright - aleft + 1;
			id1 = id2 = rec;

			/*
			 * When we have two seqs with identical start and
			 * end coordinates, set +/- tlen based on 1st/last
			 * bit flags instead, as a tie breaker.
			 */
			if (s->crecs[id2].apos == aleft) {
			    if (left_cnt == 1 || 
				(s->crecs[id2].flags & BAM_FREAD1))
				s->crecs[id2].tlen = tlen;
			    else
				s->crecs[id2].tlen = -tlen;
			} else {
			    s->crecs[id2].tlen = -tlen;
			}

			id2 = s->crecs[id2].mate_line;
			while (id2 != id1) {
			    if (s->crecs[id2].apos == aleft) {
				if (left_cnt == 1 || 
				    (s->crecs[id2].flags & BAM_FREAD1))
				    s->crecs[id2].tlen = tlen;
				else
				    s->crecs[id2].tlen = -tlen;
			    } else {
				s->crecs[id2].tlen = -tlen;
			    }
			    id2 = s->crecs[id2].mate_line;
			}
		    } else {
			id1 = id2 = rec;

			s->crecs[id2].tlen = 0;
			id2 = s->crecs[id2].mate_line;
			while (id2 != id1) {
			    s->crecs[id2].tlen = 0;
			    id2 = s->crecs[id2].mate_line;
			}
		    }
		}

		cr->mate_pos = s->crecs[cr->mate_line].apos;
		cr->mate_ref_id = s->crecs[cr->mate_line].ref_id;

		// paired
		cr->flags |= BAM_FPAIRED;

		// set mate unmapped if needed
		if (s->crecs[cr->mate_line].flags & BAM_FUNMAP) {
		    cr->flags |= BAM_FMUNMAP;
		    cr->tlen = 0;
		}
		if (cr->flags & BAM_FUNMAP) {
		    cr->tlen = 0;
		}

		// set mate reversed if needed
		if (s->crecs[cr->mate_line].flags & BAM_FREVERSE)
		    cr->flags |= BAM_FMREVERSE;
	    } else {
		fprintf(stderr, "Mate line out of bounds: %d vs [0, %d]\n",
			cr->mate_line, s->hdr->num_records-1);
	    }

	    /* FIXME: construct read names here too if needed */
	} else {
	    if (cr->mate_flags & CRAM_M_REVERSE) {
		cr->flags |= BAM_FPAIRED | BAM_FMREVERSE;
	    }
	    if (cr->mate_flags & CRAM_M_UNMAP) {
		cr->flags |= BAM_FMUNMAP;
		//cr->mate_ref_id = -1;
	    }
	    if (!(cr->flags & BAM_FPAIRED))
		cr->mate_ref_id = -1;
	}

	if (cr->tlen == INT_MIN)
	    cr->tlen = 0; // Just incase
    }
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl -0x14(%rbp), %eax
andl $0x1c0, %eax            # imm = 0x1C0
cmpl $0x0, %eax
jne 0x2d7f1
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
movq -0x10(%rbp), %rcx
movq (%rcx), %rcx
cmpl 0x10(%rcx), %eax
jge 0x2d7e5
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x18(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movl $0x0, 0x34(%rax)
movq -0x20(%rbp), %rax
movl $0x0, 0x30(%rax)
movq -0x20(%rbp), %rax
movl $0xffffffff, 0x2c(%rax) # imm = 0xFFFFFFFF
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x2d793
movl $0x0, -0x4(%rbp)
jmp 0x2dd73
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
movq -0x10(%rbp), %rcx
movq (%rcx), %rcx
cmpl 0x10(%rcx), %eax
jge 0x2dd6c
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x18(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
cmpl $0x0, 0x28(%rax)
jl 0x2dcf0
movq -0x28(%rbp), %rax
movl 0x28(%rax), %eax
movq -0x10(%rbp), %rcx
movq (%rcx), %rcx
cmpl 0x10(%rcx), %eax
jge 0x2dcc2
movq -0x28(%rbp), %rax
cmpl $0x80000000, 0x34(%rax) # imm = 0x80000000
jne 0x2dbee
movl -0x18(%rbp), %eax
movl %eax, -0x2c(%rbp)
movl -0x18(%rbp), %eax
movl %eax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movl 0x18(%rax), %eax
movl %eax, -0x34(%rbp)
movq -0x28(%rbp), %rax
movl 0x5c(%rax), %eax
movl %eax, -0x38(%rbp)
movq -0x28(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x40(%rbp)
movl $0x0, -0x44(%rbp)
movl -0x34(%rbp), %eax
movq -0x10(%rbp), %rcx
movq 0x28(%rcx), %rcx
movslq -0x30(%rbp), %rdx
imulq $0x70, %rdx, %rdx
addq %rdx, %rcx
cmpl 0x18(%rcx), %eax
jle 0x2d8c6
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x18(%rax), %eax
movl %eax, -0x34(%rbp)
movl $0x1, -0x44(%rbp)
jmp 0x2d8ec
movl -0x34(%rbp), %eax
movq -0x10(%rbp), %rcx
movq 0x28(%rcx), %rcx
movslq -0x30(%rbp), %rdx
imulq $0x70, %rdx, %rdx
addq %rdx, %rcx
cmpl 0x18(%rcx), %eax
jne 0x2d8ea
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x2d8ec
movl -0x38(%rbp), %eax
movq -0x10(%rbp), %rcx
movq 0x28(%rcx), %rcx
movslq -0x30(%rbp), %rdx
imulq $0x70, %rdx, %rdx
addq %rdx, %rcx
cmpl 0x5c(%rcx), %eax
jge 0x2d920
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x5c(%rax), %eax
movl %eax, -0x38(%rbp)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
cmpl $-0x1, 0x28(%rax)
jne 0x2d957
movl -0x18(%rbp), %ecx
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rdx
imulq $0x70, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x28(%rax)
jmp 0x2d9e9
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x28(%rax), %eax
cmpl -0x30(%rbp), %eax
jle 0x2d994
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x28(%rax), %eax
movq -0x10(%rbp), %rcx
movq (%rcx), %rcx
cmpl 0x10(%rcx), %eax
jl 0x2d9a0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2dd73
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x28(%rax), %eax
movl %eax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
cmpl -0x40(%rbp), %eax
je 0x2d9db
movl $0xffffffff, -0x40(%rbp) # imm = 0xFFFFFFFF
jmp 0x2d9dd
movl -0x30(%rbp), %eax
cmpl -0x2c(%rbp), %eax
jne 0x2d889
cmpl $-0x1, -0x40(%rbp)
je 0x2db71
movl -0x38(%rbp), %eax
subl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
movl -0x18(%rbp), %eax
movl %eax, -0x30(%rbp)
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x18(%rax), %eax
cmpl -0x34(%rbp), %eax
jne 0x2da7f
cmpl $0x1, -0x44(%rbp)
je 0x2da47
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0xc(%rax), %eax
andl $0x40, %eax
cmpl $0x0, %eax
je 0x2da62
movl -0x3c(%rbp), %ecx
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rdx
imulq $0x70, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x34(%rax)
jmp 0x2da7d
xorl %ecx, %ecx
subl -0x3c(%rbp), %ecx
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rdx
imulq $0x70, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x34(%rax)
jmp 0x2da9a
xorl %ecx, %ecx
subl -0x3c(%rbp), %ecx
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rdx
imulq $0x70, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x34(%rax)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x28(%rax), %eax
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %eax
cmpl -0x2c(%rbp), %eax
je 0x2db6f
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x18(%rax), %eax
cmpl -0x34(%rbp), %eax
jne 0x2db36
cmpl $0x1, -0x44(%rbp)
je 0x2dafe
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0xc(%rax), %eax
andl $0x40, %eax
cmpl $0x0, %eax
je 0x2db19
movl -0x3c(%rbp), %ecx
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rdx
imulq $0x70, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x34(%rax)
jmp 0x2db34
xorl %ecx, %ecx
subl -0x3c(%rbp), %ecx
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rdx
imulq $0x70, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x34(%rax)
jmp 0x2db51
xorl %ecx, %ecx
subl -0x3c(%rbp), %ecx
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rdx
imulq $0x70, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x34(%rax)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x28(%rax), %eax
movl %eax, -0x30(%rbp)
jmp 0x2dab3
jmp 0x2dbec
movl -0x18(%rbp), %eax
movl %eax, -0x30(%rbp)
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl $0x0, 0x34(%rax)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x28(%rax), %eax
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %eax
cmpl -0x2c(%rbp), %eax
je 0x2dbea
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl $0x0, 0x34(%rax)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movslq -0x30(%rbp), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x28(%rax), %eax
movl %eax, -0x30(%rbp)
jmp 0x2dbad
jmp 0x2dbec
jmp 0x2dbee
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x28(%rbp), %rcx
movslq 0x28(%rcx), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x18(%rax), %ecx
movq -0x28(%rbp), %rax
movl %ecx, 0x30(%rax)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x28(%rbp), %rcx
movslq 0x28(%rcx), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0x8(%rax), %ecx
movq -0x28(%rbp), %rax
movl %ecx, 0x2c(%rax)
movq -0x28(%rbp), %rax
movl 0xc(%rax), %ecx
orl $0x1, %ecx
movl %ecx, 0xc(%rax)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x28(%rbp), %rcx
movslq 0x28(%rcx), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0xc(%rax), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0x2dc77
movq -0x28(%rbp), %rax
movl 0xc(%rax), %ecx
orl $0x8, %ecx
movl %ecx, 0xc(%rax)
movq -0x28(%rbp), %rax
movl $0x0, 0x34(%rax)
movq -0x28(%rbp), %rax
movl 0xc(%rax), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0x2dc91
movq -0x28(%rbp), %rax
movl $0x0, 0x34(%rax)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x28(%rbp), %rcx
movslq 0x28(%rcx), %rcx
imulq $0x70, %rcx, %rcx
addq %rcx, %rax
movl 0xc(%rax), %eax
andl $0x10, %eax
cmpl $0x0, %eax
je 0x2dcc0
movq -0x28(%rbp), %rax
movl 0xc(%rax), %ecx
orl $0x20, %ecx
movl %ecx, 0xc(%rax)
jmp 0x2dcee
movq 0x5c307(%rip), %rax     # 0x89fd0
movq (%rax), %rdi
movq -0x28(%rbp), %rax
movl 0x28(%rax), %edx
movq -0x10(%rbp), %rax
movq (%rax), %rax
movl 0x10(%rax), %ecx
subl $0x1, %ecx
leaq 0x4e132(%rip), %rsi     # 0x7be19
movb $0x0, %al
callq 0x4830
jmp 0x2dd44
movq -0x28(%rbp), %rax
movl 0x6c(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x2dd0c
movq -0x28(%rbp), %rax
movl 0xc(%rax), %ecx
orl $0x21, %ecx
movl %ecx, 0xc(%rax)
movq -0x28(%rbp), %rax
movl 0x6c(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x2dd28
movq -0x28(%rbp), %rax
movl 0xc(%rax), %ecx
orl $0x8, %ecx
movl %ecx, 0xc(%rax)
movq -0x28(%rbp), %rax
movl 0xc(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x2dd42
movq -0x28(%rbp), %rax
movl $0xffffffff, 0x2c(%rax) # imm = 0xFFFFFFFF
jmp 0x2dd44
movq -0x28(%rbp), %rax
cmpl $0x80000000, 0x34(%rax) # imm = 0x80000000
jne 0x2dd5c
movq -0x28(%rbp), %rax
movl $0x0, 0x34(%rax)
jmp 0x2dd5e
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x2d7f8
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x50, %rsp
popq %rbp
retq
nopl (%rax)