Last update: December 29th 2014

XA99 - Cross Assembler 99

The XA99 cross assembler for the PC is part of the development environment of the TI994W emulator and can be found in the utility (TI994W/UTL/) directory.

XA99 (Cross Assembler 99) is a program for assembling TMS9900 assembler code for example for the TI99/4A or Geneve home computer. XA99 can be run on a PC.


Usage: XA99 -I<input file> [-O<output file>] [-L[<list file>]] [Options]

Options between [ ] are optional.


Example: XA -Imy_program.a99 -R -L -S


Commands recognized by XA99:

-I<file name> Input source file -O<file name> Output object file -L<file name> Output list file If no output or list file name is defined on the command line then the output file name and list file name is the same as the input file name with extensions '.obj' and '.lst'.

Options:

-R Define registers R0 through R15 -L Create a list file -S Add symbol table dump to list file -s Add segment table dump to list file -C Create object file in compressed format -V Verbose mode, show some informaton about the process


Features of XA99:

  • Compatible with the TI99/4A assembler of the Editor/Assembler module.

  • Generates an equal listing as the assemler of the Editor/Assembler module.
    The listing only differs in version number. This makes it easy to compare a listing file of both assemblers.

  • Generates equal object file as the assemler of the Editor/Assembler module.
    This makes it easy to compare an object file of both assemblers.

  • Handles maximum of 128 segments.

  • Supports TMS9995 opcodes DIVS, MPYS, LST, LWP.

  • Supports simple conditional assembling.
    Preprocessor directives like #if , #ifdef, #ifndef, #else, #endif are supported.

  • Searches include files (with the COPY directive) with user defined extensions.

  • Substitutes device names (like DSK1.) by user defined paths.

  • An (new) error is issued if R0 is used as an index register in any assembler instruction.
    For example MOV R8,@TABLE(R0) is what you really want to do but does not work because R0 just can NOT be used as an index register. This error message prevents you for having some severe headache (this is a common made beginners mistake).


The XA99.INI file

The XA99.INI file is used to define how COPY directives should be handled.

EXTENSIONS
If a COPY directive is encountered and there is no extension defined for the assembler source file (like COPY "MYFILE") than the file will be searched with the extensions added as defined with the EXTENSIONS key word in the given order.


INCLUDE
If a COPY directive is encountered and there is no path defined for the assembler source file (like COPY "MYFILE") than the file will be searched in the directories as defined with at the INCLUDE key word in the given order.


SUBSTITUTE
If a COPY directive is encountered and there is a TI device name with or without a path defined in front of the assembler (like COPY "DSK1.MYFILE" or COPY "WDS1.PROG.MYFILE") source file name than the SUBSTITUTE section is searched for a devicename / path combination.


Example:
If an assembly source file contains a copy directive, for example like COPY "DSK1.MYFILE" and a XA99.INI file is used with the below defined content, the include file is searched by the XA99 assembler as folows:

1) The device name "DSK1." is replaced by an empty string, COPY "MYFILE" remains.

2) First the extension .inc is added which results in COPY "MYFILE.inc".

3) Because there is no preceding path in the file name, the file will be first searched in the current directory (".\MYFILE.inc"), then ... if not found, in the previous directory (".\..\MYFILE.inc"), then ... if not found, in the last defined directory ("D:\TI994W\INCLUDE\MYFILE.inc").

4) If the file is still not found then the whole proces starts again but this time the extension .a99 is used.

5) If the file is found the assembler continues else an error message is issued.


If a device name is substituted for a path, like "DSK1.=C:\INCLUDE\" then only the defined extensions are tried to find the file because rule #3 does not apply in this case.


    [CONFIG]
    EXTENSIONS=.inc;.a99
    INCLUDE=.\;.\..\;D:\TI994W\INCLUDE\

    [SUBSTITUTE]
    DSK1.=
    DSK2.=
    DSK3.=
    SCS1.TILIB.=


XA99 Preprocessor

The XA99 Cross Assembler is equiped with a simple preprocessor wich makes it possible to exclude some code for assembling or make some code dependend for some defined symbol.

#if / [#else] / #endif

