LCC Compiler

LCC is a retargetable C compiler. The target of a C compiler is the processor for which it generates assembly instructions. The lcc compiler has also been ported to the mMIPS.

Compiling to an executable

A source code file (e.g. file.c) is compiled into an binary file (e.g. mips_mem.bin) using the following command:

lcc file.c -o mips_mem.bin

Alternatively, you can compile a (set of) source code file(s) first to a (set of) object file(s) and then link these object file(s) to a binary. In that situation, you should follow the following procedure.

A source code file (e.g. file.c) is compiled into an object file (e.g. file.o) using the following command:

lcc -c file.c -o file.o
The -c option tells the compiler that it should compile the source code file (e.g. file.c). After the -o option we put the name of the output file produced by the compiler (e.g. file.o).

After all source code files have been compiled, we can link them into one binary. Using the following command, we link the object files file1.o and file2.o into the binary 'mips_mem.bin' using the following command.

lcc file1.o file2.o -o mips_mem.bin
All object files (possibly just one) that are needed to produce the binary must be specified in this command.

Disassembling an executable

You can use the disas tool to get a disassemblance (assembler listing) of the binary. For a file mips_mem.bin, this is done using the following command: disas mips_mem.bin

Memory layout

The LCC compiler uses the following memory map:
Address Length Field
0x000000 - 0x027FFF 160KB ROM
0x400000 - 0x7FFFFF 4MB RAM
0x800000 - 0xBFFFFF 4MB Display
0xC00000 - 0xC00003 1 Byte RS232

Note that the compiler has actually no knowledge of the display and RS232 port. You should address these directly in the C code of you programming. An example of how the RS232 portcan be used is shown below. This program echos all data that is send to the RS232 port

void main(void)
{
    int *rs232_port = (int*)0xC00000;
    int a;

    while (1)
    {
        a = rs232_port[0]; /* read from port */
        rs232_port[0] = a; /* write to port */
    }
}

Besides the RS232 port, the mMIPS provides access to a display consisting of 640x480 pixels. Each pixel is accessible via its own address. The left-top pixel is assigned the address 0x800000. Its value (color) can be changed with a store word (sw) instruction to this address. The stored value should be equal to the desired color for the pixel. The three LSB bytes (bits 0 through 23) deterime respectively the Red (bits 0 through 7), Green (bits 8 through 15), Blue (bits 16 through 23) component.

The pixels are accessed in a line-by-line fashion. The lowest 10-bits of the address (bits 0 through 9) are used to index the line and the next 10-bits (bits 10 through 19) are used to index the column. Hence, the n-th pixel at the m-th line can be found at the address 0x800000 | n << 12 | m << 2.

The following code colors the screen green with a black line at the middle of the screen from the top till the center:

void main(void)
{
    int *display = (int*)(0x800000);
    int n, m;

    for (m = 0; m < 480; m++)
    {
        for (n = 0; n < 640; n++)
        {
            display[(n << 10) + m] = 0x00ff00;
        }
    }
    
    for (n = 0; n < 240; n++)
    {
        display[(320 << 10) + n] = 0x000000;
    }
}
Addresses in the display are computed by multiplying the index in the array (value between braces) with the size of the data type (e.g. is 4 bytes).

Note that the display supports only store-word instructions (sw). It is not possible to read the values currently shown on the display.