Last update: Februari 25th 2023

C99C - C99 Compiler and Optimizers

The C99C compiler for the PC and optimizers are part of the development environment of the TI994W emulator and can be found in the utility directory TI994W/UTL/.

Introduction

This page gives a description of the C99 Compiler environment I use on my PC for creating programs for the TI99/4A home computer. The C99 compiler with the C99 optimizers, Xa99 cross assembler and L99 linker forms a simple environment. The optimizers were written to be able to create and shrink programs like DM2K and DU2K so that programs like this can be used on a standard TI99/4A.

Current versions:

C99C - V 5.1.1 Clint Pulley's C99 compiler (until version 4.0) C99O - V 5.6.1 Base optimizer C99M - V 1.2.0 Move Instruction Optimizer C99X - V 1.4.7 X-File optimizer C99F - V 2.1.1 Function call and Jump optimizer C99Z - V 1.1.1 Final optimizer

C99C - C Compiler

C99C is the PC version of the C99C compiler for the TI99/4A home computer written by Clint Pulley. This X-compiler version of C99 is based on the source code release of 91/02/23 and was created somewhere in 2002.
4.0 1987/10/24 - Final 99/4A version. - Reports lines processed, global and local symbol counts. - Implements hex constants. - Issues "call files(3)" during initialization. - Corrects problem with decimal input. 4.1.0 2002/00/00 FGK - Created a C99C WIN32 console program :-) 4.1.0 2006/00/00 FGK - Fixed some runtime problems because of using uninitialized variables. 4.1.2 2021/05/02 FGK - Fixed some problems so that C99C can be used with make. Increased MACQSIZE from 1000 to 2000. 4.2.1 2023/01/02 FGK - Global symbol names converted to uppercase to prevent problems when unintentionally cases are mixed which could generate the wrong code, i.e. LI 8,NAME instead of MOV @NAME,8 (must be uppercase for the assembler anyway). 5.1.1 2023/01/04 FGK - Added assignment operators +=, -=, &=, |=, *=, /=, %=, <<= and >>= Allow // for single line comment. Added void type (handled as an int). Added new style function declarations like type function(type args); Added function prototyping: o entry type function(type arg, type arg); o static type function(type arg, type arg); o extern type function(type arg, type arg); and also variable argument list is allowed, like: o int printf(char *fmt, ...); type can be char, char *, int, int * or void which is handled like an int. Return type is not checked but is there to help you ... the programmer. When a function is called the number of arguments is checked. In the case of a variable argument list the minimum number of arguments is checked. An error is issued when number of arguments does not match.
    Usage: C99 inputfile outputfile [errorfile] [/tp]

    Options:
        /t        Keep original C-source line as comment in assembler code
        /p        Generate inline push-code
        /s        Add global symbol table dump to error file (since 5.1.1)

The C99 compiler generates ready to assemble code wich can be linked together with supplied libraries (like CSUP, file-IO etc) or your own created libraries to an running editor/assembler option 5 program for the TI99/4A.

C99O - C Optimizer

The C99O optimizer is the PC version of the optimizer originally supplied by the first version of the C99 compiler. This program started as a version for for the Geneve to run under MDOS and more and more optimizations where added over the years. Everytime I studied the assembler code created I saw something new to optimize.

    *c99 optimizer v4.5/g

    Usage: C99O inputfile outputfile

The original version of C99O only optimized code for simple assignment statements like A=B but this version of C990 optimizes every obvious assembler code that looks like it can be done simpler, like A=B&C, A=B|C, switch(A), if (A==B), etc, etc, etc.

Using this optimizer results in a smaller (and faster) program.

Here below you will see some examples how C99C code is optimized by C99O:

    C99C                               C99O
    =========================          =========================
    *key=10;
     MOV 14,8                          LI 8,10
     AI 8,12                           MOV 8,@12(14)
     BL 15
     LI 8,10
     MOV *14+,9
     MOV 8,*9

    *switch(key)
     MOV 14,8                          MOV @12(14),8
     AI 8,12                           B @C$6
     MOV *8,8
     B @C$6

    *Qftype = Qfparm & M_FTYP;
     MOV @QFPARM,8                     MOV @QFPARM,8
     BL 15                             ANDI 8,15
     LI 8,15                           MOV 8,@QFTYPE
     INV *14
     SZC *14+,8
     MOV 8,@QFTYPE

    *Qfparm = Qftype | Qfprot | Qfslct;
     MOV @QFTYPE,8                     MOV @QFTYPE,8
     BL 15                             SOC @QFPROT,8
     MOV @QFPROT,8                     SOC @QFSLCT,8
     SOC *14+,8                        MOV 8,@QFPARM
     BL 15
     MOV @QFSLCT,8
     SOC *14+,8
     MOV 8,@QFPARM

    *newname[0] = 0;
     MOV 14,8                          MOV 14,8
     BL 15                             MOV 8,9
     S 8,8                             S 8,8
     A *14+,8                          MOVB *10,*9
     BL 15
     S 8,8
     MOV *14+,9
     MOVB *10,*9

