Last update: Februari 17th 2023

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.

Version 3.1.1
Xa99_Pass_One.cpp :: Xa_Pass_One() - Add undefined opcode as symbol name in symbol table
Xa99_Pass_Two.cpp :: Xa_Pass_Two() - Added ASM_ERROR_OUT_OF_SYNC error if label
                                     address is different between PASS1 and PASS2
Xa99_OpcFunc.cpp :: Drt_Equ()      - Added ASM_ERROR_OUT_OF_SYNC error if symbol
                                     address is different between PASS1 and PASS2
                                     Added and error message for bad forward reference if
                                     a complex EQU definition is used before it was defined.

Version 3.1.2
All files :: all functions     - Removed most garbage. Some commented lines are left for reference
                                 purposes so that a do not add the same wrong and stupid ideas :-)
Xa99_List.cpp :: all functions - Removed all unused function arguments because  is
                                 being used as the comment line in the listing so that the
                                 listing is allmost exactly the same as the listing produced
                                 by the Texas Instruments Assembler of the Ed/As module.
Xa99.cpp :: print_error_text() - Errors are printed to stderr instead of stdout.

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 -P Print symbol table dump to console -C Create object file in compressed format -D symbol Define a symbol (max 6 characters and has a value of 0) -V Verbose mode, show some information about the process

Result codes:

0 No error(s) 1 Assembler errors 2 Can't open or read input file 3 Can't open output file 4 Symbol table overflow 5 Memory error (malloc failed)


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]

Warning: goto_ti99geek.html could not be included.