// File: DoubleString[P]RtConverter/src/Rtklib/rt17.cpp
// Function: bamboo::DecodeGPSEphemeris(bamboo::raw_t*)
static int DecodeGPSEphemeris(raw_t *Raw)
{
    rt17_t *rt17 = (rt17_t*) Raw->rcv_data;
    unsigned char *p = rt17->PacketBuffer;
    int prn, sat, toc, tow;
    unsigned int Flags, toe;
    double sqrtA;
    eph_t eph={0};

    tracet(3, "RT17: DecodeGPSEphemeris(); Length=%d\n", rt17->PacketLength);

    if (rt17->PacketLength < 182)
    {
        tracet(2, "RT17: RETSVDATA packet length %d < 182 bytes. GPS ephemeris packet discarded.\n", rt17->PacketLength);
        return -1;
    }

    prn = U1(p+5);

    if (!(sat=satno(SYS_GPS, prn)))
    {
        tracet(2, "RT17: GPS ephemeris satellite number error, PRN=%d.\n", prn);
        return -1;
    }
 
    eph.week  = U2(p+6);    /* 006-007: Ephemeris Week number (weeks) */
    eph.iodc  = U2(p+8);    /* 008-009: IODC */ 
    /* Reserved byte */     /* 010-010: RESERVED */
    eph.iode  = U1(p+11);   /* 011-011: IODE */
    tow       = I4(p+12);   /* 012-015: TOW */
    toc       = I4(p+16);   /* 016-019: TOC (seconds) */
    toe       = U4(p+20);   /* 020-023: TOE (seconds) */                                   
    eph.tgd[0]= R8(p+24);   /* 024-031: TGD (seconds) */
    eph.f2    = R8(p+32);   /* 032-029: AF2 (seconds/seconds^2) */
    eph.f1    = R8(p+40);   /* 040-047: AF1 (seconds/seconds) */
    eph.f0    = R8(p+48);   /* 048-055: AF0 (seconds) */
    eph.crs   = R8(p+56);   /* 056-063: CRS (meters) */
    eph.deln  = R8(p+64);   /* 064-071: DELTA N (semi-circles/second) */
    eph.M0    = R8(p+72);   /* 072-079: M SUB 0 (semi-circles) */
    eph.cuc   = R8(p+80);   /* 080-087: CUC (semi-circles) */
    eph.e     = R8(p+88);   /* 088-095: ECCENTRICITY (dimensionless) */
    eph.cus   = R8(p+96);   /* 096-103: CUS (semi-circles) */
    sqrtA     = R8(p+104);  /* 104-111: SQRT A (meters ^ 0.5) */
    eph.cic   = R8(p+112);  /* 112-119: CIC (semi-circles) */
    eph.OMG0  = R8(p+120);  /* 120-127: OMEGA SUB 0 (semi-circles) */
    eph.cis   = R8(p+128);  /* 128-135: CIS (semi-circlces) */
    eph.i0    = R8(p+136);  /* 136-143: I SUB 0 (semi-circles) */
    eph.crc   = R8(p+144);  /* 144-151: CRC (meters) */
    eph.omg   = R8(p+152);  /* 152-159: OMEGA (semi-circles?) */
    eph.OMGd  = R8(p+160);  /* 160-167: OMEGA DOT (semi-circles/second) */
    eph.idot  = R8(p+168);  /* 168-175: I DOT (semi-circles/second) */
    Flags     = U4(p+176);  /* 176-179: FLAGS */
  
    /*
    | Multiply these by PI to make ICD specified semi-circle units into radian
    | units for RTKLIB.
    */
    eph.deln *= SC2RAD;
    eph.i0   *= SC2RAD;
    eph.idot *= SC2RAD;
    eph.M0   *= SC2RAD;
    eph.omg  *= SC2RAD;
    eph.OMG0 *= SC2RAD;
    eph.OMGd *= SC2RAD;

    /*
    | As specifically directed to do so by Reference #1, multiply these by PI.
    | to make semi-circle units into radian units, which is what ICD-GPS-200C
    | calls for and also what RTKLIB needs.
    */
    eph.cic *= SC2RAD;
    eph.cis *= SC2RAD;
    eph.cuc *= SC2RAD;
    eph.cus *= SC2RAD;
 
   /*
    | Select the correct curve fit interval as per ICD-GPS-200 sections
    | 20.3.3.4.3.1 and 20.3.4.4 using IODC, fit flag and Table 20-XII.
    */
    if (Flags & M_BIT10)  /* Subframe 2, word 10, bit 17 (fit flag) */
    {
        if ((eph.iodc >= 240) && (eph.iodc <= 247))
            eph.fit = 8;
        else if (((eph.iodc >= 248) && (eph.iodc <= 255)) || (eph.iodc == 496))
            eph.fit = 14;
        else if ((eph.iodc >= 497) && (eph.iodc <= 503))
            eph.fit = 26;
        else if ((eph.iodc >= 504) && (eph.iodc <= 510))
            eph.fit = 50;
        else if ((eph.iodc == 511) || ((eph.iodc >= 752) && (eph.iodc <= 756)))
            eph.fit = 74;
        else if ((eph.iodc >= 757) && (eph.iodc <= 763))
            eph.fit = 98;
        else if (((eph.iodc >= 764) && (eph.iodc <= 767)) || ((eph.iodc >= 1008) && (eph.iodc <= 1010)))
            eph.fit = 122;
        else if ((eph.iodc >= 1011) && (eph.iodc <= 1020))
            eph.fit = 146;
        else
            eph.fit = 6;
    }
    else
        eph.fit = 4;
 
    eph.flag  = (Flags & M_BIT0);   /* Subframe 1, word 4, bit 1, Data flag for L2 P-code */
    eph.code  = (Flags >> 1) & 3;   /* Subframe 1, word 3, bits 11-12, Codes on L2 channel */
    eph.svh   = (Flags >> 4) & 127; /* Subframe 1, word 3, bits 17-22, SV health from ephemeris */
    eph.sva   = (Flags >> 11) & 15; /* Subframe 1, word 3, bits 13-16, User Range Accuracy index */     

    eph.A     = sqrtA * sqrtA;

    eph.toes  = toe;
    eph.toc   = gpst2time(eph.week, toc);
    eph.toe   = gpst2time(eph.week, toe);
    eph.ttr   = gpst2time(eph.week, tow);

    tracet(3, "RT17: DecodeGPSEphemeris(); SAT=%d, IODC=%d, IODE=%d, WEEK=%d.\n", sat, eph.iodc, eph.iode, eph.week);
    
    if (rt17->Week && (rt17->Week != eph.week))
    {
        tracet(2, "RT17: Currently set or assumed GPS week does not match received ephemeris week.\n");
        tracet(2, "RT17: Set or assumed GPS week: %d  Received ephemeris week: %d\n", rt17->Week, eph.week);
    }

    if (!(rt17->Flags & M_WEEK_OPTION))
    {
        if (!rt17->Week || (rt17->Flags & M_WEEK_TIME) || (eph.week > rt17->Week))
        {
            if (!rt17->Week)
                tracet(2, "RT17: Initial GPS WEEK number unknown; WEEK number %d assumed for now.\n", eph.week);
            else
                tracet(2, "RT17: Changing assumed week number from %d to %d.\n", rt17->Week, eph.week);
            rt17->Flags &= ~M_WEEK_TIME;
            rt17->Flags |= M_WEEK_EPH;
            rt17->Week = eph.week;
        }
    }
 
    if (!strstr(Raw->opt,"-EPHALL"))
    {
        if (eph.iode == Raw->nav.eph[sat-1].iode)
            return 0; /* unchanged */
    }

    eph.sat = sat;
    Raw->nav.eph[sat-1] = eph;
    Raw->ephsat = sat;

    return 2;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x190, %rsp            # imm = 0x190
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq 0x82ba0(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
leaq -0x160(%rbp), %rdi
xorl %esi, %esi
movl $0x120, %edx            # imm = 0x120
callq 0x93d0
movq -0x18(%rbp), %rax
movl 0x28(%rax), %edx
movl $0x3, %edi
leaq 0x5633b(%rip), %rsi     # 0xc014b
movb $0x0, %al
callq 0x95890
movq -0x18(%rbp), %rax
cmpl $0xb6, 0x28(%rax)
jae 0x69e4a
movq -0x18(%rbp), %rax
movl 0x28(%rax), %edx
movl $0x2, %edi
leaq 0x5633b(%rip), %rsi     # 0xc0172
movb $0x0, %al
callq 0x95890
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x6a633
movq -0x20(%rbp), %rax
movzbl 0x5(%rax), %eax
movl %eax, -0x24(%rbp)
movl -0x24(%rbp), %esi
movl $0x1, %edi
callq 0x8b1b0
movl %eax, -0x28(%rbp)
cmpl $0x0, %eax
jne 0x69e8c
movl -0x24(%rbp), %edx
movl $0x2, %edi
leaq 0x56348(%rip), %rsi     # 0xc01c1
movb $0x0, %al
callq 0x95890
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x6a633
movq -0x20(%rbp), %rdi
addq $0x6, %rdi
callq 0x6a8e0
movzwl %ax, %eax
movl %eax, -0x14c(%rbp)
movq -0x20(%rbp), %rdi
addq $0x8, %rdi
callq 0x6a8e0
movzwl %ax, %eax
movl %eax, -0x158(%rbp)
movq -0x20(%rbp), %rax
movzbl 0xb(%rax), %eax
movl %eax, -0x15c(%rbp)
movq -0x20(%rbp), %rdi
addq $0xc, %rdi
callq 0x690d0
movl %eax, -0x30(%rbp)
movq -0x20(%rbp), %rdi
addq $0x10, %rdi
callq 0x690d0
movl %eax, -0x2c(%rbp)
movq -0x20(%rbp), %rdi
addq $0x14, %rdi
callq 0x691a0
movl %eax, -0x38(%rbp)
movq -0x20(%rbp), %rdi
addq $0x18, %rdi
callq 0x69120
movsd %xmm0, -0x70(%rbp)
movq -0x20(%rbp), %rdi
addq $0x20, %rdi
callq 0x69120
movsd %xmm0, -0x78(%rbp)
movq -0x20(%rbp), %rdi
addq $0x28, %rdi
callq 0x69120
movsd %xmm0, -0x80(%rbp)
movq -0x20(%rbp), %rdi
addq $0x30, %rdi
callq 0x69120
movsd %xmm0, -0x88(%rbp)
movq -0x20(%rbp), %rdi
addq $0x38, %rdi
callq 0x69120
movsd %xmm0, -0xc0(%rbp)
movq -0x20(%rbp), %rdi
addq $0x40, %rdi
callq 0x69120
movsd %xmm0, -0xe0(%rbp)
movq -0x20(%rbp), %rdi
addq $0x48, %rdi
callq 0x69120
movsd %xmm0, -0xe8(%rbp)
movq -0x20(%rbp), %rdi
addq $0x50, %rdi
callq 0x69120
movsd %xmm0, -0xb8(%rbp)
movq -0x20(%rbp), %rdi
addq $0x58, %rdi
callq 0x69120
movsd %xmm0, -0x108(%rbp)
movq -0x20(%rbp), %rdi
addq $0x60, %rdi
callq 0x69120
movsd %xmm0, -0xb0(%rbp)
movq -0x20(%rbp), %rdi
addq $0x68, %rdi
callq 0x69120
movsd %xmm0, -0x40(%rbp)
movq -0x20(%rbp), %rdi
addq $0x70, %rdi
callq 0x69120
movsd %xmm0, -0xa8(%rbp)
movq -0x20(%rbp), %rdi
addq $0x78, %rdi
callq 0x69120
movsd %xmm0, -0xf8(%rbp)
movq -0x20(%rbp), %rdi
addq $0x80, %rdi
callq 0x69120
movsd %xmm0, -0xa0(%rbp)
movq -0x20(%rbp), %rdi
addq $0x88, %rdi
callq 0x69120
movsd %xmm0, -0x100(%rbp)
movq -0x20(%rbp), %rdi
addq $0x90, %rdi
callq 0x69120
movsd %xmm0, -0xc8(%rbp)
movq -0x20(%rbp), %rdi
addq $0x98, %rdi
callq 0x69120
movsd %xmm0, -0xf0(%rbp)
movq -0x20(%rbp), %rdi
addq $0xa0, %rdi
callq 0x69120
movsd %xmm0, -0xd8(%rbp)
movq -0x20(%rbp), %rdi
addq $0xa8, %rdi
callq 0x69120
movsd %xmm0, -0xd0(%rbp)
movq -0x20(%rbp), %rdi
addq $0xb0, %rdi
callq 0x691a0
movl %eax, -0x34(%rbp)
movsd 0x53cb2(%rip), %xmm0    # 0xbdd58
mulsd -0xe0(%rbp), %xmm0
movsd %xmm0, -0xe0(%rbp)
movsd 0x53c9a(%rip), %xmm0    # 0xbdd58
mulsd -0x100(%rbp), %xmm0
movsd %xmm0, -0x100(%rbp)
movsd 0x53c82(%rip), %xmm0    # 0xbdd58
mulsd -0xd0(%rbp), %xmm0
movsd %xmm0, -0xd0(%rbp)
movsd 0x53c6a(%rip), %xmm0    # 0xbdd58
mulsd -0xe8(%rbp), %xmm0
movsd %xmm0, -0xe8(%rbp)
movsd 0x53c52(%rip), %xmm0    # 0xbdd58
mulsd -0xf0(%rbp), %xmm0
movsd %xmm0, -0xf0(%rbp)
movsd 0x53c3a(%rip), %xmm0    # 0xbdd58
mulsd -0xf8(%rbp), %xmm0
movsd %xmm0, -0xf8(%rbp)
movsd 0x53c22(%rip), %xmm0    # 0xbdd58
mulsd -0xd8(%rbp), %xmm0
movsd %xmm0, -0xd8(%rbp)
movsd 0x53c0a(%rip), %xmm0    # 0xbdd58
mulsd -0xa8(%rbp), %xmm0
movsd %xmm0, -0xa8(%rbp)
movsd 0x53bf2(%rip), %xmm0    # 0xbdd58
mulsd -0xa0(%rbp), %xmm0
movsd %xmm0, -0xa0(%rbp)
movsd 0x53bda(%rip), %xmm0    # 0xbdd58
mulsd -0xb8(%rbp), %xmm0
movsd %xmm0, -0xb8(%rbp)
movsd 0x53bc2(%rip), %xmm0    # 0xbdd58
mulsd -0xb0(%rbp), %xmm0
movsd %xmm0, -0xb0(%rbp)
movl -0x34(%rbp), %eax
andl $0x400, %eax            # imm = 0x400
cmpl $0x0, %eax
je 0x6a369
cmpl $0xf0, -0x158(%rbp)
jl 0x6a1e4
cmpl $0xf7, -0x158(%rbp)
jg 0x6a1e4
movsd 0x52da1(%rip), %xmm0    # 0xbcf78
movsd %xmm0, -0x90(%rbp)
jmp 0x6a367
cmpl $0xf8, -0x158(%rbp)
jl 0x6a1fc
cmpl $0xff, -0x158(%rbp)
jle 0x6a208
cmpl $0x1f0, -0x158(%rbp)    # imm = 0x1F0
jne 0x6a21d
movsd 0x52cd8(%rip), %xmm0    # 0xbcee8
movsd %xmm0, -0x90(%rbp)
jmp 0x6a365
cmpl $0x1f1, -0x158(%rbp)    # imm = 0x1F1
jl 0x6a24a
cmpl $0x1f7, -0x158(%rbp)    # imm = 0x1F7
jg 0x6a24a
movsd 0x55343(%rip), %xmm0    # 0xbf580
movsd %xmm0, -0x90(%rbp)
jmp 0x6a363
cmpl $0x1f8, -0x158(%rbp)    # imm = 0x1F8
jl 0x6a277
cmpl $0x1fe, -0x158(%rbp)    # imm = 0x1FE
jg 0x6a277
movsd 0x5530e(%rip), %xmm0    # 0xbf578
movsd %xmm0, -0x90(%rbp)
jmp 0x6a361
cmpl $0x1ff, -0x158(%rbp)    # imm = 0x1FF
je 0x6a29b
cmpl $0x2f0, -0x158(%rbp)    # imm = 0x2F0
jl 0x6a2b0
cmpl $0x2f4, -0x158(%rbp)    # imm = 0x2F4
jg 0x6a2b0
movsd 0x552cd(%rip), %xmm0    # 0xbf570
movsd %xmm0, -0x90(%rbp)
jmp 0x6a35f
cmpl $0x2f5, -0x158(%rbp)    # imm = 0x2F5
jl 0x6a2dd
cmpl $0x2fb, -0x158(%rbp)    # imm = 0x2FB
jg 0x6a2dd
movsd 0x55298(%rip), %xmm0    # 0xbf568
movsd %xmm0, -0x90(%rbp)
jmp 0x6a35d
cmpl $0x2fc, -0x158(%rbp)    # imm = 0x2FC
jl 0x6a2f5
cmpl $0x2ff, -0x158(%rbp)    # imm = 0x2FF
jle 0x6a30d
cmpl $0x3f0, -0x158(%rbp)    # imm = 0x3F0
jl 0x6a31f
cmpl $0x3f2, -0x158(%rbp)    # imm = 0x3F2
jg 0x6a31f
movsd 0x5524b(%rip), %xmm0    # 0xbf560
movsd %xmm0, -0x90(%rbp)
jmp 0x6a35b
cmpl $0x3f3, -0x158(%rbp)    # imm = 0x3F3
jl 0x6a349
cmpl $0x3fc, -0x158(%rbp)    # imm = 0x3FC
jg 0x6a349
movsd 0x55219(%rip), %xmm0    # 0xbf558
movsd %xmm0, -0x90(%rbp)
jmp 0x6a359
movsd 0x52c1f(%rip), %xmm0    # 0xbcf70
movsd %xmm0, -0x90(%rbp)
jmp 0x6a35b
jmp 0x6a35d
jmp 0x6a35f
jmp 0x6a361
jmp 0x6a363
jmp 0x6a365
jmp 0x6a367
jmp 0x6a379
movsd 0x52a7f(%rip), %xmm0    # 0xbcdf0
movsd %xmm0, -0x90(%rbp)
movl -0x34(%rbp), %eax
andl $0x1, %eax
movl %eax, -0x144(%rbp)
movl -0x34(%rbp), %eax
shrl %eax
andl $0x3, %eax
movl %eax, -0x148(%rbp)
movl -0x34(%rbp), %eax
shrl $0x4, %eax
andl $0x7f, %eax
movl %eax, -0x150(%rbp)
movl -0x34(%rbp), %eax
shrl $0xb, %eax
andl $0xf, %eax
movl %eax, -0x154(%rbp)
movsd -0x40(%rbp), %xmm0
mulsd %xmm0, %xmm0
movsd %xmm0, -0x110(%rbp)
movl -0x38(%rbp), %eax
cvtsi2sd %rax, %xmm0
movsd %xmm0, -0x98(%rbp)
movl -0x14c(%rbp), %edi
cvtsi2sdl -0x2c(%rbp), %xmm0
callq 0x8e4a0
movq %rax, -0x170(%rbp)
movsd %xmm0, -0x168(%rbp)
movups -0x170(%rbp), %xmm0
movups %xmm0, -0x130(%rbp)
movl -0x14c(%rbp), %edi
movl -0x38(%rbp), %eax
cvtsi2sd %rax, %xmm0
callq 0x8e4a0
movq %rax, -0x180(%rbp)
movsd %xmm0, -0x178(%rbp)
movq -0x180(%rbp), %rax
movq %rax, -0x140(%rbp)
movq -0x178(%rbp), %rax
movq %rax, -0x138(%rbp)
movl -0x14c(%rbp), %edi
cvtsi2sdl -0x30(%rbp), %xmm0
callq 0x8e4a0
movq %rax, -0x190(%rbp)
movsd %xmm0, -0x188(%rbp)
movq -0x190(%rbp), %rax
movq %rax, -0x120(%rbp)
movq -0x188(%rbp), %rax
movq %rax, -0x118(%rbp)
movl -0x28(%rbp), %edx
movl -0x158(%rbp), %ecx
movl -0x15c(%rbp), %r8d
movl -0x14c(%rbp), %r9d
movl $0x3, %edi
leaq 0x55d5b(%rip), %rsi     # 0xc01f6
movb $0x0, %al
callq 0x95890
movq -0x18(%rbp), %rax
cmpl $0x0, 0x34(%rax)
je 0x6a4ee
movq -0x18(%rbp), %rax
movl 0x34(%rax), %eax
cmpl -0x14c(%rbp), %eax
je 0x6a4ee
movl $0x2, %edi
leaq 0x55d6f(%rip), %rsi     # 0xc0236
movb $0x0, %al
callq 0x95890
movq -0x18(%rbp), %rax
movl 0x34(%rax), %edx
movl -0x14c(%rbp), %ecx
movl $0x2, %edi
leaq 0x55da0(%rip), %rsi     # 0xc0287
movb $0x0, %al
callq 0x95890
movq -0x18(%rbp), %rax
movl 0x18(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x6a597
movq -0x18(%rbp), %rax
cmpl $0x0, 0x34(%rax)
je 0x6a529
movq -0x18(%rbp), %rax
movl 0x18(%rax), %eax
andl $0x4, %eax
cmpl $0x0, %eax
jne 0x6a529
movl -0x14c(%rbp), %eax
movq -0x18(%rbp), %rcx
cmpl 0x34(%rcx), %eax
jle 0x6a595
movq -0x18(%rbp), %rax
cmpl $0x0, 0x34(%rax)
jne 0x6a54e
movl -0x14c(%rbp), %edx
movl $0x2, %edi
leaq 0x55a2d(%rip), %rsi     # 0xbff72
movb $0x0, %al
callq 0x95890
jmp 0x6a56e
movq -0x18(%rbp), %rax
movl 0x34(%rax), %edx
movl -0x14c(%rbp), %ecx
movl $0x2, %edi
leaq 0x55d60(%rip), %rsi     # 0xc02c7
movb $0x0, %al
callq 0x95890
movq -0x18(%rbp), %rax
movl 0x18(%rax), %ecx
andl $-0x5, %ecx
movl %ecx, 0x18(%rax)
movq -0x18(%rbp), %rax
movl 0x18(%rax), %ecx
orl $0x2, %ecx
movl %ecx, 0x18(%rax)
movl -0x14c(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x34(%rax)
jmp 0x6a597
movq -0x10(%rbp), %rdi
addq $0x82a90, %rdi          # imm = 0x82A90
leaq 0x542b6(%rip), %rsi     # 0xbe85f
callq 0x91b0
cmpq $0x0, %rax
jne 0x6a5e8
movl -0x15c(%rbp), %eax
movq -0x10(%rbp), %rcx
movq 0x1d80(%rcx), %rcx
movl -0x28(%rbp), %edx
subl $0x1, %edx
movslq %edx, %rdx
imulq $0x120, %rdx, %rdx      # imm = 0x120
addq %rdx, %rcx
cmpl 0x4(%rcx), %eax
jne 0x6a5e6
movl $0x0, -0x4(%rbp)
jmp 0x6a633
jmp 0x6a5e8
movl -0x28(%rbp), %eax
movl %eax, -0x160(%rbp)
movq -0x10(%rbp), %rax
movq 0x1d80(%rax), %rdi
movl -0x28(%rbp), %eax
subl $0x1, %eax
cltq
imulq $0x120, %rax, %rax      # imm = 0x120
addq %rax, %rdi
leaq -0x160(%rbp), %rsi
movl $0x120, %edx            # imm = 0x120
callq 0x9610
movl -0x28(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x70e40(%rax)
movl $0x2, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x190, %rsp            # imm = 0x190
popq %rbp
retq
nop