C99X - X File Optimizer

The C99X - X File Optimizer replaces calls to standard C-functions like gets(), puts(), putchar(), locate(), poll() and tscrn() and all string and memory funtions like strcpy(), strlen(), strcat(), strcmp(), memset(), memcpy() for witch the arguments are placed on the C-stack first to the functions XGETS(), XPUTS(), XPUTC(), XLOCAT(), XPOLL(), XTSRCN(), XSCPY(), XSLEN(), XSCAT(), XSCMP(), XMSET(), XMCPY(), XMMOV() if possible but arguments are placed in registers. The code for placing the arguments on the C- stack is removed together with the code (or instruction) to clean-up the C- stack. I found that the first thing these standard C-functions do is reading the values from the C-stack and placing them in registers making the code (IMHO) for placing the arguments on the stack and cleaning the stack unnecessary. Replacing these function calls can only succeed if the arguments are in their most simple form, like FUNCTION(A,B) and not like FUNCTION(A+B,C*D). To use this optimizer an updated CSUP (CSUPTI_V7) must be used.

Using this optimizer results in a smaller (and faster) program.

    *c99 x-optimizer v1.4/g

    Usage: C99X inputfile outputfile


Here below you will see some examples how C99C code is optimized by C99X:

    C99C                               C99X
    =========================          =========================
    *locate(ypos,1);
     MOV @YPOS,8                       MOV @YPOS,1
     BL 15                             LI 0,1
     LI 8,1                            BL *12
     BL 15                             DATA XLOCAT
     BL *12
     DATA LOCATE
     AI 14,4

    *locate(y,x);
     MOV @58(14),8                     MOV @58(14),1
     BL 15                             MOV @62-2(14),0
     MOV @62(14),8                     BL *12
     BL 15                             DATA XLOCAT
     BL *12
     DATA LOCATE
     AI 14,4

    *putchar('>');
     LI 8,62                           LI 1,62
     BL 15                             BL *12
     BL *12                            DATA XPUTC
     DATA PUTCHA
     INCT 14

    *strcpy(Srcfil,Src);
     LI 8,SRCFIL                       LI 1,SRCFIL
     BL 15                             LI 2,SRC
     LI 8,SRC                          BL *12
     BL 15                             DATA XSCPY
     BL *12
     DATA STRCPY
     AI 14,4

   *strcat(Srcfil,Pfname);
    LI 8,SRCFIL                        LI 0,SRCFIL
    BL 15                              MOV @PFNAME,1
    MOV @PFNAME,8                      BL *12
    BL 15                              DATA XSCAT
    BL *12
    DATA STRCAT
    AI 14,4

C99F - Function Call Optimizer