The #if directive can be used to include or exclude some code for assembling. If a symbol is used then the code is included if the value of the symbol is not equal to 0, the code is excluded if the value of the symbol is equal to 0.


 Example(s):
 
    #if 0
           MOV R0,R1    Exlude this code
    #endif
 
    #if 1
           MOV R0,R2    Include this code
    #endif
 
    #if 0    
           MOV R0,R1    Exclude this code
    #else
           MOV R0,R2    Bit include this code
    #endif    

    SYMBOL EQU 1
    
    #if SYMBOL
           MOV R0,R1    Include this code if SYMBOL <> 0
    #else
           MOV R0,R2    Include this code if SYMBOL = 0
    #endif    



#ifdef [/ #else] / #endif

The #ifdef directive can be used to include code if some SYMBOL is defined. If the SYMBOL is undefined then the code is excluded.


 Example(s):
 
    #ifdef SYMBOL
           BL  @THIS    Include this code only if symbol is defined
    #endif
 
    #ifdef SYMBOL
           BL  @THIS    Include this code if SYMBOL is defined
    #else
           BL  @THAT    Include this code if SYMBOL is undefined
    #endif    



#ifndef [/ #else] / #endif

The #ifndef directive can be used to include code if some SYMBOL is undefined. If the SYMBOL is defined then the code is excluded.


 Example(s):
 
    #ifndef SYMBOL
           BL  @HERE    Include this code if SYMBOL is undefined
    #endif
 
    #ifndef SYMBOL
           BL  @HERE    Include this code if SYMBOL is undefined
    #else
           BL  @THERE    Include this code if SYMBOL is defined
    #endif    



List file

In a list file some character are used to indicate the type of symbols or addresses. These characters have the following meaning:

 In symbol table:

  space   No special meaning
    '     Symbol is relocatable
    +     Symbol has an absolute address
    D     Symbol is in the XDEF list
    U     Symbol is undefined
    E     Symbol is in the XREF list
    X     Symbol is an defined extended operation (DXOP)
  
  
 In code:

  space   Symbol address is in an undefined segment,
          dummy origin (DORG) or absolute origin (AORG)
    '     Symbol address is in a relocatable origin (RORG)
          or program segment (PSEG)
    "     Symbol address is in a data segment (DSEG)
    +     Symbol address is in a (user defined) common segment (CSEG 'NAME')



Expressions

Some information I found about expressions in the "Model 990/12 Computer Assembly Language Programmer's guide" paragrapgh "2.10 Expressions" page 2-19 and which is not mentioned in the Editor/Assembler manual is the following:

    if in an expression
       NA = sum of relocatable symbols added
       NS = sum of relocatable symbols subtracted
    then if
       NA - NS == 0 : Expression is absolute
       NA - NS == 1 : Expression is relative
       other is illigal



Sample Assembler listing and object file

