Difference between revisions of "C-compiler use"

From C256 Foenix Wiki
Jump to navigation Jump to search
(The compiler)
Line 42: Line 42:
 
The first line calls the compiler (wdc816cc) the import swith here is the -M switch. This specifies the memory model the compiler is going to use when compiling code. The example here is using the large model. Choosing the right memory model for your code can have a significant impact on the resulting codes execution performance. The 65816 is a 16-bit cpu but can adress up to 16MB of memory using 32 bit pointers in the large model (the bus is actually 24bit). But this take more CPU cycles than using 16bit pointers. 16 bit pointers are however to small to address all memory. So you can only use those if your code or data fits within a single page of memory (64kb). To make things more confusing. We can specify different models for both data and code. WDC provides the following table to choose a model. For more details refer to the chapter on memory models in the compiler manual (816cc.pdf)
 
The first line calls the compiler (wdc816cc) the import swith here is the -M switch. This specifies the memory model the compiler is going to use when compiling code. The example here is using the large model. Choosing the right memory model for your code can have a significant impact on the resulting codes execution performance. The 65816 is a 16-bit cpu but can adress up to 16MB of memory using 32 bit pointers in the large model (the bus is actually 24bit). But this take more CPU cycles than using 16bit pointers. 16 bit pointers are however to small to address all memory. So you can only use those if your code or data fits within a single page of memory (64kb). To make things more confusing. We can specify different models for both data and code. WDC provides the following table to choose a model. For more details refer to the chapter on memory models in the compiler manual (816cc.pdf)
  
<64K Code >64K Code
+
{|
<64K data Small Medium
+
|
>64K data Compact Large
+
|<64K Code
 +
|>64K Code
 +
|-
 +
|<64K data
 +
|Small
 +
|Medium
 +
|-
 +
|>64K data
 +
|Compact  
 +
|Large
 +
|}
  
 
The Second line of the example links to objects the compiler generated into a single hex file that can be uploaded to the foenix. -H specifies the output format. Here it is (I) Intel Hex. Though not required -V make the linker output the locations of functions and data/code segments and symbols. In this output you will notice that the compiler prefixes every function/symbol with a combination of (~) and (_). This is used to signify the memory model used by that part of the code. Unfortunately these prefixes turn up in error messages. So when you see this in an error just ignore them and find the function or such without these prefixes in your code. -T this generates a map file. -P specifies the fill characters for the output hex file. 00 will be fine here. -L is used to specify one or more libraries. Choose the correct libraries depending again on your choosen memory model. The linker manaual documents this. -O for the output hex file name. You can tell the linker to load code and data (initialized and unintialized) to specfic locations. In this example I only specify a location for the Code segment (-C1000 start code at hex 1000). The linker will layout other sections using the code segment as a starting point.  
 
The Second line of the example links to objects the compiler generated into a single hex file that can be uploaded to the foenix. -H specifies the output format. Here it is (I) Intel Hex. Though not required -V make the linker output the locations of functions and data/code segments and symbols. In this output you will notice that the compiler prefixes every function/symbol with a combination of (~) and (_). This is used to signify the memory model used by that part of the code. Unfortunately these prefixes turn up in error messages. So when you see this in an error just ignore them and find the function or such without these prefixes in your code. -T this generates a map file. -P specifies the fill characters for the output hex file. 00 will be fine here. -L is used to specify one or more libraries. Choose the correct libraries depending again on your choosen memory model. The linker manaual documents this. -O for the output hex file name. You can tell the linker to load code and data (initialized and unintialized) to specfic locations. In this example I only specify a location for the Code segment (-C1000 start code at hex 1000). The linker will layout other sections using the code segment as a starting point.  
 
The objects linked together in this example are demo.obj and col.obj. demo.obj is the output from the C-Compiler. Normally this is enough, however with the foenix we are talking a system that (excluding the kernel) does not have a formal operating system. So you need some startup code to actually set some thing up like the stack and interrupt handlers and the proper vectors. You can create the needed assembly code for this yourself. But WDC provides a few default options. C0S.OBJ, C0C.OBJ, C0M.OBJ and C0L.OBJ. Again choose the proper one based on your choise of memory model. The manual actually states that the ASM files of these are included to tweak to desire. This however is not the case. If one is interested, they can be requested by mailing WDC and asking for them. These example startup code objects do not know anything about the foenix kernel and thus assume your program is the only one running. In time proper starup objects and a format for binaries to work along with the foenix kernel should appear, but have not materialized yet. Considering that this is really a plaform to experiment the author feels this is not a significant problem at the moment.
 
The objects linked together in this example are demo.obj and col.obj. demo.obj is the output from the C-Compiler. Normally this is enough, however with the foenix we are talking a system that (excluding the kernel) does not have a formal operating system. So you need some startup code to actually set some thing up like the stack and interrupt handlers and the proper vectors. You can create the needed assembly code for this yourself. But WDC provides a few default options. C0S.OBJ, C0C.OBJ, C0M.OBJ and C0L.OBJ. Again choose the proper one based on your choise of memory model. The manual actually states that the ASM files of these are included to tweak to desire. This however is not the case. If one is interested, they can be requested by mailing WDC and asking for them. These example startup code objects do not know anything about the foenix kernel and thus assume your program is the only one running. In time proper starup objects and a format for binaries to work along with the foenix kernel should appear, but have not materialized yet. Considering that this is really a plaform to experiment the author feels this is not a significant problem at the moment.