The C99F - Function Call Optimizer replaces the code for storing function arguments on the C-stack for code that store the arguments in registers (R0-R8) and a call to a function (FARG#1 through FAARG#8) that will store all these register values on the C-stack. This optimization can only succeed for functions with 1 through 8 arguments and the arguments are in their most simple form, like FUNCTION(A,B) and not like FUNCTION(A+B,C*D). To use this optimizer the library FNCARG must be linked.
The C99F optimizer also optimizes compare instuctions by replacing a branch to a compare subroutine by a TMS9900 compare instruction wherever possible. The C99F optimizer checks if the destination of the jump is within some amount of instructions.

Using this optimizer and library results in a smaller (and not necessary faster) program.

    *c99 f-optimizer v1.3/g

    Usage: C99F inputfile outputfile


Here below you will see some examples how C99C code is optimized by C99F:

    C99C                               C99F
    =========================          =========================
    *setkbm(5);
     LI 8,5                            LI 8,5
     BL 15                             BL @FARG#1
     BL *12                            DATA SETKBM
     DATA SETKBM                       INCT 14
     INCT 14

    *getfps(FilesP, pFile);
     MOV @FILESP,8                     MOV @FILESP,7
     BL 15                             MOV @PFILE,8
     MOV @PFILE,8                      BL @FARG#2
     BL 15                             DATA GETFPS
     BL *12                            AI 14,4
     DATA GETFPS
     AI 14,4

    *key = answer("Exit program? ([y],n) ",0);
     MOV 14,8                         MOV 14,6
     AI 8,12                          AI 6,12
     BL 15                            LI 7,C$1
     LI 8,C$1                         S 8,8
     BL 15                            BL @FARG#3
     S 8,8                            DATA ANSWER
     BL 15                            AI 14,4
     BL *12                           MOV *14+,9
     DATA ANSWER                      MOV 8,*9
     AI 14,4
     MOV *14+,9
     MOV 8,*9

    *if (Qftype<=FT_SUB) [Label C$20 within range for sure]
     MOV @QFTYPE,8                    MOV @QFTYPE,8
     BL 15                            CI 8,6
     LI 8,6                           JGT C$20
     BL @C$LE
     JNE $+6
     B @C$20

    *if (Qftype<=FT_SUB) [Label C$8 maybe out of range]
     MOV @QFTYPE,8                    MOV @QFTYPE,8
     BL 15                            CI 8,6
     LI 8,6                           JLT $+8
     BL @C$LE                         JEQ $+6
     JNE $+6                          B @C$8
     B @C$8

C99M - Move Instruction Optimizer

The C99M - Move Instruction Optimizer is capable in optimizing certain MOV instructions in the assembler code as generated by the C99O optimizer.

Using this optimizer results in a smaller (and faster) program.

    *c99 m-optimizer v1.1/g

    Usage: C99M inputfile outputfile


Here below you will see some examples how C99C code is optimized by C99O and c99O code code is optimized by C99M:

    C99C                               C99O                               C99M
    =========================          =========================          =========================
    *for (...; ...; i=i+1)
     MOV 14,8                          MOV 14,8                           MOV 14,9
     BL 15                             BL 15                              MOV *9,8
     MOV 14,8                          MOV @2(14),8                       AI 8,1
     INCT 8                            AI 8,1                             MOV 8,*9
     MOV *8,8                          MOV *14+,9
     BL 15                             MOV 8,*9
     LI 8,1
     A *14+,8
     MOV *14+,9
     MOV 8,*9

    *sx = x+p;
     MOV 14,8                          MOV 14,8                           MOV 14,9
     AI 8,10                           AI 8,10                            AI 9,10
     BL 15                             BL 15                              MOV @24(14),8
     MOV 14,8                          MOV @26(14),8                      A @4(14),8
     AI 8,26                           A @8-2(14),8                       MOV 8,*9
     MOV *8,8                          MOV *14+,9
     BL 15                             MOV 8,*9
     MOV 14,8
     AI 8,8
     MOV *8,8
     A *14+,8
     MOV *14+,9
     MOV 8,*9

C99Z - Final Optimizer

The C99Z - Final Instruction Optimizer optimizes assignments, compares instructions in the assembler code as generated by the C99O / C99M and C99F optimizers. This optimizer searches for those instructions that loads R8 with a value and then compares this value with zero (CI 8,0) or determine the absolute value (ABS 8) followed by some JMP instruction. Then this CI or ABS instruction is unnecessary. Another optimization is some assignment using R8 as an intermediant register (MOV x,8 and MOV 8,y). This is unnecessary if R8 is used again in the next instuction and the two MOV instructions are replaced by one MOV x,y instruction. Onother optimization is when the address of a variable is determined using R8 and this address is directly moved to R9 followed by determining the value for this same variable using R8. This is replaced by the determining the addres of the variable directly in R9.

Using this optimizer results in a smaller (and faster) program.

    *c99 z-optimizer v1.1/g

    Usage: C99Z inputfile outputfile


Here below you will see some examples how C99C code is optimized by C99O and C99Z:

    C99C                               C99O                 C99F                 C99Z            
    =========================          ================     ================     ================
    *if (dbuf == 0) ...                                                          
     MOV @DBUF,8                       MOV @DBUF,8          MOV @DBUF,8          MOV @DBUF,8
     BL 15                             BL 15                CI  8,0              JNE C$6 
     S 8,8                             S 8,8                JNE C$6                    
     BL @C$EQ                          BL @C$EQ                                          
     JNE $+6                           JNE $+6                                  
     B @C$6                            B @C$6       <- Label C$6 is in reach of JMP                              
                                                                                 
    *FilesT = FilesP;                                                                   
     MOV @FILESP,8                     MOV @FILESP,8        MOV @FILESP,8        MOV @FILESP,@FILEST
     MOV 8,@FILEST                     MOV 8,@FILEST        MOV 8,@FILEST
     *
     MOV @REFRES,8    <- R8 is used in the next instruction
     
    *newname[0] = 0;                   
     MOV 14,8                          MOV 14,8             MOV 14,8             MOV 14,9
     INCT 8                            INCT 8               INCT 8               INCT 9
     BL 15                             MOV 8,9              MOV 8,9              S 8,8
     S 8,8                             S 8,8                S 8,8                MOV *10,*9
     A *14+,8                          MOVB *10,*9          MOVB *10,*9          
     BL 15                             
     S 8,8                             
     MOV *14+,9                        
     MOVB *10,*9                       






[EOF]

Warning: goto_ti99geek.html could not be included.