// File: /workspace/github_c_makefile_star2_O2/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 $0x38, %rsp
movl %edx, %ebp
movq %rsi, %r13
movq %rdi, 0x28(%rsp)
movq %rsi, %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x4200
cmpl $-0x1, %eax
je 0x5a2b
movl %eax, %r12d
pushq $0x2
popq %rdx
movl %eax, %edi
xorl %esi, %esi
callq 0x40d0
cmpq $-0x1, %rax
je 0x5a43
movq %rax, %r15
movl %r12d, %edi
xorl %esi, %esi
xorl %edx, %edx
callq 0x40d0
movq %r15, %rdi
callq 0x4160
testq %rax, %rax
je 0x5a58
movq %rax, %r14
movq 0x28(%rsp), %rbx
movq 0x60(%rbx), %rax
movq %rax, 0x18(%rsp)
movl %r12d, %edi
movq %r14, %rsi
movq %r15, %rdx
callq 0x4110
movl %r12d, %edi
callq 0x4100
leaq 0x3c4f(%rip), %rsi      # 0x9229
pushq $0x2
popq %rdi
movq %r13, %rdx
xorl %eax, %eax
callq 0x43f9
cmpl $0x1, %ebp
jne 0x5a6e
leaq 0x3c47(%rip), %rsi      # 0x923e
pushq $0x3
popq %rdi
movq %r13, %rdx
xorl %eax, %eax
callq 0x43f9
movq %r14, %rax
addq $0x9, %rax
movq %rax, 0x30(%rsp)
movq $0x0, 0x8(%rsp)
xorl %ebp, %ebp
movl $0x0, 0x24(%rsp)
movq %rbx, %r13
movq 0x18(%rsp), %rax
cmpq %r15, %rbp
jae 0x5a78
movzbl (%r14,%rbp), %ecx
cmpl $0xa, %ecx
je 0x5643
cmpl $0xd, %ecx
jne 0x5648
incq %rbp
jmp 0x562b
movq %rax, 0x18(%rsp)
cmpl $0x3a, %ecx
jne 0x5b4e
movzbl 0x1(%r14,%rbp), %edi
callq 0x5b6a
movl %eax, %r12d
shlb $0x4, %r12b
movzbl 0x2(%r14,%rbp), %edi
callq 0x5b6a
orb %r12b, %al
movzbl %al, %edx
pushq $0x4
popq %rdi
leaq 0x3c17(%rip), %rsi      # 0x929a
movq %rdx, 0x10(%rsp)
xorl %eax, %eax
callq 0x43f9
movzbl 0x3(%r14,%rbp), %edi
callq 0x5b6a
movl %eax, %r12d
shlb $0x4, %r12b
movzbl 0x4(%r14,%rbp), %edi
callq 0x5b6a
orb %r12b, %al
movzbl %al, %ebx
movzbl 0x5(%r14,%rbp), %edi
callq 0x5b6a
shll $0x8, %ebx
shlb $0x4, %al
movzbl %al, %r12d
orl %ebx, %r12d
movzbl 0x6(%r14,%rbp), %edi
callq 0x5b6a
movzbl %al, %eax
orl %r12d, %eax
movzwl %ax, %r12d
pushq $0x4
popq %rbx
movl %ebx, %edi
leaq 0x3bc4(%rip), %rsi      # 0x92af
movl %r12d, %edx
xorl %eax, %eax
callq 0x43f9
movq 0x8(%rsp), %rax
andq $-0x10000, %rax         # imm = 0xFFFF0000
orq %rax, %r12
movl %ebx, %edi
leaq 0x3bb9(%rip), %rsi      # 0x92c5
movq %r12, 0x8(%rsp)
movq %r12, %rdx
xorl %eax, %eax
callq 0x43f9
movzbl 0x7(%r14,%rbp), %edi
callq 0x5b6a
movl %eax, %r12d
shlb $0x4, %r12b
movzbl 0x8(%r14,%rbp), %edi
callq 0x5b6a
orb %r12b, %al
movzbl %al, %r12d
movl %ebx, %edi
leaq 0x3b92(%rip), %rsi      # 0x92da
movl %r12d, %edx
xorl %eax, %eax
callq 0x43f9
cmpb $0x5, %r12b
ja 0x5af5
leaq 0x38a1(%rip), %rcx      # 0x9004
movslq (%rcx,%r12,4), %rax
addq %rcx, %rax
movq 0x18(%rsp), %r12
jmpq *%rax
addq $0x9, %rbp
movq 0x8(%rsp), %rax
movq 0x10(%rsp), %rcx
leaq (%rax,%rcx), %rbx
movq %rbx, %rdx
subq 0x68(%r13), %rdx
cmpq %r12, %rdx
jbe 0x58c1
testq %r12, %r12
cmoveq %r15, %r12
addq %r12, %r12
movq 0x58(%r13), %rdi
movq %r12, %rsi
callq 0x41a0
movq %rax, 0x58(%r13)
jmp 0x5783
movq 0x10(%rsp), %rax
addl %eax, %eax
movq %rax, 0x10(%rsp)
movq 0x30(%rsp), %r12
pushq $-0x9
popq %rbx
movq 0x10(%rsp), %rax
addl %ebx, %eax
cmpl $-0x9, %eax
je 0x5813
cmpl $-0x9, %ebx
jne 0x57e8
movzbl (%r12,%rbp), %edi
callq 0x5b6a
movzbl %al, %eax
movq %rax, 0x8(%rsp)
jmp 0x580b
movq 0x8(%rsp), %r13
shlq $0x4, %r13
movzbl (%r12,%rbp), %edi
callq 0x5b6a
movzbl %al, %eax
orq %rax, %r13
movq %r13, 0x8(%rsp)
movq 0x28(%rsp), %r13
decq %rbx
incq %r12
jmp 0x57c3
movq 0x8(%rsp), %rcx
shlq $0x10, %rcx
movq %rcx, %rax
movq %rcx, 0x8(%rsp)
andl $0xffc00000, %eax       # imm = 0xFFC00000
subq %rbx, %rbp
cmpl $0x0, 0x24(%rsp)
je 0x5a1d
cmpq 0x68(%r13), %rax
movq 0x18(%rsp), %rax
jne 0x5b18
pushq $0x1
popq %rcx
movl %ecx, 0x24(%rsp)
jmp 0x59b7
movq 0x10(%rsp), %rax
addl %eax, %eax
movq %rax, 0x10(%rsp)
movq 0x30(%rsp), %r12
pushq $-0x9
popq %rbx
movq 0x10(%rsp), %rax
addl %ebx, %eax
cmpl $-0x9, %eax
je 0x58b6
cmpl $-0x9, %ebx
jne 0x588b
movzbl (%r12,%rbp), %edi
callq 0x5b6a
movzbl %al, %eax
movq %rax, 0x8(%rsp)
jmp 0x58ae
movq 0x8(%rsp), %r13
shlq $0x4, %r13
movzbl (%r12,%rbp), %edi
callq 0x5b6a
movzbl %al, %eax
orq %rax, %r13
movq %r13, 0x8(%rsp)
movq 0x28(%rsp), %r13
decq %rbx
incq %r12
jmp 0x5866
shlq $0x4, 0x8(%rsp)
jmp 0x59af
movq %r12, 0x18(%rsp)
cmpq 0x60(%r13), %rdx
jbe 0x58e1
movq %rdx, 0x60(%r13)
pushq $0x3
popq %rdi
leaq 0x3a13(%rip), %rsi      # 0x92ed
xorl %eax, %eax
callq 0x43f9
movq 0x8(%rsp), %rbx
subq $0x1, 0x10(%rsp)
jb 0x5921
movzbl (%r14,%rbp), %edi
callq 0x5b6a
movl %eax, %r12d
shlb $0x4, %r12b
movzbl 0x1(%r14,%rbp), %edi
addq $0x2, %rbp
callq 0x5b6a
orb %r12b, %al
movq 0x58(%r13), %rcx
subq 0x68(%r13), %rcx
movb %al, (%rcx,%rbx)
incq %rbx
jmp 0x58e6
pushq $0x1
popq %rax
movl %eax, 0x24(%rsp)
jmp 0x59b2
movq 0x10(%rsp), %rax
addl %eax, %eax
movq %rax, 0x10(%rsp)
movq 0x30(%rsp), %r13
pushq $-0x9
popq %rbx
xorl %r12d, %r12d
movq 0x10(%rsp), %rax
addl %ebx, %eax
cmpl $-0x9, %eax
je 0x5983
cmpl $-0x9, %ebx
jne 0x5966
movzbl (%r13,%rbp), %edi
callq 0x5b6a
movzbl %al, %r12d
jmp 0x597b
shlq $0x4, %r12
movzbl (%r13,%rbp), %edi
callq 0x5b6a
movzbl %al, %eax
orq %rax, %r12
decq %rbx
incq %r13
jmp 0x5944
movzwl %r12w, %eax
shrq $0xc, %r12
andq $-0x10, %r12
addq %rax, %r12
pushq $0x1
popq %rdi
leaq 0x3966(%rip), %rsi      # 0x9302
movq %r12, %rdx
xorl %eax, %eax
callq 0x43f9
movq 0x28(%rsp), %r13
movq %r12, 0x70(%r13)
subq %rbx, %rbp
movq 0x18(%rsp), %rax
cmpb $0xa, (%r14,%rbp)
leaq 0x1(%rbp), %rbp
jne 0x59b7
jmp 0x562b
movq 0x10(%rsp), %rax
addl %eax, %eax
movq %rax, 0x10(%rsp)
movq 0x30(%rsp), %r13
pushq $-0x9
popq %rbx
xorl %r12d, %r12d
movq 0x10(%rsp), %rax
addl %ebx, %eax
cmpl $-0x9, %eax
je 0x5992
cmpl $-0x9, %ebx
jne 0x5a00
movzbl (%r13,%rbp), %edi
callq 0x5b6a
movzbl %al, %r12d
jmp 0x5a15
shlq $0x4, %r12
movzbl (%r13,%rbp), %edi
callq 0x5b6a
movzbl %al, %eax
orq %rax, %r12
decq %rbx
incq %r13
jmp 0x59de
movq %rax, 0x68(%r13)
movl $0x0, 0x24(%rsp)
jmp 0x59b2
leaq 0x37a1(%rip), %rsi      # 0x91d3
pushq $0x1
popq %rdi
movq %r13, %rdx
xorl %eax, %eax
callq 0x43f9
pushq $0x3d
jmp 0x5a6b
leaq 0x379d(%rip), %rsi      # 0x91e7
pushq $0x1
popq %rdi
xorl %eax, %eax
callq 0x43f9
pushq $0x3e
jmp 0x5a6b
leaq 0x379e(%rip), %rsi      # 0x91fd
pushq $0x1
popq %rdi
xorl %eax, %eax
callq 0x43f9
pushq $0x3f
popq %rbx
jmp 0x5ae4
movq %r14, 0x58(%rbx)
movq %r15, 0x60(%rbx)
jmp 0x5ace
leaq 0x393f(%rip), %rsi      # 0x93be
pushq $0x2
popq %rdi
xorl %eax, %eax
callq 0x43f9
cmpl $0x4, 0x86c0(%rip)      # 0xe150
jl 0x5ac2
leaq 0x36ff(%rip), %rdi      # 0x9198
movl $0x242, %esi            # imm = 0x242
movl $0x1ff, %edx            # imm = 0x1FF
xorl %eax, %eax
callq 0x4200
movl %eax, %ebp
movq 0x58(%r13), %rsi
movq 0x60(%r13), %rdx
movl %eax, %edi
callq 0x4090
movl %ebp, %edi
callq 0x4100
movq %r14, %rdi
callq 0x4030
movq 0x60(%r13), %r15
leaq 0x3909(%rip), %rsi      # 0x93de
xorl %ebx, %ebx
pushq $0x2
popq %rdi
movq %r15, %rdx
xorl %eax, %eax
callq 0x43f9
movl %ebx, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r14, %rdi
callq 0x4030
leaq 0x388c(%rip), %rsi      # 0x9390
pushq $0x1
popq %rdi
pushq $0x37
popq %rbx
movl %ebx, %edx
movl %r12d, %ecx
xorl %eax, %eax
callq 0x43f9
jmp 0x5ae4
leaq 0x37fb(%rip), %rsi      # 0x931a
pushq $0x1
popq %r14
movl %r14d, %edi
xorl %eax, %eax
callq 0x43f9
movq 0x68(%r13), %rdx
leaq 0x381f(%rip), %rsi      # 0x9357
movl %r14d, %edi
movq 0x8(%rsp), %rcx
xorl %eax, %eax
callq 0x43f9
pushq $0x45
jmp 0x5a6b
leaq 0x3711(%rip), %rsi      # 0x9266
pushq $0x1
popq %rbx
movl %ebx, %edi
movl %ecx, %edx
xorl %eax, %eax
callq 0x43f9
movl %ebx, %edi
callq 0x4240