// File: /workspace/github_c_makefile_star2_O3/bokunimowakaru[P]petit15term/lpc21isp/lpc21isp.c
// Function: LoadFile
static int LoadFile(ISP_ENVIRONMENT *IspEnvironment, const char *filename, int FileFormat)
{
    int            fd;
    int            i;
    int            BinaryOffsetDefined;
    unsigned long  Pos;
    unsigned long  FileLength;
    BINARY        *FileContent;              /**< Used to store the content of a hex */
                                             /*   file before converting to binary.  */
    unsigned long  BinaryMemSize;

    fd = open(filename, O_RDONLY | O_BINARY);
    if (fd == -1)
    {
        DebugPrintf(1, "Can't open file %s\n", filename);
        return ERR_FILE_OPEN_HEX;
    }

    FileLength = lseek(fd, 0L, 2);      // Get file size

    if (FileLength == (size_t)-1)
    {
        DebugPrintf(1, "\nFileLength = -1 !?!\n");
        return ERR_FILE_SIZE_HEX;
    }

    lseek(fd, 0L, 0);

    // Just read the entire file into memory to parse.
    FileContent = (BINARY*) malloc(FileLength);

    if( FileContent == 0)
    {
        DebugPrintf( 1, "\nCouldn't allocate enough memory for file.\n");
        return ERR_FILE_ALLOC_HEX;
    }

    BinaryOffsetDefined = 0;

    BinaryMemSize = IspEnvironment->BinaryLength;

    read(fd, FileContent, FileLength);

    close(fd);

    DebugPrintf(2, "File %s:\n\tloaded...\n", filename);

    // Intel-Hex -> Binary Conversion

    if (FileFormat == FORMAT_HEX)
    {
        unsigned char  RecordLength;
        unsigned short RecordAddress;
        unsigned long  RealAddress = 0;
        unsigned char  RecordType;
        unsigned char  Hexvalue;
        unsigned long  StartAddress;

        DebugPrintf(3, "Converting file %s to binary format...\n", filename);

        Pos = 0;
        while (Pos < FileLength)
        {
            if (FileContent[Pos] == '\r')
            {
                Pos++;
                continue;
            }

            if (FileContent[Pos] == '\n')
            {
                Pos++;
                continue;
            }

            if (FileContent[Pos] != ':')
            {
                DebugPrintf(1, "Missing start of record (':') wrong byte %c / %02X\n", FileContent[Pos], FileContent[Pos]);
                exit(1);
            }

            Pos++;

            RecordLength   = Ascii2Hex(FileContent[Pos++]);
            RecordLength <<= 4;
            RecordLength  |= Ascii2Hex(FileContent[Pos++]);

            DebugPrintf(4, "RecordLength = %02X\n", RecordLength);

            RecordAddress   = Ascii2Hex(FileContent[Pos++]);
            RecordAddress <<= 4;
            RecordAddress  |= Ascii2Hex(FileContent[Pos++]);
            RecordAddress <<= 4;
            RecordAddress  |= Ascii2Hex(FileContent[Pos++]);
            RecordAddress <<= 4;
            RecordAddress  |= Ascii2Hex(FileContent[Pos++]);

            DebugPrintf(4, "RecordAddress = %04X\n", RecordAddress);

            RealAddress = RealAddress - (RealAddress & 0xffff) + RecordAddress;

            DebugPrintf(4, "RealAddress = %08lX\n", RealAddress);

            RecordType      = Ascii2Hex(FileContent[Pos++]);
            RecordType    <<= 4;
            RecordType     |= Ascii2Hex(FileContent[Pos++]);

            DebugPrintf(4, "RecordType = %02X\n", RecordType);

            if (RecordType == 0x00)          // 00 - Data record
            {
                /*
                * Binary Offset is defined as soon as first data record read
                */
                BinaryOffsetDefined = 1;
                // Memory for binary file big enough ?
                while (RealAddress + RecordLength - IspEnvironment->BinaryOffset > BinaryMemSize)
                {
                    if(!BinaryMemSize) BinaryMemSize = FileLength * 2;
                    else BinaryMemSize <<= 1;
                    IspEnvironment->BinaryContent = realloc(IspEnvironment->BinaryContent, BinaryMemSize);
                }

                // We need to know, what the highest address is,
                // how many bytes / sectors we must flash
                if (RealAddress + RecordLength - IspEnvironment->BinaryOffset > IspEnvironment->BinaryLength)
                {
                    IspEnvironment->BinaryLength = RealAddress + RecordLength - IspEnvironment->BinaryOffset;
                    DebugPrintf(3, "Image size now: %ld\n", IspEnvironment->BinaryLength);
                }

                for (i = 0; i < RecordLength; i++)
                {
                    Hexvalue        = Ascii2Hex(FileContent[Pos++]);
                    Hexvalue      <<= 4;
                    Hexvalue       |= Ascii2Hex(FileContent[Pos++]);
                    IspEnvironment->BinaryContent[RealAddress + i - IspEnvironment->BinaryOffset] = Hexvalue;
                }
            }
            else if (RecordType == 0x01)     // 01 - End of file record
            {
                break;
            }
            else if (RecordType == 0x02)     // 02 - Extended segment address record
            {
                for (i = 0; i < RecordLength * 2; i++)   // double amount of nibbles
                {
                    RealAddress <<= 4;
                    if (i == 0)
                    {
                        RealAddress  = Ascii2Hex(FileContent[Pos++]);
                    }
                    else
                    {
                        RealAddress |= Ascii2Hex(FileContent[Pos++]);
                    }
                }
                RealAddress <<= 4;
            }
            else if (RecordType == 0x03)     // 03 - Start segment address record
            {
                unsigned long cs,ip;
                StartAddress = 0;
                for (i = 0; i < RecordLength * 2; i++)   // double amount of nibbles
                {
                    StartAddress <<= 4;
                    if (i == 0)
                    {
                        StartAddress  = Ascii2Hex(FileContent[Pos++]);
                    }
                    else
                    {
                        StartAddress |= Ascii2Hex(FileContent[Pos++]);
                    }
                }
                cs = StartAddress >> 16; //high part
                ip = StartAddress & 0xffff; //low part
                StartAddress = cs*16+ip; //segmented 20-bit space
                DebugPrintf(1,"Start Address = 0x%08X\n", StartAddress);
                IspEnvironment->StartAddress = StartAddress;
            }
            else if (RecordType == 0x04)     // 04 - Extended linear address record, used by IAR
            {
                for (i = 0; i < RecordLength * 2; i++)   // double amount of nibbles
                {
                    RealAddress <<= 4;
                    if (i == 0)
                    {
                        RealAddress  = Ascii2Hex(FileContent[Pos++]);
                    }
                    else
                    {
                        RealAddress |= Ascii2Hex(FileContent[Pos++]);
                    }
                }
                RealAddress <<= 16;
                if (!BinaryOffsetDefined)
                {
                    // set startaddress of BinaryContent
                    // use of LPC_FLASHMASK to allow a memory range, not taking the first
                    // [04] record as actual start-address.
                    IspEnvironment->BinaryOffset = RealAddress & LPC_FLASHMASK;
                }
                else
                {
                    if ((RealAddress & LPC_FLASHMASK) != IspEnvironment->BinaryOffset)
                    {
                        DebugPrintf(1, "New Extended Linear Address Record [04] out of memory range\n");
                        DebugPrintf(1, "Current Memory starts at: 0x%08X, new Address is: 0x%08X",
                            IspEnvironment->BinaryOffset, RealAddress);
                        return ERR_MEMORY_RANGE;
                    }
                }
            }
            else if (RecordType == 0x05)     // 05 - Start linear address record
            {
                StartAddress = 0;
                for (i = 0; i < RecordLength * 2; i++)   // double amount of nibbles
                {
                    StartAddress <<= 4;
                    if (i == 0)
                    {
                        StartAddress  = Ascii2Hex(FileContent[Pos++]);
                    }
                    else
                    {
                        StartAddress |= Ascii2Hex(FileContent[Pos++]);
                    }
                }
                DebugPrintf(1,"Start Address = 0x%08X\n", StartAddress);
                IspEnvironment->StartAddress = StartAddress;
            }
            else
            {
                free( FileContent);
                DebugPrintf( 1, "Error %d RecordType %02X not yet implemented\n", ERR_RECORD_TYPE_LOADFILE, RecordType);
                return( ERR_RECORD_TYPE_LOADFILE);
            }

            while (FileContent[Pos++] != 0x0a)      // Search till line end
            {
            }
        }

        DebugPrintf(2, "\tconverted to binary format...\n");

        // When debugging is switched on, output result of conversion to file debugout.bin
        if (debug_level >= 4)
        {
            int fdout;
            fdout = open("debugout.bin", O_RDWR | O_BINARY | O_CREAT | O_TRUNC, 0777);
            write(fdout, IspEnvironment->BinaryContent, IspEnvironment->BinaryLength);
            close(fdout);
        }

        free( FileContent);   // Done with file contents
    }
    else // FORMAT_BINARY
    {
        IspEnvironment->BinaryContent = FileContent;
        IspEnvironment->BinaryLength = FileLength;
    }

    DebugPrintf(2, "\timage size : %ld\n", IspEnvironment->BinaryLength);

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl %edx, %ebp
movq %rsi, %r13
movq %rdi, 0x8(%rsp)
movq %rsi, %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x4200
cmpl $-0x1, %eax
je 0x5a8d
movl %eax, %ebx
movl %eax, %edi
xorl %esi, %esi
movl $0x2, %edx
callq 0x40d0
cmpq $-0x1, %rax
je 0x5aad
movq %rax, %r15
movl %ebx, %edi
xorl %esi, %esi
xorl %edx, %edx
callq 0x40d0
movq %r15, %rdi
callq 0x4160
testq %rax, %rax
je 0x5aca
movq %rax, %r14
movq 0x8(%rsp), %rax
movq 0x60(%rax), %rax
movq %rax, 0x20(%rsp)
movl %ebx, %edi
movq %r14, %rsi
movq %r15, %rdx
callq 0x4110
movl %ebx, %edi
callq 0x4100
leaq 0x3baa(%rip), %rsi      # 0x9229
movl $0x2, %edi
movq %r13, %rdx
xorl %eax, %eax
callq 0x43fd
cmpl $0x1, %ebp
jne 0x5ae7
leaq 0x3ba0(%rip), %rsi      # 0x923e
movl $0x3, %edi
movq %r13, %rdx
xorl %eax, %eax
callq 0x43fd
testq %r15, %r15
je 0x5af6
movl $0x0, 0x14(%rsp)
xorl %ebp, %ebp
xorl %r13d, %r13d
movzbl (%r14,%rbp), %ecx
cmpl $0xa, %ecx
je 0x56d2
cmpl $0xd, %ecx
jne 0x56df
incq %rbp
cmpq %r15, %rbp
jb 0x56c3
jmp 0x5af6
cmpl $0x3a, %ecx
jne 0x5be4
movzbl 0x1(%r14,%rbp), %edi
callq 0x5c03
movl %eax, %ebx
shlb $0x4, %bl
movzbl 0x2(%r14,%rbp), %edi
callq 0x5c03
orb %bl, %al
movzbl %al, %edx
movl $0x4, %edi
leaq 0x3b86(%rip), %rsi      # 0x929a
movl %edx, 0x4(%rsp)
xorl %eax, %eax
callq 0x43fd
movzbl 0x3(%r14,%rbp), %edi
callq 0x5c03
movl %eax, %ebx
shlb $0x4, %bl
movzbl 0x4(%r14,%rbp), %edi
callq 0x5c03
orb %bl, %al
movzbl %al, %ebx
movzbl 0x5(%r14,%rbp), %edi
callq 0x5c03
shll $0x8, %ebx
shlb $0x4, %al
movzbl %al, %r12d
orl %ebx, %r12d
movzbl 0x6(%r14,%rbp), %edi
callq 0x5c03
movzbl %al, %eax
orl %r12d, %eax
movzwl %ax, %ebx
movl $0x4, %edi
leaq 0x3b38(%rip), %rsi      # 0x92af
movl %ebx, %edx
xorl %eax, %eax
callq 0x43fd
andq $-0x10000, %r13         # imm = 0xFFFF0000
orq %r13, %rbx
movl $0x4, %edi
leaq 0x3b2f(%rip), %rsi      # 0x92c5
movq %rbx, 0x18(%rsp)
movq %rbx, %rdx
xorl %eax, %eax
callq 0x43fd
movzbl 0x7(%r14,%rbp), %edi
callq 0x5c03
movl %eax, %ebx
shlb $0x4, %bl
movzbl 0x8(%r14,%rbp), %edi
callq 0x5c03
orb %bl, %al
movzbl %al, %r13d
movl $0x4, %edi
leaq 0x3b08(%rip), %rsi      # 0x92da
movl %r13d, %edx
xorl %eax, %eax
callq 0x43fd
cmpb $0x5, %r13b
ja 0x5b81
addq $0x9, %rbp
leaq 0x3813(%rip), %rcx      # 0x9004
movslq (%rcx,%r13,4), %rax
addq %rcx, %rax
movq 0x18(%rsp), %r13
jmpq *%rax
movq %r13, %rax
movl 0x4(%rsp), %r13d
leaq (%rax,%r13), %r12
movq %r12, %rdx
movq 0x8(%rsp), %rax
subq 0x68(%rax), %rdx
movq 0x20(%rsp), %rbx
cmpq %rbx, %rdx
jbe 0x5854
movq 0x8(%rsp), %rax
movq 0x58(%rax), %rax
testq %rbx, %rbx
cmoveq %r15, %rbx
addq %rbx, %rbx
movq %rax, %rdi
movq %rbx, %rsi
callq 0x41a0
movq 0x8(%rsp), %rdi
movq %rax, 0x58(%rdi)
movq %r12, %rdx
subq 0x68(%rdi), %rdx
cmpq %rbx, %rdx
ja 0x582a
movq %rbx, 0x20(%rsp)
movq 0x8(%rsp), %rax
cmpq 0x60(%rax), %rdx
jbe 0x5880
movq 0x8(%rsp), %rax
movq %rdx, 0x60(%rax)
movl $0x3, %edi
leaq 0x3a74(%rip), %rsi      # 0x92ed
xorl %eax, %eax
callq 0x43fd
movl $0x1, 0x14(%rsp)
cmpl $0x0, 0x4(%rsp)
je 0x5a78
movq 0x18(%rsp), %r12
movzbl (%r14,%rbp), %edi
callq 0x5c03
movl %eax, %ebx
shlb $0x4, %bl
movzbl 0x1(%r14,%rbp), %edi
addq $0x2, %rbp
callq 0x5c03
movq 0x8(%rsp), %rdx
movq 0x58(%rdx), %rcx
subq 0x68(%rdx), %rcx
orb %bl, %al
movb %al, (%rcx,%r12)
incq %r12
decq %r13
jne 0x5898
jmp 0x5a78
movl 0x4(%rsp), %r12d
testl %r12d, %r12d
je 0x5919
addl %r12d, %r12d
negl %r12d
xorl %ebx, %ebx
subl $0x1, %ebx
jae 0x58fd
movzbl (%r14,%rbp), %edi
callq 0x5c03
movzbl %al, %r13d
jmp 0x5911
shlq $0x4, %r13
movzbl (%r14,%rbp), %edi
callq 0x5c03
movzbl %al, %eax
orq %rax, %r13
incq %rbp
cmpl %ebx, %r12d
jne 0x58e8
shlq $0x10, %r13
movl %r13d, %eax
andl $0xffc00000, %eax       # imm = 0xFFC00000
cmpl $0x0, 0x14(%rsp)
je 0x5a2f
movl $0x1, 0x14(%rsp)
movq 0x8(%rsp), %rcx
cmpq 0x68(%rcx), %rax
je 0x5a7d
jmp 0x5bab
movl 0x4(%rsp), %eax
testl %eax, %eax
je 0x5992
addl %eax, %eax
negl %eax
xorl %ebx, %ebx
movl %eax, 0x4(%rsp)
subl $0x1, %ebx
jae 0x5973
movzbl (%r14,%rbp), %edi
callq 0x5c03
movzbl %al, %r13d
jmp 0x5987
shlq $0x4, %r13
movzbl (%r14,%rbp), %edi
callq 0x5c03
movzbl %al, %eax
orq %rax, %r13
incq %rbp
movl 0x4(%rsp), %eax
cmpl %ebx, %eax
jne 0x595e
shlq $0x4, %r13
jmp 0x5a7d
movl 0x4(%rsp), %r12d
testl %r12d, %r12d
je 0x5a42
addl %r12d, %r12d
negl %r12d
xorl %ebx, %ebx
xorl %r13d, %r13d
subl $0x1, %ebx
jae 0x59c9
movzbl (%r14,%rbp), %edi
callq 0x5c03
movzbl %al, %r13d
jmp 0x59dd
shlq $0x4, %r13
movzbl (%r14,%rbp), %edi
callq 0x5c03
movzbl %al, %eax
orq %rax, %r13
incq %rbp
cmpl %ebx, %r12d
jne 0x59b4
jmp 0x5a45
movl 0x4(%rsp), %r12d
testl %r12d, %r12d
je 0x5a56
addl %r12d, %r12d
negl %r12d
xorl %ebx, %ebx
xorl %r13d, %r13d
subl $0x1, %ebx
jae 0x5a11
movzbl (%r14,%rbp), %edi
callq 0x5c03
movzbl %al, %r13d
jmp 0x5a25
shlq $0x4, %r13
movzbl (%r14,%rbp), %edi
callq 0x5c03
movzbl %al, %eax
orq %rax, %r13
incq %rbp
cmpl %ebx, %r12d
jne 0x59fc
jmp 0x5a59
movq 0x8(%rsp), %rcx
movq %rax, 0x68(%rcx)
movl $0x0, 0x14(%rsp)
jmp 0x5a7d
xorl %r13d, %r13d
movzwl %r13w, %eax
shrq $0xc, %r13
andq $-0x10, %r13
addq %rax, %r13
jmp 0x5a59
xorl %r13d, %r13d
movl $0x1, %edi
leaq 0x389d(%rip), %rsi      # 0x9302
movq %r13, %rdx
xorl %eax, %eax
callq 0x43fd
movq 0x8(%rsp), %rax
movq %r13, 0x70(%rax)
movq 0x18(%rsp), %r13
cmpb $0xa, (%r14,%rbp)
leaq 0x1(%rbp), %rbp
jne 0x5a7d
jmp 0x56d5
leaq 0x373f(%rip), %rsi      # 0x91d3
movl $0x1, %edi
movq %r13, %rdx
xorl %eax, %eax
callq 0x43fd
movl $0x3d, %ebx
jmp 0x5b70
leaq 0x3733(%rip), %rsi      # 0x91e7
movl $0x1, %edi
xorl %eax, %eax
callq 0x43fd
movl $0x3e, %ebx
jmp 0x5b70
leaq 0x372c(%rip), %rsi      # 0x91fd
movl $0x1, %edi
xorl %eax, %eax
callq 0x43fd
movl $0x3f, %ebx
jmp 0x5b70
movq 0x8(%rsp), %rax
movq %r14, 0x58(%rax)
movq %r15, 0x60(%rax)
jmp 0x5b58
leaq 0x38c1(%rip), %rsi      # 0x93be
movl $0x2, %edi
xorl %eax, %eax
callq 0x43fd
cmpl $0x4, 0x8640(%rip)      # 0xe150
jl 0x5b47
leaq 0x367f(%rip), %rdi      # 0x9198
movl $0x242, %esi            # imm = 0x242
movl $0x1ff, %edx            # imm = 0x1FF
xorl %eax, %eax
callq 0x4200
movl %eax, %ebx
movq 0x8(%rsp), %rax
movq 0x58(%rax), %rsi
movq 0x60(%rax), %rdx
movl %ebx, %edi
callq 0x4090
movl %ebx, %edi
callq 0x4100
movq %r14, %rdi
callq 0x4030
movq 0x8(%rsp), %rax
movq 0x60(%rax), %r15
leaq 0x387f(%rip), %rsi      # 0x93de
xorl %ebx, %ebx
movl $0x2, %edi
movq %r15, %rdx
xorl %eax, %eax
callq 0x43fd
movl %ebx, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r14, %rdi
callq 0x4030
leaq 0x3800(%rip), %rsi      # 0x9390
movl $0x37, %ebx
movl $0x1, %edi
movl $0x37, %edx
movl %r13d, %ecx
xorl %eax, %eax
callq 0x43fd
jmp 0x5b70
leaq 0x3768(%rip), %rsi      # 0x931a
movl $0x1, %edi
xorl %eax, %eax
callq 0x43fd
movq 0x8(%rsp), %rax
movq 0x68(%rax), %rdx
leaq 0x3789(%rip), %rsi      # 0x9357
movl $0x1, %edi
movq %r13, %rcx
xorl %eax, %eax
callq 0x43fd
movl $0x45, %ebx
jmp 0x5b70
leaq 0x367b(%rip), %rsi      # 0x9266
movl $0x1, %edi
movl %ecx, %edx
xorl %eax, %eax
callq 0x43fd
movl $0x1, %edi
callq 0x4240