Revision as of 14:29, 12 February 2020

C-Compiler pointers

Warning this document is rather a work in progress, take it for what it is... :)

The compiler

Though assembly at the moment seems to be the most popular programming language for the IDE, it is not the only one. Assembly (when done right) will produce the most speedy and compact code. But it is not exactly portable nor does everyone want to learn every seperate cpu its specific opcodes. For those Western Design Center (WDC) provides an C-Compiler. It has a few quircks but if you are familier with C on other platforms most things will seem quite familier to you.

Where to get it
You can download the compiler at https://wdc65xx.com/. I cannot provide a direct link as it requires you to provide an email address. You will be send the download URL in an email. I have not noticed any spam from them so I guess its not a problem. Here you can also download several manuals for thing like the compiler, the linker and the assembler.
Installing
The compiler is a windows program, but runs fine under wine on linux. It is command line based, but the setup is graphical. Just do the usual next next finish steps. It installs to c:\wdc by default and I advise to keep this location. It sets the path variables properly so after installation you can call it from any location. For those installing it under wine run wine installer.exe from your favorite shell or wine installer utility.


Using
For those working on Linux use wineconsole to get a command prompt and from that you can use it the same as windows. Wine provides a z-drive by default that links to your linux file system and PATH variables to the compiler executables should work fine.
You can write your code in any text editor you like. The auther likes VSCode as it runs both on linux and windows and it folder based (contrary to for example Visual Studio which is solution based). So you can just create a new folder for your project and at the a new c-file to it. VSCode has extension for c syntax highlighting to make life a little easier. But this is not about talking up VSCode, use whatever you like for editing. Once you have a folder and a C-file, you can create eiter a batch file or make file to run the compilation. The author prefers a simple batch file as they are native to windows and are very simple to use.

a basic c file looks like this:

  1. include <stdio.h>
  2. include <sys/types.h>
  1. define BORDER_Y_SIZE (*(volatile unsigned char *)0xAF0009)

volatile unsigned char * const textScreen = (unsigned char *)0xAFA000;

void IRQHandler(void) { }

void main(void) { BORDER_Y_SIZE = 0; textScreen[0] = 'H'; }


To the batch file add the following lines wdc816cc -ML demo.c wdcln -HI -V -T -P00 demo.obj c0l.obj -LCL -O demo.hex -C1000

The first line calls the compiler (wdc816cc) the import swith here is the -M switch. This specifies the memory model the compiler is going to use when compiling code. The example here is using the large model. Choosing the right memory model for your code can have a significant impact on the resulting codes execution performance. The 65816 is a 16-bit cpu but can adress up to 16MB of memory using 32 bit pointers in the large model (the bus is actually 24bit). But this take more CPU cycles than using 16bit pointers. 16 bit pointers are however to small to address all memory. So you can only use those if your code or data fits within a single page of memory (64kb). To make things more confusing. We can specify different models for both data and code. WDC provides the following table to choose a model. For more details refer to the chapter on memory models in the compiler manual (816cc.pdf)

<64K Code >64K Code
<64K data Small Medium
>64K data Compact Large

The Second line of the example links to objects the compiler generated into a single hex file that can be uploaded to the foenix. -H specifies the output format. Here it is (I) Intel Hex. Though not required -V make the linker output the locations of functions and data/code segments and symbols. In this output you will notice that the compiler prefixes every function/symbol with a combination of (~) and (_). This is used to signify the memory model used by that part of the code. Unfortunately these prefixes turn up in error messages. So when you see this in an error just ignore them and find the function or such without these prefixes in your code. -T this generates a map file. -P specifies the fill characters for the output hex file. 00 will be fine here. -L is used to specify one or more libraries. Choose the correct libraries depending again on your choosen memory model. The linker manaual documents this. -O for the output hex file name. You can tell the linker to load code and data (initialized and unintialized) to specfic locations. In this example I only specify a location for the Code segment (-C1000 start code at hex 1000). The linker will layout other sections using the code segment as a starting point. The objects linked together in this example are demo.obj and col.obj. demo.obj is the output from the C-Compiler. Normally this is enough, however with the foenix we are talking a system that (excluding the kernel) does not have a formal operating system. So you need some startup code to actually set some thing up like the stack and interrupt handlers and the proper vectors. You can create the needed assembly code for this yourself. But WDC provides a few default options. C0S.OBJ, C0C.OBJ, C0M.OBJ and C0L.OBJ. Again choose the proper one based on your choise of memory model. The manual actually states that the ASM files of these are included to tweak to desire. This however is not the case. If one is interested, they can be requested by mailing WDC and asking for them. These example startup code objects do not know anything about the foenix kernel and thus assume your program is the only one running. In time proper starup objects and a format for binaries to work along with the foenix kernel should appear, but have not materialized yet. Considering that this is really a plaform to experiment the author feels this is not a significant problem at the moment.