// File: /workspace/github_c_makefile_star2_O1/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, %r12
movq %rsi, %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x4200
cmpl $-0x1, %eax
je 0x5af5
movl %eax, %ebx
movl %eax, %edi
xorl %esi, %esi
movl $0x2, %edx
callq 0x40d0
cmpq $-0x1, %rax
je 0x5b15
movq %rax, %r15
movl %ebx, %edi
xorl %esi, %esi
xorl %edx, %edx
callq 0x40d0
movq %r15, %rdi
callq 0x4160
testq %rax, %rax
je 0x5b32
movq %rax, %r14
movq 0x60(%r12), %rax
movq %rax, 0x18(%rsp)
movl %ebx, %edi
movq %r14, %rsi
movq %r15, %rdx
callq 0x4110
movl %ebx, %edi
callq 0x4100
leaq 0x3b4c(%rip), %rsi      # 0x9229
movl $0x2, %edi
movq %r13, %rdx
xorl %eax, %eax
callq 0x43fd
cmpl $0x1, %ebp
jne 0x5b4f
leaq 0x3b42(%rip), %rsi      # 0x923e
movl $0x3, %edi
movq %r13, %rdx
xorl %eax, %eax
callq 0x43fd
testq %r15, %r15
je 0x5b5b
movl $0x0, 0x4(%rsp)
xorl %r13d, %r13d
xorl %ebp, %ebp
movzbl (%r14,%r13), %ecx
cmpl $0xa, %ecx
je 0x5730
cmpl $0xd, %ecx
jne 0x573d
incq %r13
cmpq %r15, %r13
jb 0x5721
jmp 0x5b5b
movq %rbp, 0x8(%rsp)
cmpl $0x3a, %ecx
jne 0x5c4b
movzbl 0x1(%r14,%r13), %edi
callq 0x5c6a
movl %eax, %ebx
shlb $0x4, %bl
movzbl 0x2(%r14,%r13), %edi
callq 0x5c6a
orb %bl, %al
movzbl %al, %edx
movl $0x4, %edi
leaq 0x3b23(%rip), %rsi      # 0x929a
movl %edx, (%rsp)
xorl %eax, %eax
callq 0x43fd
movzbl 0x3(%r14,%r13), %edi
callq 0x5c6a
movl %eax, %ebx
shlb $0x4, %bl
movzbl 0x4(%r14,%r13), %edi
callq 0x5c6a
orb %bl, %al
movzbl %al, %ebx
movzbl 0x5(%r14,%r13), %edi
callq 0x5c6a
shll $0x8, %ebx
shlb $0x4, %al
movzbl %al, %ebp
orl %ebx, %ebp
movzbl 0x6(%r14,%r13), %edi
callq 0x5c6a
movzbl %al, %eax
orl %ebp, %eax
movzwl %ax, %ebx
movl $0x4, %edi
leaq 0x3ad9(%rip), %rsi      # 0x92af
movl %ebx, %edx
xorl %eax, %eax
callq 0x43fd
movq 0x8(%rsp), %rax
andq $-0x10000, %rax         # imm = 0xFFFF0000
orq %rax, %rbx
movl $0x4, %edi
leaq 0x3acc(%rip), %rsi      # 0x92c5
movq %rbx, 0x8(%rsp)
movq %rbx, %rdx
xorl %eax, %eax
callq 0x43fd
movzbl 0x7(%r14,%r13), %edi
callq 0x5c6a
movl %eax, %ebx
shlb $0x4, %bl
movzbl 0x8(%r14,%r13), %edi
callq 0x5c6a
orb %bl, %al
movzbl %al, %ebp
movl $0x4, %edi
leaq 0x3aa6(%rip), %rsi      # 0x92da
movl %ebp, %edx
xorl %eax, %eax
callq 0x43fd
cmpb $0x5, %bpl
ja 0x5be4
addq $0x9, %r13
leaq 0x37b2(%rip), %rcx      # 0x9004
movslq (%rcx,%rbp,4), %rax
addq %rcx, %rax
movq 0x8(%rsp), %rbp
movq %r12, 0x10(%rsp)
jmpq *%rax
movl (%rsp), %ecx
movq %rcx, 0x20(%rsp)
addq %rcx, %rbp
movq %rbp, %rdx
subq 0x68(%r12), %rdx
movq 0x18(%rsp), %rbx
cmpq %rbx, %rdx
jbe 0x597b
testq %rbx, %rbx
cmoveq %r15, %rbx
addq %rbx, %rbx
movq 0x58(%r12), %rdi
movq %rbx, %rsi
callq 0x41a0
movq %rax, 0x58(%r12)
movq %rbp, %rdx
subq 0x68(%r12), %rdx
jmp 0x587d
movl (%rsp), %r12d
testl %r12d, %r12d
je 0x58f3
addl %r12d, %r12d
cmpl $0x1, %r12d
adcl $0x0, %r12d
xorl %ebx, %ebx
testl %ebx, %ebx
je 0x58dc
shlq $0x4, %rbp
movzbl (%r14,%r13), %edi
callq 0x5c6a
movzbl %al, %eax
orq %rax, %rbp
jmp 0x58e9
movzbl (%r14,%r13), %edi
callq 0x5c6a
movzbl %al, %ebp
incq %r13
incl %ebx
cmpl %ebx, %r12d
jne 0x58c2
shlq $0x10, %rbp
movl %ebp, %eax
andl $0xffc00000, %eax       # imm = 0xFFC00000
cmpl $0x0, 0x4(%rsp)
je 0x5a98
movl $0x1, 0x4(%rsp)
movq 0x10(%rsp), %r12
cmpq 0x68(%r12), %rax
je 0x5ae5
jmp 0x5c10
movl (%rsp), %r12d
testl %r12d, %r12d
je 0x596d
addl %r12d, %r12d
cmpl $0x1, %r12d
adcl $0x0, %r12d
xorl %ebx, %ebx
testl %ebx, %ebx
je 0x5956
shlq $0x4, %rbp
movzbl (%r14,%r13), %edi
callq 0x5c6a
movzbl %al, %eax
orq %rax, %rbp
jmp 0x5963
movzbl (%r14,%r13), %edi
callq 0x5c6a
movzbl %al, %ebp
incq %r13
incl %ebx
cmpl %ebx, %r12d
jne 0x593c
shlq $0x4, %rbp
movq 0x10(%rsp), %r12
jmp 0x5ae5
movq %rbx, 0x18(%rsp)
cmpq 0x60(%r12), %rdx
jbe 0x599f
movq %rdx, 0x60(%r12)
movl $0x3, %edi
leaq 0x3955(%rip), %rsi      # 0x92ed
xorl %eax, %eax
callq 0x43fd
movl $0x1, 0x4(%rsp)
cmpl $0x0, (%rsp)
movq 0x20(%rsp), %rbp
je 0x5ae0
movq 0x8(%rsp), %r12
movzbl (%r14,%r13), %edi
callq 0x5c6a
movl %eax, %ebx
shlb $0x4, %bl
movzbl 0x1(%r14,%r13), %edi
addq $0x2, %r13
callq 0x5c6a
movq 0x10(%rsp), %rdx
movq 0x58(%rdx), %rcx
subq 0x68(%rdx), %rcx
orb %bl, %al
movb %al, (%rcx,%r12)
incq %r12
decq %rbp
jne 0x59bb
movq 0x10(%rsp), %r12
jmp 0x5ae0
movl (%rsp), %r12d
testl %r12d, %r12d
je 0x5aac
addl %r12d, %r12d
cmpl $0x1, %r12d
adcl $0x0, %r12d
xorl %ebx, %ebx
xorl %ebp, %ebp
testl %ebx, %ebx
je 0x5a34
shlq $0x4, %rbp
movzbl (%r14,%r13), %edi
callq 0x5c6a
movzbl %al, %eax
orq %rax, %rbp
jmp 0x5a41
movzbl (%r14,%r13), %edi
callq 0x5c6a
movzbl %al, %ebp
incq %r13
incl %ebx
cmpl %ebx, %r12d
jne 0x5a1a
jmp 0x5aae
movl (%rsp), %r12d
testl %r12d, %r12d
je 0x5abe
addl %r12d, %r12d
cmpl $0x1, %r12d
adcl $0x0, %r12d
xorl %ebx, %ebx
xorl %ebp, %ebp
testl %ebx, %ebx
je 0x5a7f
shlq $0x4, %rbp
movzbl (%r14,%r13), %edi
callq 0x5c6a
movzbl %al, %eax
orq %rax, %rbp
jmp 0x5a8c
movzbl (%r14,%r13), %edi
callq 0x5c6a
movzbl %al, %ebp
incq %r13
incl %ebx
cmpl %ebx, %r12d
jne 0x5a65
jmp 0x5ac0
movq 0x10(%rsp), %r12
movq %rax, 0x68(%r12)
movl $0x0, 0x4(%rsp)
jmp 0x5ae5
xorl %ebp, %ebp
movzwl %bp, %eax
shrq $0xc, %rbp
andq $-0x10, %rbp
addq %rax, %rbp
jmp 0x5ac0
xorl %ebp, %ebp
movl $0x1, %edi
leaq 0x3836(%rip), %rsi      # 0x9302
movq %rbp, %rdx
xorl %eax, %eax
callq 0x43fd
movq 0x10(%rsp), %r12
movq %rbp, 0x70(%r12)
movq 0x8(%rsp), %rbp
cmpb $0xa, (%r14,%r13)
leaq 0x1(%r13), %r13
jne 0x5ae5
jmp 0x5733
leaq 0x36d7(%rip), %rsi      # 0x91d3
movl $0x1, %edi
movq %r13, %rdx
xorl %eax, %eax
callq 0x43fd
movl $0x3d, %ebx
jmp 0x5bd3
leaq 0x36cb(%rip), %rsi      # 0x91e7
movl $0x1, %edi
xorl %eax, %eax
callq 0x43fd
movl $0x3e, %ebx
jmp 0x5bd3
leaq 0x36c4(%rip), %rsi      # 0x91fd
movl $0x1, %edi
xorl %eax, %eax
callq 0x43fd
movl $0x3f, %ebx
jmp 0x5bd3
movq %r14, 0x58(%r12)
movq %r15, 0x60(%r12)
jmp 0x5bb9
leaq 0x385c(%rip), %rsi      # 0x93be
movl $0x2, %edi
xorl %eax, %eax
callq 0x43fd
cmpl $0x4, 0x85db(%rip)      # 0xe150
jl 0x5ba9
leaq 0x361a(%rip), %rdi      # 0x9198
movl $0x242, %esi            # imm = 0x242
movl $0x1ff, %edx            # imm = 0x1FF
xorl %eax, %eax
callq 0x4200
movl %eax, %ebx
movq 0x58(%r12), %rsi
movq 0x60(%r12), %rdx
movl %eax, %edi
callq 0x4090
movl %ebx, %edi
callq 0x4100
movq %r14, %rdi
callq 0x4030
movb $0x1, %r14b
testb %r14b, %r14b
je 0x5bd3
movq 0x60(%r12), %rdx
leaq 0x3819(%rip), %rsi      # 0x93de
xorl %ebx, %ebx
movl $0x2, %edi
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 0x379d(%rip), %rsi      # 0x9390
xorl %r14d, %r14d
movl $0x37, %ebx
movl $0x1, %edi
movl $0x37, %edx
movl %ebp, %ecx
xorl %eax, %eax
callq 0x43fd
jmp 0x5bb4
leaq 0x3703(%rip), %rsi      # 0x931a
xorl %r14d, %r14d
movl $0x1, %edi
xorl %eax, %eax
callq 0x43fd
movq 0x68(%r12), %rdx
leaq 0x3725(%rip), %rsi      # 0x9357
movl $0x1, %edi
movq %rbp, %rcx
xorl %eax, %eax
callq 0x43fd
movl $0x45, %ebx
jmp 0x5bb4
leaq 0x3614(%rip), %rsi      # 0x9266
movl $0x1, %edi
movl %ecx, %edx
xorl %eax, %eax
callq 0x43fd
movl $0x1, %edi
callq 0x4240