Here below you will find a sample of an assembler listing containing some segments and the object file containing the code.


   Xa99 Cross Assembler
  VERSION 1.2/A                                                PAGE 0001
    0001            * A sample assembler listing created with XA99
    0002            * to demonstrate segments.
    0003            
    0004            	IDT	'XA99SMPL'
    0005            	
    0006            	DEF	L001,L101,L201,T001,T002
    0007            	REF	R001,R002
    0008            
    0009            ***************************************
    0010            
    0011 0000       L001	RORG			
    0012            
    0013 0000 0001  D001	DATA	1,2,3,4
         0002 0002 
         0004 0003 
         0006 0004 
    0014 0008 000A  D002	DATA	>A,>B,>C,>D
         000A 000B 
         000C 000C 
         000E 000D 
    0015 0010 0041  D003	DATA	'A','B','C'
         0012 0042 
         0014 0043 
    0016 0016   41  D004	BYTE	'A','B','C'
         0017   42 
         0018   43 
    0017 0019   41  D005	TEXT	'ABC'
    0018            	EVEN
    0019            
    0020 001C 0000' T001	DATA	D001,D002
         001E 0008'
    0021            
    0022 0020 0201  L002	LI	R1,D001
         0022 0000'
    0023 0024 C0A0  	MOV	@T001,R2
         0026 001C'
    0024            
    0025            ***************************************
    0026            
    0027 C000       L101	DORG	>C000
    0028            
    0029 C000 0001  D101	DATA	1,2,3,4
         C002 0002 
         C004 0003 
         C006 0004 
    0030 C008 000A  D102	DATA	>A,>B,>C,>D
         C00A 000B 
         C00C 000C 
         C00E 000D 
    0031            
    0032 C010 C000  T101	DATA	D101,D102
         C012 C008 
    0033            
    0034 C014 0201  L102	LI	R1,D101
         C016 C000 
    0035 C018 C0A0  	MOV	@T101,R2
         C01A C010 
    0036            
    0037            ***************************************
 
   Xa99 Cross Assembler
  VERSION 1.2/A                                                PAGE 0002
    0038            
    0039 A000       L201	AORG	>A000
    0040            
    0041 A000 0001  D201	DATA	1,2,3
         A002 0002 
         A004 0003 
    0042 A006 000A  D202	DATA	>A,>B,>C
         A008 000B 
         A00A 000C 
    0043            
    0044 A00C A000  T201	DATA	D201,D202
         A00E A006 
    0045            
    0046 A010 0201  L202	LI	R1,D001
         A012 0000'
    0047 A014 C0A0  	MOV	@T201,R2
         A016 A00C 
    0048            
    0049            ***************************************
    0050            
    0051 0000       L301	DSEG			Define your data in a DSEG
    0052            
    0053 0000 0001  D301	DATA	1,2,3
         0002 0002 
         0004 0003 
    0054 0006 000A  D302	DATA	>A,>B,>C
         0008 000B 
         000A 000C 
    0055 000C   30  D303	TEXT	'0123456789ABCDEF'
    0056            	EVEN
    0057            	
    0058 001C       	DEND
    0059            	
    0060            ***************************************
    0061            
    0062 0028       L401	PSEG			Same segment as RORG
    0063            
    0064 0028 0201  	LI	R1,D001
         002A 0000'
    0065 002C 0202  	LI	R2,D005
         002E 0019'
    0066 0030 04C0  	CLR	R0
    0067 0032 0203  	LI	R3,1
         0034 0001 
    0068 0036 C120  	MOV	@T001(R0),R4	This is an error
         0038 001C'
  *****  INVALID INDEX REGISTER R0 - 0068
    0069 003A C123  	MOV	@T001(R3),R4	And this is okay
         003C 001C'
    0070            	
    0071 003E       	PEND
    0072            
    0073            ***************************************
    0074            
    0075 0000       L501	CSEG	'MYSEG1'	User defined segment
    0076            
    0077 0000 0201  L502	LI	R1,D001
         0002 0000'
    0078 0004 C0A0  	MOV	@T001,R2
  
   Xa99 Cross Assembler
  VERSION 1.2/A                                                PAGE 0003
         0006 001C'
    0079 0008 0202  	LI	R2,D303
         000A 000C"
    0080            
    0081 000C 0201  L503	LI	R1,D001
         000E 0000'
    0082 0010 C0A0  	MOV	@T201,R2
         0012 A00C 
    0083            
    0084 0014       	CEND
    0085            	
    0086            ***************************************
    0087            
    0088 0000       L601	CSEG	'MYSEG2'	User defined segment
    0089            
    0090 0000 0201  	LI	R1,D001
         0002 0000'
    0091 0004 C0A0  	MOV	@T001,R2
         0006 001C'
    0092 0008 C0E0  	MOV	@T002,R3
         000A 0000 
  *****  BAD FWD REFERENCE - 0092
    0093 000C 0460  	B	@L503
         000E 000C+
    0094            
    0095 0010       	CEND
    0096            
    0097            ***************************************
    0098            
    0099 0014       L701	CSEG	'MYSEG1'	Continues user defined segment MYSEG1
    0100            
    0101 0014 0201  L702	LI	R1,R001
         0016 0000 
    0102 0018 C0A0  	MOV	@R002,R2
         001A 0000 
    0103 001C 0203  	LI	R3,L601
         001E 003E+
    0104            
    0105            	DXOP	MYXOP,7
    0106            	
    0107 0020 2DE0  	MYXOP	@>1234
         0022 1234 
    0108            
    0109 0024       	CEND
    0110            
    0111            ***************************************
    0112            *
    0113            * Sense and nonsense in expressions:
    0114            *
    0115            * See "Model 990/12 Computer Assembly Language
    0116            *      Programmer's guide" 
    0117            * Paragraph "2.10 Expressions" page 2-19
    0118            *
    0119            * if in an expression
    0120            *    NA = sum of relocatable symbols added
    0121            *    NS = sum of relocatable symbols subtracted
    0122            * then if
    0123            *    NA - NS == 0 : Expression is absolute
    0124            *    NA - NS == 1 : Expression is relative
  
   Xa99 Cross Assembler
  VERSION 1.2/A                                                PAGE 0004
    0125            *    other is illigal
    0126            *
    0127 003E       	PSEG
    0128            	
    0129 003E       D801	BSS	10		A table
    0130 0048       D802	BSS	20		Another table
    0131 005C       D803	BSS	30		And a third table
    0132            
    0133      0002  EQ01	EQU	2
    0134      0004  EQU2	EQU	4
    0135      0006  EQU3	EQU	6
    0136            
    0137 007A 000A  S801	DATA	D802-D801	(NA-NS=0 Abs) This is the size of D801
    0138 007C 0014  S802	DATA	D803-D802	(NA-NS=0 Abs) This is the size of D802
    0139            
    0140 007E 0000  X801	DATA	D802+D801	(NA-NS=2 XXX) This is nonsence
  *****  SYNTAX ERROR - 0140
    0141      0000  Q801	EQU	D802+D801-5	Doesn't matter how it is used, still no
  *****  SYNTAX ERROR - 0141
    0142            
    0143 0080 0066' OKAY1	DATA	D803+D802-D801	(NA-NS=1 Rel) This some offset in D
    0144            
    0145 0082       	PEND
    0146            	
    0147            	END
     THE FOLLOWING SYMBOLS ARE UNDEFINED:
  T002
  
   Xa99 Cross Assembler
  VERSION 1.2/A                                                PAGE 0005
    ' D001    0000    ' D002    0008    ' D003    0010    ' D004    0016  
    ' D005    0019      D101    C000      D102    C008      D201    A000  
      D202    A006    ' D301    0000    ' D302    0006    ' D303    000C  
    ' D801    003E    ' D802    0048    ' D803    005C      EQ01    0002  
      EQU2    0004      EQU3    0006    D L001    0000    ' L002    0020  
    D L101    C000      L102    C014    D L201    A000      L202    A010  
      L301    A018    ' L401    0028    ' L501    003E    ' L502    0000  
    ' L503    000C    ' L601    003E    ' L701    003E    ' L702    0014  
    X MYXOP   0007    ' OKAY1   0080      Q801    0000      R0      0000  
    E R001    0016    E R002    001A      R1      0001      R10     000A  
      R11     000B      R12     000C      R13     000D      R14     000E  
      R15     000F      R2      0002      R3      0003      R4      0004  
      R5      0005      R6      0006      R7      0007      R8      0008  
      R9      0009    ' S801    007A    ' S802    007C    D T001    001C  
    U T002    0000      T101    C010      T201    A00C    ' X801    007E  
    0004 ERRORS
  
   Xa99 Cross Assembler
  VERSION 1.2/A                                                PAGE 0006
    SEGMENT DORG     SIZE 00028 (>001C) BYTES
    SEGMENT AORG     SIZE 00024 (>0018) BYTES
    SEGMENT RORG     SIZE 00130 (>0082) BYTES
    SEGMENT $DATA    SIZE 00028 (>001C) BYTES
    SEGMENT MYSEG1   SIZE 00036 (>0024) BYTES
    SEGMENT MYSEG2   SIZE 00016 (>0010) BYTES

  00082XA99SMPLM001C$DATA 0000M0024MYSEG10002M0010MYSEG20003A00007F135F       0001
  A0000B0001B0002B0003B0004B000AB000BB000CB000DB0041B0042B00437F34CF          0002
  A0016B4142B4341B4243C0000C0008B0201C0000BC0A0C001C9A000B00017F337F          0003
  9A002B0002B0003B000AB000BB000CBA000BA006B0201C0000BC0A0BA00C7F2F8F          0004
  S0000B0001B0002B0003B000AB000BB000CB3031B3233B3435B3637B38397F319F          0005
  S0016B4142B4344B4546A0028B0201C0000B0202C0019B04C0B0203B00017F333F          0006
  A0036BC120C001CBC123C001CP00000002B0201C0000BC0A0C001CB0202T000C7F21AF      0007
  P000C0002B0201C0000BC0A0BA00CP00000003B0201C0000BC0A0C001CBC0E07F24EF       0008
  P000A0003B0000B0460N000C0002P00140002B0201B0000BC0A0B0000B02037F2E7F        0009
  P001E0002N003E0003B2DE0B1234A003EA0048A005CA007AB000AB0014B00007F24BF       0010
  A0080C00667FDB1F                                                            0011
  50000L001  6C000L101  6A000L201  5001CT001  7F73CF                          0012
  X0016R001  0002X001AR002  00027F9B5F                                        0013
  :       XA99 v1.2/a                                                         0014




[EOF]