home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1986 / 05 / xassm.lst < prev   
File List  |  1986-05-31  |  143KB  |  4,970 lines

  1.  
  2. LISTING ONE
  3. DEFINITION MODULE LongNumbers;            
  4. (* Routines to handle HEX digits for the X68000 cross assembler. *)
  5. (* All but LongPut and LongWrite are limited to 8 digit numbers. *)
  6.  
  7.    FROM Files IMPORT
  8.       FILE;
  9.  
  10.    EXPORT QUALIFIED
  11.       LONG, LongClear, LongAdd, LongSub, LongInc, LongDec, 
  12.       LongCompare, CardToLong, LongToCard, LongToInt, 
  13.       LongPut, LongWrite, StringToLong, AddrBoundL, AddrBoundW;
  14.  
  15.    CONST
  16.       DIGITS = 8;
  17.       BASE = 16;
  18.  
  19.    TYPE
  20.       LONG = ARRAY [1..DIGITS] OF INTEGER;
  21.  
  22.  
  23.    PROCEDURE LongClear (VAR A : LONG);
  24.    (* Sets LONG to Zero *)
  25.  
  26.    PROCEDURE LongAdd (A, B : LONG; VAR Result : LONG);
  27.    (* Add two LONGs, giving Result *)
  28.  
  29.    PROCEDURE LongSub (A, B : LONG; VAR Result : LONG);
  30.    (* Subtract two LONGs (A - B), giving Result *)
  31.  
  32.    PROCEDURE CardToLong (n : CARDINAL; VAR A : LONG);
  33.    (* Converts CARDINAL to LONG *)
  34.  
  35.    PROCEDURE LongToCard (A : LONG; VAR n : CARDINAL) : BOOLEAN;
  36.    (* Converts LONG TO CARDINAL, returns FALSE if conversion impossible *)
  37.  
  38.    PROCEDURE LongToInt (A : LONG; VAR n : INTEGER) : BOOLEAN;
  39.    (* Converts LONG to INTEGER, returns FALSE if conversion impossible *)
  40.  
  41.    PROCEDURE LongInc (VAR A : LONG; n : CARDINAL);
  42.    (* Increment LONG by n *)
  43.  
  44.    PROCEDURE LongDec (VAR A : LONG; n : CARDINAL);
  45.    (* Decrement LONG by n *)
  46.  
  47.    PROCEDURE LongCompare (A, B : LONG) : INTEGER;
  48.    (* Returns: 0 if A = B, -1 if A < B, +1 if A > B *)
  49.  
  50.    PROCEDURE LongPut (f : FILE; A : ARRAY OF INTEGER; Size : CARDINAL);
  51.    (* Put LONG number in FILE f *)
  52.  
  53.    PROCEDURE LongWrite (A : ARRAY OF INTEGER; Size : CARDINAL);
  54.    (* Write LONG number to console screen *)
  55.  
  56.    PROCEDURE StringToLong (S : ARRAY OF CHAR; VAR A : LONG) : BOOLEAN;
  57.    (* Converts a string (in HEX) into a LONG *)
  58.  
  59.    PROCEDURE AddrBoundL (VAR A : LONG);
  60.    (* Forces Address to a 68000 long word boundary *)
  61.  
  62.    PROCEDURE AddrBoundW (VAR A : LONG);
  63.    (* Forces Address to a 68000 word boundary *)
  64.  
  65. END LongNumbers.
  66.  
  67. -------------------------------
  68. LISTING TWO
  69. DEFINITION MODULE CmdLin2;
  70. (* Parses command line - returns pointer to an array of pointer to strings *)
  71.  
  72.    FROM SYSTEM IMPORT
  73.       ADDRESS;
  74.  
  75.    EXPORT QUALIFIED
  76.       ReadCmdLin;
  77.  
  78.    PROCEDURE ReadCmdLin (VAR ArgC : CARDINAL; VAR ArgV : ADDRESS);
  79.    (* Gives count of items in command line, and an array of pointer to them *)
  80.  
  81. END CmdLin2.
  82.  
  83. --------------------------------
  84. LISTING THREE
  85. DEFINITION MODULE Parser;
  86. (* Reads the Source file, and splits each *)
  87. (* line into Label, OpCode & Operand(s).  *)
  88.  
  89.    FROM Strings IMPORT
  90.       STRING;
  91.  
  92.    FROM Files IMPORT
  93.       FILE;
  94.  
  95.  
  96.    EXPORT QUALIFIED
  97.       TOKEN, OPERAND, Line, LineCount, OpLoc, SrcLoc, DestLoc, LineParts;
  98.  
  99.  
  100.    CONST
  101.       TokenSize = 8;
  102.       OperandSize = 20;
  103.  
  104.    TYPE
  105.       TOKEN = ARRAY [0..TokenSize] OF CHAR;
  106.       OPERAND = ARRAY [0..OperandSize] OF CHAR;
  107.  
  108.    VAR
  109.       OpLoc, SrcLoc, DestLoc : CARDINAL;
  110.       Line : STRING;
  111.       LineCount : CARDINAL;
  112.  
  113.  
  114.    PROCEDURE LineParts (f : FILE; VAR EndFile : BOOLEAN; 
  115.                         VAR Label, OpCode : TOKEN; 
  116.                         VAR SrcOp, DestOp : OPERAND);
  117.    (* Reads Line, breaks into tokens, on-passes to symbol & code generators *)
  118.  
  119. END Parser.
  120.  
  121. -----------------------------------------------
  122. LISTING FOUR
  123. DEFINITION MODULE SymbolTable;
  124. (* Initializes symbol table.  Maintains list of all labels, *)
  125. (* along with their values.  Provides access to the list.   *)
  126.  
  127.    FROM LongNumbers IMPORT
  128.       LONG;
  129.  
  130.    FROM Parser IMPORT
  131.       TOKEN;
  132.  
  133.  
  134.    EXPORT QUALIFIED
  135.       FillSymTab, SortSymTab, ReadSymTab, ListSymTab;
  136.  
  137.  
  138.    PROCEDURE FillSymTab (Label : TOKEN; Value : LONG; VAR Full : BOOLEAN);
  139.    (* Add a symbol to the table *)
  140.  
  141.    PROCEDURE SortSymTab (VAR NumSyms : CARDINAL);
  142.    (* Sort symbols into alphabetical order *)
  143.  
  144.    PROCEDURE ReadSymTab (Label : ARRAY OF CHAR; 
  145.                          VAR Value : LONG; VAR Duplicate : BOOLEAN) : BOOLEAN;
  146.    (* Passes Value of Label to calling program -- returns FALSE if the *)
  147.    (* Label is not defined.  Also checks for Multiply Defined Symbols  *)
  148.  
  149.    PROCEDURE ListSymTab (i : CARDINAL; VAR Label : TOKEN; VAR Value : LONG);
  150.    (* Returns the i-th item in the symbol table *)
  151.  
  152. END SymbolTable.
  153. -------------------------------------------
  154. LISTING FIVE
  155. DEFINITION MODULE CodeGenerator;
  156. (* Uses information supplied by Parser, OperationCodes, *)
  157. (* and SyntaxAnalyzer to produce the object code.       *)
  158.  
  159.    FROM Parser IMPORT
  160.       TOKEN, OPERAND;
  161.  
  162.    FROM LongNumbers IMPORT
  163.       LONG;
  164.  
  165.  
  166.    EXPORT QUALIFIED
  167.       LZero, AddrCnt, Pass2, BuildSymTable, AdvAddrCnt, GetObjectCode;
  168.  
  169.  
  170.    VAR
  171.       LZero, AddrCnt : LONG;
  172.       Pass2 : BOOLEAN;
  173.  
  174.  
  175.    PROCEDURE BuildSymTable (VAR AddrCnt : LONG; 
  176.                             Label, OpCode : TOKEN; SrcOp, DestOp : OPERAND);
  177.    (* Builds symbol table from symbolic information of Source File *)
  178.  
  179.  
  180.    PROCEDURE AdvAddrCnt (VAR AddrCnt : LONG);
  181.    (* Advances the address counter based on the length of the instruction *)
  182.  
  183.  
  184.    PROCEDURE GetObjectCode (Label, OpCode : TOKEN;
  185.                             SrcOp, DestOp : OPERAND;
  186.                             VAR AddrCnt, ObjOp, ObjSrc, ObjDest : LONG;
  187.                             VAR   nA,      nO,    nS,     nD    : CARDINAL);
  188.    (* Determines the object code for the operation as well as the operands *)
  189.    (* Returns each (up to 3 fields), along with their length               *) 
  190.  
  191. END CodeGenerator.
  192. -------------------------------------
  193. LISTING SIX
  194. DEFINITION MODULE SyntaxAnalyzer;
  195. (* Analyzes the operands to provide information for CodeGenerator *)
  196.  
  197.    FROM LongNumbers IMPORT
  198.       LONG;
  199.  
  200.    FROM OperationCodes IMPORT
  201.       ModeTypeA, ModeTypeB, ModeA, ModeB;
  202.  
  203.    FROM Parser IMPORT
  204.       TOKEN, OPERAND, OpLoc, SrcLoc, DestLoc;
  205.  
  206.  
  207.    EXPORT QUALIFIED
  208.       OpMode, Xtype, SizeType, OpConfig,         (*      TYPEs       *)
  209.       Size, InstSize,                            (*      VARs        *) 
  210.       AddrModeA, AddrModeB, Op, Src, Dest,       (*      VARs        *)
  211.       GetValue, GetSize,                         (*    PROCEDURE's   *)
  212.       GetInstModeSize, GetOperand, GetMultReg;   (*    PROCEDURE's   *)
  213.  
  214.  
  215.    TYPE
  216.       OpMode = (DReg,      (* Data Register *)
  217.                 ARDir,     (* Address Register Direct *)
  218.                 ARInd,     (* Address Register Indirect *)
  219.                 ARPost,    (* Address Register with Post-Increment *)
  220.                 ARPre,     (* Address Register with Pre-Decrement *)
  221.                 ARDisp,    (* Address Register with Displacement *)
  222.                 ARDisX,    (* Address Register with Disp. & Index *)
  223.                 AbsW,      (* Absolute Word (16-bit Address) *)
  224.                 AbsL,      (* Absolute Word (32-bit Address) *)
  225.                 PCDisp,    (* Program Counter Relative, with Displacement *)
  226.                 PCDisX,    (* Program Counter Relative, with Disp. & Index *)
  227.                 Imm,       (* Immediate *)
  228.                 MultiM,    (* Multiple Register Move *)
  229.                 SR,        (* Status Register *)
  230.                 CCR,       (* Condition Code Register *)
  231.                 USP,       (* User's Stack Pointer *)
  232.                 Null);     (* Error Condition, or Operand missing *)
  233.  
  234.       Xtype = (X0, Dreg, Areg);
  235.       SizeType = (S0, Byte, Word, S3, Long);
  236.  
  237.       OpConfig = RECORD                 (* OPERAND CONFIGURATION *)
  238.                     Mode : OpMode;
  239.                     Value : LONG;
  240.                     Loc : CARDINAL;     (* Location of Operand on line *)
  241.                     Rn : CARDINAL;      (* Register number *)
  242.                     Xn : CARDINAL;      (* Index Reg. nbr. *)
  243.                     Xsize : SizeType;   (* size of Index *)
  244.                     X : Xtype;          (* Is index Data or Address register? *)
  245.                  END;
  246.  
  247.  
  248.    VAR
  249.       Size : SizeType;       (* size for OpCode *)  
  250.       AbsSize : SizeType;    (* size of operand (Absolute only) *)
  251.       InstSize : CARDINAL;
  252.       AddrModeA : ModeA;     (* Addressing modes for this instruction *)
  253.       AddrModeB : ModeB;     (*               ditto                   *)
  254.       Op : BITSET;           (* Raw bit pattern for OpCode *)
  255.       Src, Dest : OpConfig;
  256.    
  257.  
  258.    PROCEDURE GetValue (Operand : OPERAND; VAR Value : LONG);
  259.    (* determines value of operand (in Decimal, HEX, or via Symbol Table) *)
  260.  
  261.  
  262.    PROCEDURE GetSize (VAR Symbol : ARRAY OF CHAR; VAR Size : SizeType);
  263.    (* determines size of opcode: Byte, Word, or Long *)
  264.  
  265.    PROCEDURE GetAbsSize (VAR Symbol : ARRAY OF CHAR; VAR AbsSize : SizeType);
  266.    (* determines size of operand: Word or Long *)
  267.  
  268.    PROCEDURE GetInstModeSize (Mode : OpMode; Size : SizeType;
  269.                                  VAR InstSize : CARDINAL) : CARDINAL;
  270.    (* Determines the size for the various instruction modes.    *)
  271.  
  272.    PROCEDURE GetOperand (Oper : OPERAND; VAR Op : OpConfig);
  273.    (* Finds mode and value for source or destination operand *)
  274.  
  275.    PROCEDURE GetMultReg (Oper : OPERAND; PreDec : BOOLEAN;
  276.                          Loc : CARDINAL; VAR MultExt : BITSET);
  277.    (* Builds a BITSET marking each register used in a MOVEM instruction *)
  278.  
  279. END SyntaxAnalyzer.
  280. ------------------------------------
  281. LISTING SEVEN
  282. DEFINITION MODULE ErrorX68;
  283. (* Displays error messages for X68000 cross assembler *)
  284.  
  285.    FROM Files IMPORT
  286.       FILE;
  287.  
  288.    EXPORT QUALIFIED
  289.       ErrorType, ErrorCount, Error, WriteErrorCount;
  290.  
  291.    TYPE
  292.       ErrorType = (Dummy, TooLong, NoCode, SymDup, Undef, SymFull, Phase,
  293.                    ModeErr, OperErr, BraErr, AddrErr, SizeErr, EndErr);
  294.  
  295.    VAR
  296.       ErrorCount : CARDINAL;
  297.  
  298.    PROCEDURE Error (Pos : CARDINAL; ErrorNbr : ErrorType);
  299.    (*  Displays Error #ErrorNbr, then waits for any key to continue *)
  300.  
  301.    PROCEDURE WriteErrorCount (f : FILE);
  302.    (* Error count output to Console & Listing file *)
  303.  
  304. END ErrorX68.
  305. ---------------------------------------
  306. LISTING EIGHT
  307. DEFINITION MODULE Listing;
  308. (* Creates a program listing, including Addresses, Code & Source. *)
  309.  
  310.    FROM Files IMPORT
  311.       FILE;
  312.  
  313.    FROM LongNumbers IMPORT
  314.       LONG;
  315.  
  316.  
  317.    EXPORT QUALIFIED
  318.       StartListing, WriteListLine, WriteSymTab;
  319.  
  320.  
  321.    PROCEDURE StartListing (f : FILE);
  322.    (* Sign on messages for listing file -- initialize *)
  323.  
  324.  
  325.    PROCEDURE WriteListLine (f : FILE; 
  326.                             AddrCnt, ObjOp, ObjSrc, ObjDest : LONG;
  327.                                nA,     nO,    nS,     nD    : CARDINAL);
  328.    (* Writes one line to the Listing file, Including Object Code *)
  329.  
  330.  
  331.    PROCEDURE WriteSymTab (f : FILE; NumSym : CARDINAL);
  332.    (* Lists symbol table in alphabetical order *)
  333.  
  334. END Listing.
  335. ------------------------------------------
  336. LISTING NINE
  337. DEFINITION MODULE Srecord;
  338. (* Creates Motorola S-records of program:        *)
  339. (*    S0 = header record,                        *)
  340. (*    S2 = code/data records (24 bit address),   *)
  341. (*    S8 = termination record (24 bit address).  *)
  342.  
  343.    FROM Files IMPORT
  344.       FILE;
  345.  
  346.    FROM LongNumbers IMPORT
  347.       LONG;
  348.  
  349.  
  350.    EXPORT QUALIFIED
  351.       StartSrec, WriteSrecLine, EndSrec;
  352.  
  353.  
  354.    PROCEDURE StartSrec (f : FILE; SourceFN : ARRAY OF CHAR);
  355.    (* Writes S0 record (HEADER) and initializes *)
  356.  
  357.    PROCEDURE WriteSrecLine (f : FILE; 
  358.                             AddrCnt, ObjOp, ObjSrc, ObjDest : LONG;
  359.                                nA,     nO,    nS,     nD    : CARDINAL);
  360.    (* Collects Object Code -- Writes an S2 record to file if line is full *)
  361.  
  362.    PROCEDURE EndSrec (f : FILE);
  363.    (* Finishes off any left-over (Partial) S2 line, *)
  364.    (* and then writes S8 record (TRAILER)           *)
  365.  
  366. END Srecord.
  367. --------------------------------
  368. LISITNG TEN
  369. MODULE X68000;
  370. (*------------------------------------------------------------------*)
  371. (*                                                                  *)
  372. (*                    MC68000 Cross Assembler                       *)
  373. (*            Copyright (c) 1985 by Brian R. Anderson               *)
  374. (*                                                                  *)
  375. (*   This program may be copied for personal, non-commercial use    *)
  376. (*   only, provided that the above copyright notice is included     *)
  377. (*   on all copies of the source code.  Copying for any other use   *)
  378. (*   without the consent of the author is prohibited.               *)  
  379. (*                                                                  *)
  380. (*------------------------------------------------------------------*)
  381.  
  382.    FROM Terminal IMPORT
  383.       WriteString, WriteLn, ReadString;
  384.  
  385.    FROM Files IMPORT
  386.       FILE, FileState, Open, Create, Write, Close;
  387.  
  388.    FROM Strings IMPORT
  389.       STRING, CompareStr, Assign, Concat, Length, Delete;
  390.  
  391.    IMPORT ASCII;
  392.  
  393.    FROM CmdLin2 IMPORT   (*  Access CP/M command line *)
  394.       ReadCmdLin;
  395.  
  396.    FROM LongNumbers IMPORT
  397.       LONG;
  398.  
  399.    FROM SymbolTable IMPORT
  400.       SortSymTab;
  401.  
  402.    FROM Parser IMPORT
  403.       TOKEN, OPERAND, LineCount, LineParts;
  404.  
  405.    FROM CodeGenerator IMPORT
  406.       LZero, AddrCnt, Pass2, BuildSymTable, AdvAddrCnt, GetObjectCode;
  407.  
  408.    FROM Listing IMPORT
  409.       StartListing, WriteListLine, WriteSymTab;
  410.  
  411.    FROM Srecord IMPORT
  412.       StartSrec, WriteSrecLine, EndSrec;
  413.  
  414.    FROM ErrorX68 IMPORT
  415.       ErrorCount, WriteErrorCount;
  416.  
  417.  
  418.  
  419.    TYPE
  420.       FileName = ARRAY [0..14] OF CHAR;
  421.  
  422.  
  423.    VAR
  424.       ArgC : CARDINAL;
  425.       ArgV : POINTER TO ARRAY [1..3] OF POINTER TO STRING;  (* Command Line *)
  426.       SourceFN, ListFN, SrecFN : FileName;
  427.       Source, List, Srec : FILE;
  428.       Label, OpCode : TOKEN;
  429.       SrcOp, DestOp : OPERAND;
  430.       EndFile : BOOLEAN;
  431.       NumSyms : CARDINAL;
  432.       ObjOp, ObjSrc, ObjDest : LONG;
  433.       nA, nO, nS, nD : CARDINAL;
  434.  
  435.  
  436.  
  437.    PROCEDURE MakeNames (VAR S, L, R : FileName);
  438.    (* builds names for Source, Listing & S-Record files *)
  439.  
  440.       VAR
  441.          T : FileName;   (* temporary work name *)
  442.          i, l : CARDINAL;
  443.  
  444.       BEGIN
  445.          L := '';   R := '';   (* set Listing & S-rec names to null *)
  446.  
  447.          i := 0;   l := 0;
  448.          WHILE (S[i] # 0C) AND (S[i] # ' ') DO
  449.             IF S[i] = '.' THEN   (* mark beginning of file extension *)
  450.                l := i;
  451.             END;
  452.             S[i] := CAP (S[i]);
  453.             INC (i);
  454.          END;
  455.       
  456.          IF S[i] = ' ' THEN
  457.             Delete (S, i, Length (S) - i);
  458.          END;
  459.  
  460.          Assign (S, T);
  461.          IF l = 0 THEN
  462.             Concat (T, ".ASM", S);
  463.          ELSE   
  464.             Delete (T, l, i - l);
  465.          END;
  466.  
  467.          Concat (T, ".LST", L);
  468.          Concat (T, ".S", R);
  469.       END MakeNames;
  470.  
  471.  
  472.  
  473.    PROCEDURE OpenFiles;
  474.       BEGIN
  475.          IF Open (Source, SourceFN) # FileOK THEN
  476.             WriteLn;
  477.             WriteString ("No Source File: ");   WriteString (SourceFN);   
  478.             WriteLn;
  479.             HALT;
  480.          END;
  481.  
  482.          IF Create (List, ListFN) # FileOK THEN   (* DOS may trap this *)
  483.             WriteLn;
  484.             WriteString ("Cannot create disk files!");   WriteLn;
  485.             HALT;
  486.          END;
  487.  
  488.          IF Create (Srec, SrecFN) # FileOK THEN
  489.             WriteLn;
  490.             WriteString ("Cannot create disk files!");   WriteLn;
  491.             HALT;
  492.          END;
  493.       END OpenFiles;
  494.  
  495.  
  496.  
  497.    PROCEDURE StartPass2;
  498.       BEGIN
  499.          IF (Close (Source) # FileOK) OR 
  500.           (Open (Source, SourceFN) # FileOK) THEN
  501.             WriteString ("Unable to 'Reset' Source file for 2nd Pass.");
  502.             WriteLn;
  503.             HALT;
  504.          END;
  505.          Pass2 := TRUE;   (* Pass2 IMPORTed from CodeGenerator *)
  506.          AddrCnt := LZero;   (* Assume ORG = 0 to start *)
  507.          ErrorCount := 0;   (* ErrorCount IMPORTed from ErrorX68 *)
  508.          LineCount := 0;   (* LineCount IMPORTed from Parser *)
  509.          EndFile := FALSE;
  510.       END StartPass2;
  511.  
  512.  
  513.  
  514.    PROCEDURE CloseFiles;
  515.       BEGIN
  516.          (*--------------------------------------------------------*)
  517.          (*                                                        *)
  518.          (*    Ctrl-Z written to files before closing              *)
  519.          (*    due to bug in "Files" module.   Remove these        *)
  520.          (*    before submitting listing for publication.          *)
  521.          (*                                                        *)
  522.          (*--------------------------------------------------------*)
  523.          Write (List, ASCII.sub);   Write (Srec, ASCII.sub);
  524.  
  525.          IF (Close (Source) # FileOK) 
  526.           OR (Close (List) # FileOK)
  527.            OR (Close (Srec) # FileOK) THEN
  528.             WriteString ("Error closing files...");   WriteLn;
  529.             HALT;
  530.          END;
  531.       END CloseFiles;
  532.  
  533.  
  534.  
  535. BEGIN   (* X68000 -- main program *)
  536.    ReadCmdLin (ArgC, ArgV);
  537.  
  538.    IF ArgC = 0 THEN
  539.       WriteLn; 
  540.       WriteString ("Enter Source Filename: ");
  541.       ReadString (SourceFN);
  542.       WriteLn;
  543.    ELSE
  544.       Assign (ArgV^[1]^, SourceFN);
  545.    END;
  546.  
  547.    MakeNames (SourceFN, ListFN, SrecFN);   
  548.  
  549.    OpenFiles;
  550.  
  551.    WriteLn;
  552.    WriteString ("                 68000 Cross Assembler");   WriteLn;
  553.    WriteString ("         Copyright (c) 1985 by Brian R. Anderson");
  554.    WriteLn;   WriteLn;
  555.    WriteString ("                 Assembling ");   WriteString (SourceFN);  
  556.    WriteLn;   WriteLn;   WriteLn;
  557.  
  558.  
  559. (*---
  560.     Begin Pass 1 
  561.                   ---*)
  562.    WriteString ("PASS 1");   WriteLn;
  563.    AddrCnt := LZero;   (* Assume ORG = 0 to start *)
  564.    EndFile := FALSE;
  565.  
  566.    REPEAT
  567.       LineParts (Source, EndFile, Label, OpCode, SrcOp, DestOp);
  568.       
  569.       BuildSymTable (AddrCnt, Label, OpCode, SrcOp, DestOp);
  570.  
  571.       AdvAddrCnt (AddrCnt);
  572.  
  573.    UNTIL EndFile OR (CompareStr (OpCode, "END") = 0);
  574.  
  575.  
  576. (*---
  577.    Begin Pass 2 
  578.                ---*)
  579.    WriteString ("PASS 2");   WriteLn;
  580.    StartPass2;   (* get Source file, Parser & ErrorX68 ready for 2nd pass *)
  581.    SortSymTab (NumSyms);
  582.    StartListing (List);
  583.    StartSrec (Srec, SourceFN);
  584.  
  585.    REPEAT
  586.       LineParts (Source, EndFile, Label, OpCode, SrcOp, DestOp);
  587.  
  588.       GetObjectCode (Label, OpCode,
  589.                      SrcOp,  DestOp, 
  590.                      AddrCnt, ObjOp, ObjSrc, ObjDest, 
  591.                      nA,      nO,    nS,     nD      );
  592.  
  593.       WriteListLine (List, AddrCnt, ObjOp, ObjSrc, ObjDest, nA, nO, nS, nD);
  594.  
  595.       WriteSrecLine (Srec, AddrCnt, ObjOp, ObjSrc, ObjDest, nA, nO, nS, nD); 
  596.       
  597.       AdvAddrCnt (AddrCnt);
  598.  
  599.    UNTIL EndFile OR (CompareStr (OpCode, "END") = 0);
  600.  
  601.    EndSrec (Srec);   (* Also: Finish off any partial line *)
  602.  
  603.    WriteErrorCount (List);   (* Error count output to Console & Listing file *)
  604.  
  605.    WriteSymTab (List, NumSyms);   (* Write Symbol Table to Listing File *)
  606.  
  607.    CloseFiles;
  608.  
  609. END X68000.
  610.  
  611. --------------------------------
  612.               LISTINGS CONTINUED- KEYWORD:MAY86
  613.  
  614.  
  615. LISTING ELEVEN
  616. IMPLEMENTATION MODULE LongNumbers;            
  617. (* Routines to handle HEX digits for the X68000 cross assembler. *)
  618. (* All but LongPut and LongWrite are limited to 8 digit numbers. *)
  619.  
  620.    FROM Files IMPORT
  621.       FILE;
  622.  
  623.    IMPORT Files;   (* Write *)
  624.  
  625.    IMPORT Terminal;   (* Write *)
  626.  
  627. (*---
  628. (* These objects are declared in the DEFINITION MODULE *)
  629.  
  630.    CONST
  631.       DIGITS = 8;
  632.       BASE = 16;
  633.  
  634.    TYPE
  635.       LONG = ARRAY [1..DIGITS] OF INTEGER;
  636.                                                     ---*)              
  637.  
  638.    CONST
  639.       Zero = 30H;
  640.       Nine = 39H;
  641.       hexA = 41H;
  642.       hexF = 46H;
  643.  
  644.  
  645.  
  646.    PROCEDURE LongClear (VAR A : LONG);
  647.    (* Sets A to Zero *)
  648.  
  649.       VAR
  650.          i : CARDINAL;
  651.  
  652.       BEGIN
  653.          FOR i := 1 TO DIGITS DO
  654.             A[i] := 0;
  655.          END;
  656.       END LongClear;
  657.  
  658.  
  659.  
  660.    PROCEDURE LongAdd (A, B : LONG; VAR Result : LONG);
  661.    (* Add two LONGs, giving Result *)
  662.  
  663.       VAR
  664.          Carry : INTEGER;
  665.          i : CARDINAL;
  666.  
  667.       BEGIN
  668.          Carry := 0;
  669.          FOR i := 1 TO DIGITS DO
  670.             Result[i] := (A[i] + Carry) + B[i];
  671.             IF Result[i] >= BASE THEN
  672.                Result[i] := Result[i] - BASE;
  673.                Carry := 1;
  674.             ELSE
  675.                Carry := 0;
  676.             END;
  677.          END;
  678.       END LongAdd;
  679.  
  680.  
  681.  
  682.    PROCEDURE LongSub (A, B : LONG; VAR Result : LONG);
  683.    (* Subtract two LONGs (A - B), giving Result *)
  684.  
  685.       VAR
  686.          Borrow : INTEGER;
  687.          i : CARDINAL;
  688.  
  689.       BEGIN
  690.          Borrow := 0;
  691.          FOR i := 1 TO DIGITS DO
  692.             Result[i] := (A[i] - Borrow) - B[i];
  693.             IF Result[i] < 0 THEN
  694.                Result[i] := Result[i] + BASE;
  695.                Borrow := 1;
  696.             ELSE
  697.                Borrow := 0;
  698.             END;
  699.          END;
  700.       END LongSub;
  701.  
  702.  
  703.  
  704.    PROCEDURE CardToLong (n : CARDINAL; VAR A : LONG);
  705.    (* Converts CARDINALs to LONGs *)
  706.  
  707.       VAR
  708.          i : CARDINAL;
  709.  
  710.       BEGIN
  711.          LongClear (A);
  712.  
  713.          i := 1;
  714.          REPEAT
  715.             A[i] := n MOD BASE;
  716.             INC (i);
  717.             n := n DIV BASE;
  718.          UNTIL n = 0;
  719.       END CardToLong;
  720.  
  721.  
  722.  
  723.    PROCEDURE LongToCard (A : LONG; VAR n : CARDINAL) : BOOLEAN;
  724.    (* Converts LONG TO CARDINAL, returns FALSE if conversion impossible *)
  725.       BEGIN
  726.          n := (A[4] * 4096) + (A[3] * 256) + (A[2] * 16) + A[1];
  727.          RETURN ((A[5] = 0) AND (A[6] = 0) AND (A[7] = 0) AND (A[8] = 0));
  728.       END LongToCard;
  729.  
  730.  
  731.  
  732.    PROCEDURE LongToInt (A : LONG; VAR n : INTEGER) : BOOLEAN;
  733.    (* Converts LONG to INTEGER, returns FALSE if conversion impossible *)
  734.  
  735.       VAR
  736.          TempC : CARDINAL;
  737.          Neg : BOOLEAN;
  738.  
  739.       BEGIN
  740.          IF (A[5] = 0) AND (A[6] = 0) AND (A[7] = 0) AND (A[8] = 0) THEN
  741.             Neg := FALSE;
  742.          ELSIF (A[5] = 15) AND (A[6] = 15) AND (A[7] = 15) AND (A[8] = 15) THEN
  743.             Neg := TRUE;
  744.          ELSE
  745.             RETURN FALSE;   (* Out of INTEGER range *)
  746.          END;
  747.       
  748.          TempC := (A[4] * 4096) + (A[3] * 256) + (A[2] * 16) + A[1];
  749.          IF ((TempC <= 32767) AND (NOT Neg)) OR ((TempC > 32767) AND Neg) THEN
  750.             n := INTEGER (TempC);
  751.             RETURN TRUE;
  752.          ELSE
  753.             RETURN FALSE;
  754.          END;
  755.       END LongToInt;
  756.  
  757.  
  758.  
  759.    PROCEDURE LongInc (VAR A : LONG; n : CARDINAL);
  760.    (* Increment LONG by n *)
  761.  
  762.       VAR
  763.          T : LONG;
  764.  
  765.       BEGIN
  766.          CardToLong (n, T);
  767.          LongAdd (A, T, A);
  768.       END LongInc;
  769.  
  770.  
  771.  
  772.    PROCEDURE LongDec (VAR A : LONG; n : CARDINAL);
  773.    (* Decrement LONG by n *)
  774.  
  775.       VAR
  776.          T : LONG;
  777.  
  778.       BEGIN
  779.          CardToLong (n, T);
  780.          LongSub (A, T, A);
  781.       END LongDec;
  782.  
  783.  
  784.  
  785.    PROCEDURE LongCompare (A, B : LONG) : INTEGER;
  786.    (* Returns: 0 if A = B, -1 if A < B, +1 if A > B *)
  787.  
  788.       VAR
  789.          i : CARDINAL;
  790.  
  791.       BEGIN
  792.          i := DIGITS;
  793.          WHILE (i > 0) AND (A[i] = B[i]) DO
  794.             DEC (i);
  795.          END;
  796.          
  797.          IF i = 0 THEN
  798.             RETURN 0;
  799.          ELSIF A[i] < B[i] THEN
  800.             RETURN -1;
  801.          ELSIF A[i] > B[i] THEN
  802.             RETURN +1;
  803.          ELSE
  804.             (* Impossible! *)
  805.          END;
  806.       END LongCompare;
  807.  
  808.  
  809.  
  810.    PROCEDURE GetDigit (n : INTEGER) : CHAR;
  811.    (* Function returning HEX character corresponding to digit *) 
  812.  
  813.       BEGIN
  814.          IF (n >= 0) AND (n <= 9) THEN
  815.             RETURN CHR (CARDINAL (n) + Zero);
  816.          ELSIF (n >= 10) AND (n <= 15) THEN
  817.             RETURN CHR ((CARDINAL (n) - 10) + hexA);
  818.          ELSE
  819.             RETURN '*';
  820.          END;
  821.       END GetDigit;
  822.  
  823.  
  824.  
  825.    PROCEDURE LongPut (f : FILE; A : ARRAY OF INTEGER; Size : CARDINAL);
  826.    (* Put LONG number in FILE f *)
  827.    
  828.       VAR
  829.          i : CARDINAL;
  830.    
  831.       BEGIN
  832.          IF Size = 0 THEN
  833.             RETURN;
  834.          END;
  835.  
  836.          DEC (Size);   (* adjust for zero-based array *)
  837.          IF Size > HIGH (A) THEN
  838.             Size := HIGH (A);
  839.          END;
  840.  
  841.          FOR i := Size TO 0 BY -1 DO
  842.             Files.Write (f, GetDigit (A[i]));
  843.          END;
  844.       END LongPut;
  845.  
  846.  
  847.  
  848.    PROCEDURE LongWrite (A : ARRAY OF INTEGER; Size : CARDINAL);
  849.    (* Write LONG number to console screen *)
  850.  
  851.       VAR
  852.          i : CARDINAL;
  853.    
  854.       BEGIN
  855.          IF Size = 0 THEN
  856.             RETURN;
  857.          END;
  858.  
  859.          DEC (Size);
  860.          IF Size > HIGH (A) THEN
  861.             Size := HIGH (A);
  862.          END;
  863.  
  864.          FOR i := Size TO 0 BY -1 DO
  865.             Terminal.Write (GetDigit (A[i]));
  866.          END;
  867.       END LongWrite;
  868.  
  869.  
  870.  
  871.    PROCEDURE IsHEX (c : CHAR) : BOOLEAN;
  872.    (* checks if c is one of 0..9, A..F *)
  873.    
  874.       VAR
  875.          C : CARDINAL;
  876.  
  877.       BEGIN
  878.          C := ORD (CAP (c));
  879.       
  880.          RETURN (((C >= Zero) AND (C <= Nine)) OR
  881.                  ((C >= hexA) AND (C <= hexF)));
  882.       END IsHEX;
  883.  
  884.  
  885.    
  886.    PROCEDURE GetHEX (c : CHAR) : INTEGER;
  887.    (* returns HEX value of character *)
  888.  
  889.       VAR
  890.          C : CARDINAL;
  891.  
  892.       BEGIN
  893.          C := ORD (CAP (c));
  894.          IF C < hexA THEN
  895.             RETURN INTEGER (C - Zero);
  896.          ELSE
  897.             RETURN 10 + INTEGER (C - hexA);
  898.          END;
  899.       END GetHEX;
  900.  
  901.  
  902.  
  903.    PROCEDURE StringToLong (S : ARRAY OF CHAR; VAR A : LONG) : BOOLEAN;
  904.    (* Converts a string (in HEX) into a LONG *)
  905.  
  906.       VAR
  907.          i, j : CARDINAL;
  908.  
  909.       BEGIN
  910.          LongClear (A);
  911.  
  912.          IF S[0] # '$' THEN
  913.             RETURN FALSE;   (* not a HEX string *)
  914.          ELSE
  915.             j := 1;
  916.             WHILE (IsHEX (S[j])) AND (j <= DIGITS) DO
  917.                INC (j);
  918.             END;     
  919.  
  920.             DEC (j);   (* gone too far, so back up one *)
  921.             i := 1;
  922.             WHILE j > 0 DO
  923.                A[i] := GetHEX (S[j]);
  924.                INC (i);   DEC (j);
  925.             END;       
  926.  
  927.             RETURN (i > 1);
  928.          END;
  929.       END StringToLong;
  930.  
  931.  
  932.  
  933.    PROCEDURE AddrBoundL (VAR A : LONG);
  934.    (* Forces A to a long word boundary *)
  935.       BEGIN
  936.          WHILE NOT (CARDINAL (A[1]) IN {0, 4, 8, 12}) DO
  937.             LongInc (A, 1);
  938.          END;
  939.       END AddrBoundL;
  940.  
  941.  
  942.  
  943.    PROCEDURE AddrBoundW (VAR A : LONG);
  944.    (* Forces A to a word boundary *)
  945.       BEGIN
  946.          WHILE NOT (CARDINAL (A[1]) IN {0, 2, 4, 6, 8, 10, 12, 14}) DO
  947.             LongInc (A, 1);
  948.          END;
  949.       END AddrBoundW;
  950.  
  951. END LongNumbers.
  952. ----------------------------------------
  953. LISTING TWELVE
  954. IMPLEMENTATION MODULE CmdLin2;
  955. (* Parses command line - returns pointer to an array of pointer to strings *)
  956.  
  957.    FROM SYSTEM IMPORT
  958.       ADDRESS, ADR;
  959.  
  960.  
  961.    CONST
  962.       MAXARGS = 5;
  963.  
  964.  
  965.    VAR
  966.       CommandLine[80H] : ARRAY [0..7FH] OF CHAR;
  967.       Arguments : ARRAY [0..MAXARGS - 1] OF ADDRESS;
  968.  
  969.  
  970.    PROCEDURE ReadCmdLin (VAR ArgC : CARDINAL; VAR ArgV : ADDRESS);
  971.    (* Gives count of items in command line, and an array of pointer to them *)
  972.  
  973.       VAR
  974.          i, C : CARDINAL;
  975.  
  976.       BEGIN
  977.          IF ORD (CommandLine[0]) = 0 THEN
  978.             ArgC := 0;   (* Nothing in Command Tail Buffer *)
  979.             ArgV := NIL;
  980.          ELSE
  981.             i := 1;   C := 0;
  982.  
  983.             LOOP
  984.                WHILE CommandLine[i] = ' ' DO   (* Skip Blanks *)
  985.                   INC (i);
  986.                END;
  987.       
  988.                IF CommandLine[i] = 0C THEN   (* end of tail buffer *)
  989.                   EXIT;
  990.                ELSE
  991.                   Arguments[C] := ADR (CommandLine[i]);
  992.                   INC (C);
  993.                   IF C = MAXARGS THEN
  994.                      EXIT;
  995.                   END;
  996.                END;
  997.  
  998.                WHILE CommandLine[i] # ' ' DO   (* Advance to next Argument *)
  999.                   INC (i);
  1000.                   IF CommandLine[i] = 0C THEN
  1001.                      EXIT;
  1002.                   END;
  1003.                END;
  1004.  
  1005.                CommandLine[i] := 0C;   (* Terminate Argument *)
  1006.                INC (i);
  1007.             END;   (* LOOP *)
  1008.  
  1009.             CommandLine[0] := 0C;   (* Command Tail must only be used once *)
  1010.             ArgC := C;
  1011.             ArgV := ADR (Arguments);      
  1012.          END;
  1013.       END ReadCmdLin;
  1014.  
  1015. END CmdLin2.
  1016. ----------------------------------------
  1017. LISITNG THIRTEEN
  1018. IMPLEMENTATION MODULE Parser;
  1019. (* Reads the Source file, and splits each *)
  1020. (* line into Label, OpCode & Operand(s).  *)
  1021.  
  1022.    FROM Strings IMPORT
  1023.       STRING;
  1024.  
  1025.    FROM Files IMPORT
  1026.       FILE, EOF, Read;
  1027.  
  1028.    FROM ErrorX68 IMPORT
  1029.       ErrorType, Error;
  1030.  
  1031.    IMPORT ASCII;
  1032.  
  1033.  
  1034. (*---
  1035. (* These objects are declared in the DEFINITION MODULE *)
  1036.    CONST
  1037.       TokenSize = 8;
  1038.       OperandSize = 20;
  1039.  
  1040.    TYPE
  1041.       TOKEN = ARRAY [0..TokenSize] OF CHAR;
  1042.       OPERAND = ARRAY [0..OperandSize] OF CHAR;
  1043.  
  1044.    VAR
  1045.       OpLoc, SrcLoc, DestLoc : CARDINAL;   (* location of line parts *)
  1046.       Line : STRING;
  1047.       LineCount : CARDINAL;
  1048.                                                                   ---*)
  1049.  
  1050.  
  1051.    PROCEDURE GetLine (f : FILE; VAR EndFile : BOOLEAN);
  1052.    (* Inputs a Line -- up to 80 characters ending in cr/lf -- from a file. *)
  1053.  
  1054.       CONST
  1055.          MAXLINE = 80;
  1056.  
  1057.       VAR
  1058.          i : CARDINAL;
  1059.          ch : CHAR;
  1060.  
  1061.       PROCEDURE Get (VAR c : CHAR) : CHAR;
  1062.          BEGIN
  1063.             IF NOT EOF (f) THEN
  1064.                Read (f, c);
  1065.                RETURN c;
  1066.             ELSE
  1067.                EndFile := TRUE;
  1068.             END;
  1069.          END Get;
  1070.       
  1071.       BEGIN   (* GetLine *)
  1072.          EndFile := FALSE;
  1073.  
  1074.          i := 0;
  1075.          WHILE (i < MAXLINE) AND (Get (ch) # ASCII.lf) AND (NOT EndFile) DO
  1076.             Line[i] := ch;
  1077.             INC (i);
  1078.          END;
  1079.          
  1080.          IF Line[i - 1] = ASCII.cr THEN   (* Strip cr/lf - terminate with 0C *)
  1081.             Line[i - 1] := 0C;
  1082.          ELSE
  1083.             Line[i] := 0C;
  1084.          END;
  1085.  
  1086.          INC (LineCount);
  1087.       END GetLine;
  1088.  
  1089.  
  1090.    
  1091.    PROCEDURE SplitLine (VAR Label, OpCode : TOKEN; 
  1092.                         VAR SrcOp, DestOp : OPERAND);
  1093.    (* Separates TOKENs & OPERANDs from Line. *)
  1094.  
  1095.       CONST
  1096.          Quote = 47C;
  1097.          StringMAX = 12;
  1098.       
  1099.       VAR
  1100.          i, j : CARDINAL;
  1101.          ParCnt : INTEGER;   (* Tracks open parentheses *)
  1102.          c : CHAR;
  1103.          InQuotes : BOOLEAN;
  1104.  
  1105.       PROCEDURE Cap (ch : CHAR) : CHAR;
  1106.          BEGIN
  1107.             IF InQuotes THEN
  1108.                RETURN (ch);
  1109.             ELSE
  1110.                RETURN CAP (ch);
  1111.             END;
  1112.          END Cap;
  1113.  
  1114.       PROCEDURE White (ch : CHAR) : BOOLEAN;
  1115.          BEGIN
  1116.             RETURN ((ch = ASCII.ht) OR (ch = ' '));
  1117.          END White;
  1118.  
  1119.       PROCEDURE Delimiter (ch : CHAR) : BOOLEAN;
  1120.          BEGIN
  1121.             RETURN ((NOT InQuotes) AND 
  1122.                    ((ch = ASCII.ht) OR (ch = ' ') OR (ch = 0C)));
  1123.          END Delimiter;
  1124.  
  1125.       PROCEDURE OpDelimiter (ch : CHAR) : BOOLEAN;
  1126.          BEGIN
  1127.             RETURN ((NOT InQuotes) AND (ch = ',') AND (ParCnt = 0));
  1128.          END OpDelimiter;
  1129.  
  1130.       PROCEDURE Done (ch : CHAR) : BOOLEAN;
  1131.       (* look for start of comment or NULL terminator *)
  1132.          BEGIN
  1133.             RETURN ((ch = ';') OR (ch = 0C) OR ((ch = '*') AND (i = 0)));
  1134.          END Done;
  1135.  
  1136.    
  1137.       BEGIN   (* SplitLine *)
  1138.          i := 0;
  1139.          InQuotes := FALSE;
  1140.  
  1141.          IF Done (Line[i]) THEN   (* look for blank or all-comment line *)
  1142.             RETURN;
  1143.          END;
  1144.  
  1145.          IF White (Line[i]) THEN
  1146.             INC (i);
  1147.             WHILE White (Line[i]) DO
  1148.                INC (i);   (* Skip spaces & tabs *)
  1149.             END;
  1150.          ELSE   (* Found a Label *)
  1151.             j := 0;
  1152.             c := Line[i];
  1153.             WHILE (NOT Delimiter (c)) AND (j < TokenSize) DO
  1154.                Label[j] := CAP (c);
  1155.                INC (i);   INC (j);
  1156.                c := Line[i];
  1157.             END;
  1158.             Label[j] := 0C;   (* terminate Label string *)
  1159.             IF j = TokenSize THEN
  1160.                Error (i, TooLong);
  1161.             END;
  1162.             WHILE NOT Delimiter (Line[i]) DO 
  1163.                INC (i);   (* Skip remainder of Too-Long Token *)
  1164.             END;
  1165.          END;
  1166.  
  1167.          WHILE White (Line[i]) DO
  1168.             INC (i);
  1169.          END;
  1170.  
  1171.          IF Done (Line[i]) THEN
  1172.             RETURN;
  1173.          ELSE   (* Found an OpCode *)
  1174.             OpLoc := i;
  1175.             j := 0;
  1176.             c := Line[i];
  1177.             WHILE (NOT Delimiter (c)) AND (j < TokenSize) DO
  1178.                OpCode[j] := CAP (c);
  1179.                INC (i);   INC (j);
  1180.                c := Line[i];
  1181.             END;
  1182.             OpCode[j] := 0C;  
  1183.             IF j = TokenSize THEN
  1184.                Error (i, TooLong);
  1185.             END;
  1186.             WHILE NOT Delimiter (Line[i]) DO 
  1187.                INC (i);   (* Skip remainder of Too-Long Token *)
  1188.             END;
  1189.          END;
  1190.  
  1191.          WHILE White (Line[i]) DO
  1192.             INC (i);
  1193.          END;
  1194.  
  1195.          IF Done (Line[i]) THEN
  1196.             RETURN;
  1197.          ELSE   (* Found 1st Operand *)
  1198.             SrcLoc := i;
  1199.             j := 0;
  1200.             ParCnt := 0;
  1201.             c := Line[i];
  1202.             IF c = Quote THEN   (* String Constant *)
  1203.                SrcOp[j] := c;   
  1204.                INC (i);   INC (j);
  1205.                REPEAT
  1206.                   c := Line[i];
  1207.                   SrcOp[j] := c;
  1208.                   INC (i);   INC (j);
  1209.                UNTIL (c = Quote) OR (j > StringMAX) OR (c = 0C);
  1210.                SrcOp[j] := 0C;
  1211.                IF j > StringMAX THEN
  1212.                   Error (i, TooLong);
  1213.                END;
  1214.                RETURN;  (* second operand not allowed after string constant *)
  1215.             ELSE   (* Normal Operand *)
  1216.                WHILE (NOT Delimiter (c)) 
  1217.                 AND (NOT OpDelimiter (c)) 
  1218.                  AND (j < OperandSize) DO
  1219.                   IF c = Quote THEN
  1220.                      InQuotes := NOT InQuotes;   (* Toggle Switch *)
  1221.                   END;
  1222.                   IF NOT InQuotes THEN
  1223.                      IF c = '(' THEN
  1224.                         INC (ParCnt);
  1225.                      END;
  1226.                      IF c = ')' THEN
  1227.                         DEC (ParCnt);
  1228.                      END;
  1229.                   END;
  1230.                   SrcOp[j] := Cap (c);   (* Switched CAP function *)
  1231.                   INC (i);   INC (j);
  1232.                   c := Line[i];
  1233.                END;
  1234.                SrcOp[j] := 0C;
  1235.                IF j = OperandSize THEN
  1236.                   Error (i, TooLong);
  1237.                END;
  1238.             END;
  1239.             WHILE (NOT Delimiter (Line[i])) AND (NOT OpDelimiter (Line[i])) DO 
  1240.                INC (i);   (* Skip remainder of Too-Long Operand *)
  1241.             END;
  1242.          END;
  1243.  
  1244.          IF NOT OpDelimiter (Line[i]) THEN
  1245.             RETURN;   (* because only one OPERAND *)
  1246.          ELSE   (* Found 2nd Operand *)
  1247.             INC (i);   (* Skip OpDelimiter (comma) *)
  1248.             DestLoc := i;
  1249.             j := 0;
  1250.             c := Line[i];
  1251.             WHILE (NOT Delimiter (c)) AND (j < OperandSize) DO
  1252.                DestOp[j] := CAP (c);
  1253.                INC (i);   INC (j);
  1254.                c := Line[i];
  1255.             END;
  1256.             DestOp[j] := 0C;
  1257.             IF j = OperandSize THEN
  1258.                Error (i, TooLong);
  1259.             END;
  1260.          END;
  1261.       END SplitLine;
  1262.  
  1263.  
  1264.  
  1265.    PROCEDURE LineParts (f : FILE; VAR EndFile : BOOLEAN;
  1266.                         VAR Label, OpCode : TOKEN; 
  1267.                         VAR SrcOp, DestOp : OPERAND);
  1268.    (* Reads line, breaks into tokens, on-passes to symbol & code generators *)
  1269.  
  1270.       BEGIN
  1271.          Line := "";
  1272.          GetLine (f, EndFile);   (* read a line from the file *)
  1273.  
  1274.          Label := "";   OpCode := "";   SrcOp := "";   DestOp := "";
  1275.          IF EndFile THEN
  1276.             Error (0, EndErr);
  1277.          ELSE
  1278.             SplitLine (Label, OpCode, SrcOp, DestOp);
  1279.          END;
  1280.       END LineParts;   
  1281.  
  1282.  
  1283.  
  1284. BEGIN   (* MODULE Initialization *)
  1285.    OpLoc := 0;   SrcLoc := 0;   DestLoc := 0;   LineCount := 0; 
  1286. END Parser.
  1287. ----------------------------------------
  1288. LISTING FOURTEEN
  1289. IMPLEMENTATION MODULE SymbolTable;
  1290. (* Initializes symbol table.  Maintains list of all labels, *)
  1291. (* along with their values.  Provides access to the list.   *)
  1292.  
  1293.    FROM LongNumbers IMPORT
  1294.       LONG, LongClear;
  1295.  
  1296.    FROM Parser IMPORT
  1297.       TOKEN;
  1298.  
  1299.    FROM Strings IMPORT
  1300.       CompareStr;
  1301.  
  1302.  
  1303.    CONST
  1304.       MAXSYM = 500;   (* Maximum entries in Symbol Table *)
  1305.  
  1306.  
  1307.    TYPE
  1308.       SYMBOL = RECORD
  1309.                   Name : TOKEN;
  1310.                   Value : LONG;
  1311.                END;
  1312.  
  1313.    VAR
  1314.       SymTab : ARRAY [1..MAXSYM] OF SYMBOL;
  1315.       Next : CARDINAL;   (* Array index into next entry in Symbol Table *)
  1316.       Top : INTEGER;   (* Last used array position as seen by Sort *)
  1317.  
  1318.  
  1319.  
  1320.    PROCEDURE FillSymTab (Label : TOKEN; Value : LONG; VAR Full : BOOLEAN);
  1321.    (* Add a symbol to the table *)
  1322.       BEGIN
  1323.          IF Next <= MAXSYM THEN
  1324.             SymTab[Next].Name := Label;
  1325.             SymTab[Next].Value := Value;
  1326.             INC (Next);
  1327.             Full := FALSE;
  1328.          ELSE
  1329.             Full := TRUE;
  1330.          END;
  1331.       END FillSymTab;
  1332.  
  1333.  
  1334.  
  1335.    PROCEDURE SortSymTab (VAR NumSyms : CARDINAL);
  1336.    (* Sort symbols into alphabetical order *)
  1337.  
  1338.       VAR
  1339.          i, j, gap : INTEGER;   (* Shell Sort causes j to go negative *)
  1340.          Temp : SYMBOL;
  1341.  
  1342.       PROCEDURE Swap;
  1343.          BEGIN
  1344.             Temp := SymTab[j];
  1345.             SymTab[j] := SymTab[j + gap];
  1346.             SymTab[j + gap] := Temp;
  1347.          END Swap;
  1348.  
  1349.       BEGIN   (* Sort *)
  1350.          Top := Next - 1;
  1351.  
  1352.          gap := (Top + 1) DIV 2;
  1353.          WHILE gap > 0 DO
  1354.             i := gap;
  1355.             WHILE i <= Top DO
  1356.                j := i - gap;
  1357.                WHILE j >= 1 DO
  1358.                   IF CompareStr (SymTab[j].Name, SymTab[j + gap].Name) > 0 THEN
  1359.                      Swap;
  1360.                   END;
  1361.                   j := j - gap;
  1362.                END;
  1363.                INC (i);
  1364.             END;
  1365.             gap := gap DIV 2;
  1366.          END;
  1367.  
  1368.          NumSyms := Top;
  1369.       END SortSymTab;
  1370.  
  1371.  
  1372.  
  1373.    PROCEDURE ReadSymTab (LABEL : ARRAY OF CHAR; 
  1374.                          VAR Value : LONG; VAR Duplicate : BOOLEAN) : BOOLEAN;
  1375.    (* Passes Value of Label to calling program -- returns FALSE if the *)
  1376.    (* Label is not defined.  Also checks for Multiply Defined Symbols  *)
  1377.  
  1378.       CONST
  1379.          GoLower = -1;
  1380.          GoHigher = +1;
  1381.  
  1382.       VAR
  1383.          i, j, mid : INTEGER;
  1384.          Search : INTEGER;
  1385.          Found : BOOLEAN;
  1386.          c : CHAR;
  1387.          Label : TOKEN;         
  1388.  
  1389.       BEGIN
  1390.          LongClear (Value);
  1391.          Duplicate := FALSE;
  1392.  
  1393.          i := 0;
  1394.          REPEAT
  1395.             c := LABEL[i];
  1396.             Label[i] := c;
  1397.             INC (i);
  1398.          UNTIL (c = 0C) OR (i > 8);
  1399.  
  1400.          IF c # 0C THEN   (* Operand label too long --> Undefined *)
  1401.             RETURN FALSE;
  1402.          END;
  1403.  
  1404.          i := 1;
  1405.          j := Top;
  1406.          Found := FALSE;
  1407.  
  1408.          REPEAT   (* Binary search *)
  1409.             mid := (i + j) DIV 2;
  1410.             Search := CompareStr (Label, SymTab[mid].Name);
  1411.  
  1412.             IF Search = GoLower THEN
  1413.                j := mid - 1;
  1414.             ELSIF Search = GoHigher THEN
  1415.                i := mid + 1;
  1416.             ELSE   (* Got It! *)
  1417.                Found := TRUE;
  1418.             END;
  1419.          UNTIL (j < i) OR Found;
  1420.  
  1421.          IF Found THEN
  1422.             IF mid > 1 THEN
  1423.                IF CompareStr (SymTab[mid].Name, SymTab[mid - 1].Name) = 0 THEN
  1424.                   Duplicate := TRUE;   (* Multiply Defined Symbol *)
  1425.                END;
  1426.             END;
  1427.             IF mid < Top THEN
  1428.                IF CompareStr (SymTab[mid].Name, SymTab[mid + 1].Name) = 0 THEN
  1429.                   Duplicate := TRUE;   (* Multiply Defined Symbol *)
  1430.                END;
  1431.             END;
  1432.  
  1433.             Value := SymTab[mid].Value;
  1434.             RETURN TRUE;
  1435.          ELSE
  1436.             RETURN FALSE;
  1437.          END;
  1438.       END ReadSymTab;
  1439.  
  1440.  
  1441.  
  1442.    PROCEDURE ListSymTab (i : CARDINAL; VAR Label : TOKEN; VAR Value : LONG);
  1443.    (* Returns the i-th item in the symbol table *)
  1444.       BEGIN
  1445.          IF i < Next THEN
  1446.             Label := SymTab[i].Name;
  1447.             Value := SymTab[i].Value;
  1448.          END;
  1449.       END ListSymTab;
  1450.       
  1451.  
  1452.  
  1453. BEGIN   (* MODULE Initialization *)
  1454.    FOR Next := 1 TO MAXSYM DO
  1455.       SymTab[Next].Name := "";
  1456.       LongClear (SymTab[Next].Value);
  1457.    END;
  1458.  
  1459.    Top := 0;
  1460.    Next := 1;
  1461. END SymbolTable.
  1462. ----------------------------------------
  1463. LISTING FIFTEEN
  1464. IMPLEMENTATION MODULE OperationCodes;
  1465. (* Initializes lookup table for Mnemonic OpCodes.  Searches the table *)
  1466. (* and returns the bit pattern along with address mode information.   *)
  1467.  
  1468.    FROM Files IMPORT
  1469.       FILE, FileState, Open, ReadRec, Close;
  1470.  
  1471.    FROM Terminal IMPORT
  1472.       WriteString, WriteLn;
  1473.  
  1474.    FROM Strings IMPORT
  1475.       STRING, CompareStr;
  1476.  
  1477.    FROM Parser IMPORT
  1478.       TOKEN;
  1479.  
  1480.    FROM ErrorX68 IMPORT
  1481.       ErrorType, Error;
  1482.  
  1483.  
  1484.    CONST
  1485.       FIRST = 1;       (* First 68000 OpCode *)
  1486.       LAST = 118;      (* Last 68000 OpCode *)
  1487.  
  1488.  
  1489. (*---
  1490. (* These objects are declared in the DEFINITION MODULE *)
  1491.  
  1492.    TYPE
  1493.       ModeTypeA = (RegMem3,      (* 0 = Register, 1 = Memory *)
  1494.                    Ry02,         (* Register Rx -- Bits 0-2 *)
  1495.                    Rx911,        (* Register Ry -- Bits 9-11 *)
  1496.                    Data911,      (* Immediate Data -- Bits 9-11 *)
  1497.                    CntR911,      (* Count Register or Immediate Data *)
  1498.                    Brnch,        (* Relative Branch *)
  1499.                    DecBr,        (* Decrement and Branch *)
  1500.                    Data03,       (* Used for VECT only *)
  1501.                    Data07,       (* MOVEQ *)
  1502.                    OpM68D,       (* Data *)
  1503.                    OpM68A,       (* Address *)
  1504.                    OpM68C,       (* Compare *)
  1505.                    OpM68X,       (* XOR *)
  1506.                    OpM68S,       (* Sign Extension *)
  1507.                    OpM68R,       (* Register/Memory *)    
  1508.                    OpM37);       (* Exchange Registers *)
  1509.                    
  1510.       ModeTypeB = (Bit811,       (* BIT operations - bits 8/11 as switch *)
  1511.                    Size67,       (* 00 = Byte, 01 = Word, 10 = Long *)
  1512.                    Size6,        (* 0 = Word, 1 = Long *)
  1513.                    Size1213A,    (* 01 = Byte, 11 = Word, 10 = Long *)
  1514.                    Size1213,     (* 11 = Word, 10 = Long *)
  1515.                    Exten,        (* OpCode extension required *)
  1516.                    EA05a,        (* Effective Address - ALL *)
  1517.                    EA05b,        (* Less 1 *)
  1518.                    EA05c,        (* Less 1, 11 *)
  1519.                    EA05d,        (* Less 9, 10, 11 *)
  1520.                    EA05e,        (* Less 1, 9, 10, 11 *)
  1521.                    EA05f,        (* Less 0, 1, 3, 4, 11 *)
  1522.                    EA05x,        (* Dual mode - OR/AND *)
  1523.                    EA05y,        (* Dual mode - ADD/SUB *)
  1524.                    EA05z,        (* Dual mode - MOVEM *)
  1525.                    EA611);       (* Used only by MOVE *)
  1526.                    
  1527.       ModeA = SET OF ModeTypeA;
  1528.       ModeB = SET OF ModeTypeB;
  1529.  
  1530.                                                             ---*)
  1531.    TYPE
  1532.       TableRecord = RECORD
  1533.                        Mnemonic : TOKEN;
  1534.                        Op : BITSET;
  1535.                        AddrModeA : ModeA;
  1536.                        AddrModeB : ModeB;
  1537.                     END;
  1538.  
  1539.  
  1540.    VAR
  1541.       Table68K : ARRAY [FIRST..LAST] OF TableRecord;
  1542.       i : CARDINAL;   (* index variable for initializing Table68K *)
  1543.       f : FILE;
  1544.  
  1545.  
  1546.    PROCEDURE Instructions (MnemonSym : TOKEN; 
  1547.                            OpLoc : CARDINAL; VAR Op : BITSET; 
  1548.                            VAR AddrModeA : ModeA; VAR AddrModeB : ModeB);
  1549.    (* Uses lookup table to find addressing mode & bit pattern of opcode. *)
  1550.  
  1551.       CONST
  1552.          GoLower = -1;
  1553.          GoHigher = +1;
  1554.  
  1555.       VAR
  1556.          Top, Bottom, Look : CARDINAL;   (* index to Op-code table *)
  1557.          Found : BOOLEAN;
  1558.          Search : INTEGER;
  1559.  
  1560.       BEGIN
  1561.          Bottom := FIRST;
  1562.          Top := LAST;
  1563.          Found := FALSE;
  1564.          
  1565.          REPEAT   (* Binary Search *)
  1566.             Look := (Bottom + Top) DIV 2;
  1567.             Search := CompareStr (MnemonSym, Table68K[Look].Mnemonic);
  1568.            
  1569.             IF Search = GoLower THEN
  1570.                Top := Look - 1;
  1571.             ELSIF Search = GoHigher THEN
  1572.                Bottom := Look + 1;
  1573.             ELSE   (* Got It! *)
  1574.                Found := TRUE;
  1575.             END;
  1576.          UNTIL (Top < Bottom) OR Found;
  1577.  
  1578.          IF Found THEN
  1579.             (* Return the instruction, mode, and address restristictions *)
  1580.             Op := Table68K[Look].Op;
  1581.             AddrModeA := Table68K[Look].AddrModeA;
  1582.             AddrModeB := Table68K[Look].AddrModeB;
  1583.          ELSE
  1584.             Error (OpLoc, NoCode);
  1585.          END;
  1586.       END Instructions;
  1587.  
  1588.  
  1589. BEGIN   (* MODULE Initialization *)
  1590.    IF Open (f, "OPCODE.DAT") # FileOK THEN
  1591.       WriteString ("Can't Find 'OPCODE.DAT'.");
  1592.       WriteLn;
  1593.       HALT;
  1594.    END;
  1595.  
  1596.    FOR i := FIRST TO LAST DO
  1597.       ReadRec (f, Table68K[i]);
  1598.    END;
  1599.  
  1600.    IF Close (f) # FileOK THEN
  1601.       (* Don't worry about it! *)
  1602.    END;
  1603. END OperationCodes.
  1604. ----------------------------------------
  1605. LISTING SIXTEEN
  1606. MODULE InitOperationCodes;
  1607. (* Module to construct the file containing the Operation Code Data Table *)
  1608.  
  1609.    FROM Files IMPORT
  1610.       FILE, FileState, Create, WriteRec, Close;
  1611.  
  1612.    FROM Terminal IMPORT
  1613.       WriteString, WriteLn;
  1614.  
  1615.    FROM Parser IMPORT
  1616.       TOKEN;
  1617.  
  1618.  
  1619.    CONST
  1620.       FIRST = 1;
  1621.       LAST = 118;
  1622.  
  1623.    TYPE
  1624.       ModeTypeA = (RegMem3,      (* 0 = Register, 1 = Memory *)
  1625.                    Ry02,         (* Register Rx -- Bits 0-2 *)
  1626.                    Rx911,        (* Register Ry -- Bits 9-11 *)
  1627.                    Data911,      (* Immediate Data -- Bits 9-11 *)
  1628.                    CntR911,      (* Count Register or Immediate Data *)
  1629.                    Brnch,        (* Relative Branch *)
  1630.                    DecBr,        (* Decrement and Branch *)
  1631.                    Data03,       (* Used for VECT only *)
  1632.                    Data07,       (* Branch & MOVEQ *)
  1633.                    OpM68D,       (* Data *)
  1634.                    OpM68A,       (* Address *)
  1635.                    OpM68C,       (* Compare *)
  1636.                    OpM68X,       (* XOR *)
  1637.                    OpM68S,       (* Sign Extension *)
  1638.                    OpM68R,       (* Register/Memory *)    
  1639.                    OpM37);       (* Exchange Registers *)
  1640.                    
  1641.       ModeTypeB = (Bit811,       (* BIT operations - bits 8/11 as switch *)
  1642.                    Size67,       (* 00 = Byte, 01 = Word, 10 = Long *)
  1643.                    Size6,        (* 0 = Word, 1 = Long *)
  1644.                    Size1213A,    (* 01 = Byte, 11 = Word, 10 = Long *)
  1645.                    Size1213,     (* 11 = Word, 10 = Long *)
  1646.                    Exten,        (* OpCode extension required *)
  1647.                    EA05a,        (* Effective Address - ALL *)
  1648.                    EA05b,        (* Less 1 *)
  1649.                    EA05c,        (* Less 1, 11 *)
  1650.                    EA05d,        (* Less 9, 10, 11 *)
  1651.                    EA05e,        (* Less 1, 9, 10, 11 *)
  1652.                    EA05f,        (* Less 0, 1, 3, 4, 11 *)
  1653.                    EA05x,        (* Dual mode - OR/AND *)
  1654.                    EA05y,        (* Dual mode - ADD/SUB *)
  1655.                    EA05z,        (* Dual mode - MOVEM *)
  1656.                    EA611);       (* Used only by MOVE *)
  1657.                    
  1658.       ModeA = SET OF ModeTypeA;
  1659.       ModeB = SET OF ModeTypeB;
  1660.  
  1661.       TableRecord = RECORD
  1662.                        Mnemonic : TOKEN;
  1663.                        Op : BITSET;
  1664.                        AddrModeA : ModeA;
  1665.                        AddrModeB : ModeB;
  1666.                     END;
  1667.  
  1668.  
  1669.    VAR
  1670.       Table68K : ARRAY [FIRST..LAST] OF TableRecord;
  1671.       i : CARDINAL;   (* index variable for initializing Table68K *)
  1672.       f : FILE;   (* "OPCODE.DAT" *)
  1673.  
  1674.    
  1675. BEGIN
  1676.    i := 1;
  1677.    WITH Table68K[i] DO
  1678.       Mnemonic := "ABCD";
  1679.       Op := {15, 14, 8};
  1680.       AddrModeA := ModeA{Rx911, RegMem3, Ry02};
  1681.       AddrModeB := ModeB{};
  1682.    END;
  1683.  
  1684.    INC (i);
  1685.    WITH Table68K[i] DO
  1686.       Mnemonic := "ADD";
  1687.       Op := {15, 14, 12};
  1688.       AddrModeA := ModeA{OpM68D};
  1689.       AddrModeB := ModeB{EA05y};
  1690.    END;
  1691.  
  1692.    INC (i);
  1693.    WITH Table68K[i] DO
  1694.       Mnemonic := "ADDA";
  1695.       Op := {15, 14, 12};
  1696.       AddrModeA := ModeA{OpM68A};
  1697.       AddrModeB := ModeB{EA05a};
  1698.    END;
  1699.  
  1700.          
  1701.    INC (i);
  1702.    WITH Table68K[i] DO
  1703.       Mnemonic := "ADDI";
  1704.       Op := {10, 9};
  1705.       AddrModeA := ModeA{};
  1706.       AddrModeB := ModeB{Size67, EA05e, Exten};
  1707.    END;
  1708.    
  1709.    INC (i);
  1710.    WITH Table68K[i] DO
  1711.       Mnemonic := "ADDQ";
  1712.       Op := {14, 12};
  1713.       AddrModeA := ModeA{Data911};
  1714.       AddrModeB := ModeB{Size67, EA05d};
  1715.    END;
  1716.    
  1717.    INC (i);
  1718.    WITH Table68K[i] DO
  1719.       Mnemonic := "ADDX";
  1720.       Op := {15, 14, 12, 8};
  1721.       AddrModeA := ModeA{RegMem3, Rx911, Ry02};
  1722.       AddrModeB := ModeB{Size67};
  1723.    END;
  1724.    
  1725.    INC (i);
  1726.    WITH Table68K[i] DO
  1727.       Mnemonic := "AND";
  1728.       Op := {15, 14};
  1729.       AddrModeA := ModeA{OpM68D};
  1730.       AddrModeB := ModeB{EA05x};
  1731.    END;
  1732.    
  1733.    INC (i);             
  1734.    WITH Table68K[i] DO
  1735.       Mnemonic := "ANDI";
  1736.       Op := {9};
  1737.       AddrModeA := ModeA{};
  1738.       AddrModeB := ModeB{EA05e, Size67, Exten};
  1739.    END;
  1740.    
  1741.    INC (i);
  1742.    WITH Table68K[i] DO
  1743.       Mnemonic := "ASL";
  1744.       Op := {15, 14, 13, 8};
  1745.       AddrModeA := ModeA{CntR911};
  1746.       AddrModeB := ModeB{};
  1747.    END;
  1748.    
  1749.    INC (i);
  1750.    WITH Table68K[i] DO
  1751.       Mnemonic := "ASR";
  1752.       Op := {15, 14, 13};
  1753.       AddrModeA := ModeA{CntR911};
  1754.       AddrModeB := ModeB{};
  1755.    END;
  1756.    
  1757.    INC (i);
  1758.    WITH Table68K[i] DO
  1759.       Mnemonic := "BCC";
  1760.       Op := {14, 13, 10};
  1761.       AddrModeA := ModeA{Brnch};
  1762.       AddrModeB := ModeB{};
  1763.    END;
  1764.    
  1765.    INC (i);
  1766.    WITH Table68K[i] DO
  1767.       Mnemonic := "BCHG";
  1768.       Op := {6};
  1769.       AddrModeA := ModeA{};
  1770.       AddrModeB := ModeB{EA05e, Exten, Bit811};
  1771.    END;
  1772.    
  1773.    INC (i);
  1774.    WITH Table68K[i] DO
  1775.       Mnemonic := "BCLR";
  1776.       Op := {7};
  1777.       AddrModeA := ModeA{};
  1778.       AddrModeB := ModeB{EA05e, Exten, Bit811};
  1779.    END;
  1780.    
  1781.    INC (i);
  1782.    WITH Table68K[i] DO
  1783.       Mnemonic := "BCS";
  1784.       Op := {14, 13, 10, 8};
  1785.       AddrModeA := ModeA{Brnch};
  1786.       AddrModeB := ModeB{};
  1787.    END;
  1788.    
  1789.    INC (i);
  1790.    WITH Table68K[i] DO
  1791.       Mnemonic := "BEQ";
  1792.       Op := {14, 13, 10, 9, 8};
  1793.       AddrModeA := ModeA{Brnch};
  1794.       AddrModeB := ModeB{};
  1795.    END;
  1796.    
  1797.    INC (i);
  1798.    WITH Table68K[i] DO
  1799.       Mnemonic := "BGE";
  1800.       Op := {14, 13, 11, 10};
  1801.       AddrModeA := ModeA{Brnch};
  1802.       AddrModeB := ModeB{};
  1803.    END;
  1804.    
  1805.    INC (i);
  1806.    WITH Table68K[i] DO
  1807.       Mnemonic := "BGT";
  1808.       Op := {14, 13, 11, 10, 9};
  1809.       AddrModeA := ModeA{Brnch};
  1810.       AddrModeB := ModeB{};
  1811.    END;
  1812.    
  1813.    INC (i);
  1814.    WITH Table68K[i] DO
  1815.       Mnemonic := "BHI";
  1816.       Op := {14, 13, 9};
  1817.       AddrModeA := ModeA{Brnch};
  1818.       AddrModeB := ModeB{};
  1819.    END;
  1820.    
  1821.    INC (i);
  1822.    WITH Table68K[i] DO
  1823.       Mnemonic := "BLE";
  1824.       Op := {14, 13, 11, 10, 9, 8};
  1825.       AddrModeA := ModeA{Brnch};
  1826.       AddrModeB := ModeB{};
  1827.    END;
  1828.    
  1829.    INC (i);
  1830.    WITH Table68K[i] DO
  1831.       Mnemonic := "BLS";
  1832.       Op := {14, 13, 9, 8};
  1833.       AddrModeA := ModeA{Brnch};
  1834.       AddrModeB := ModeB{};
  1835.    END;
  1836.    
  1837.    INC (i);
  1838.    WITH Table68K[i] DO
  1839.       Mnemonic := "BLT";
  1840.       Op := {14, 13, 11, 10, 8};
  1841.       AddrModeA := ModeA{Brnch};
  1842.       AddrModeB := ModeB{};
  1843.    END;
  1844.    
  1845.    INC (i);
  1846.    WITH Table68K[i] DO
  1847.       Mnemonic := "BMI";
  1848.       Op := {14, 13, 11, 9, 8};
  1849.       AddrModeA := ModeA{Brnch};
  1850.       AddrModeB := ModeB{};
  1851.    END;
  1852.    
  1853.    INC (i);
  1854.    WITH Table68K[i] DO
  1855.       Mnemonic := "BNE";
  1856.       Op := {14, 13, 10, 9};
  1857.       AddrModeA := ModeA{Brnch};
  1858.       AddrModeB := ModeB{};
  1859.    END;
  1860.    
  1861.    INC (i);
  1862.    WITH Table68K[i] DO
  1863.       Mnemonic := "BPL";
  1864.       Op := {14, 13, 11, 9};
  1865.       AddrModeA := ModeA{Brnch};
  1866.       AddrModeB := ModeB{};
  1867.    END;
  1868.    
  1869.    INC (i);
  1870.    WITH Table68K[i] DO
  1871.       Mnemonic := "BRA";
  1872.       Op := {14, 13};
  1873.       AddrModeA := ModeA{Brnch};
  1874.       AddrModeB := ModeB{};
  1875.    END;
  1876.    
  1877.    INC (i);
  1878.    WITH Table68K[i] DO
  1879.       Mnemonic := "BSET";
  1880.       Op := {7, 6};
  1881.       AddrModeA := ModeA{};
  1882.       AddrModeB := ModeB{EA05e, Exten, Bit811};
  1883.    END;
  1884.    
  1885.    INC (i);
  1886.    WITH Table68K[i] DO
  1887.       Mnemonic := "BSR";
  1888.       Op := {14, 13, 8};
  1889.       AddrModeA := ModeA{Brnch};
  1890.       AddrModeB := ModeB{};
  1891.    END;
  1892.    
  1893.    INC (i);         
  1894.    WITH Table68K[i] DO
  1895.       Mnemonic := "BTST";
  1896.       Op := {};
  1897.       AddrModeA := ModeA{};
  1898.       AddrModeB := ModeB{EA05c, Exten, Bit811};
  1899.    END;
  1900.    
  1901.    INC (i);         
  1902.    WITH Table68K[i] DO
  1903.       Mnemonic := "BVC";
  1904.       Op := {14, 13, 11};
  1905.       AddrModeA := ModeA{Brnch};
  1906.       AddrModeB := ModeB{};
  1907.    END;
  1908.    
  1909.    INC (i);
  1910.    WITH Table68K[i] DO
  1911.       Mnemonic := "BVS";
  1912.       Op := {14, 13, 11, 8};
  1913.       AddrModeA := ModeA{Brnch};
  1914.       AddrModeB := ModeB{};
  1915.    END;
  1916.    
  1917.    INC (i);
  1918.    WITH Table68K[i] DO
  1919.       Mnemonic := "CHK";
  1920.       Op := {14, 8, 7};
  1921.       AddrModeA := ModeA{Rx911};
  1922.       AddrModeB := ModeB{EA05b};
  1923.    END;
  1924.    
  1925.    INC (i);         
  1926.    WITH Table68K[i] DO
  1927.       Mnemonic := "CLR";
  1928.       Op := {14, 9};
  1929.       AddrModeA := ModeA{};
  1930.       AddrModeB := ModeB{Size67, EA05e};
  1931.    END;
  1932.    
  1933.    INC (i);         
  1934.    WITH Table68K[i] DO
  1935.       Mnemonic := "CMP";
  1936.       Op := {15, 13, 12};
  1937.       AddrModeA := ModeA{OpM68C};
  1938.       AddrModeB := ModeB{EA05a};
  1939.    END;
  1940.    
  1941.    INC (i);         
  1942.    WITH Table68K[i] DO
  1943.       Mnemonic := "CMPA";
  1944.       Op := {15, 13, 12};
  1945.       AddrModeA := ModeA{OpM68A};
  1946.       AddrModeB := ModeB{EA05a};
  1947.    END;
  1948.    
  1949.    INC (i);         
  1950.    WITH Table68K[i] DO
  1951.       Mnemonic := "CMPI";
  1952.       Op := {11, 10};
  1953.       AddrModeA := ModeA{};
  1954.       AddrModeB := ModeB{Size67, EA05e, Exten};
  1955.    END;
  1956.    
  1957.    INC (i);         
  1958.    WITH Table68K[i] DO
  1959.       Mnemonic := "CMPM";
  1960.       Op := {15, 13, 12, 8, 3};
  1961.       AddrModeA := ModeA{Rx911, Ry02};
  1962.       AddrModeB := ModeB{Size67};
  1963.    END;
  1964.    
  1965.    INC (i);         
  1966.    WITH Table68K[i] DO
  1967.       Mnemonic := "DBCC";
  1968.       Op := {14, 12, 10, 7, 6, 3};
  1969.       AddrModeA := ModeA{DecBr};
  1970.       AddrModeB := ModeB{};
  1971.    END;
  1972.    
  1973.    INC (i);         
  1974.    WITH Table68K[i] DO
  1975.       Mnemonic := "DBCS";
  1976.       Op := {14, 12, 10, 8, 7, 6, 3};
  1977.       AddrModeA := ModeA{DecBr};
  1978.       AddrModeB := ModeB{};
  1979.    END;
  1980.    
  1981.    INC (i);         
  1982.    WITH Table68K[i] DO
  1983.       Mnemonic := "DBEQ";
  1984.       Op := {14, 12, 10, 9, 8, 7, 6, 3};
  1985.       AddrModeA := ModeA{DecBr};
  1986.       AddrModeB := ModeB{};
  1987.    END;
  1988.    
  1989.    INC (i);         
  1990.    WITH Table68K[i] DO
  1991.       Mnemonic := "DBF";
  1992.       Op := {14, 12, 8, 7, 6, 3};
  1993.       AddrModeA := ModeA{DecBr};
  1994.       AddrModeB := ModeB{};
  1995.    END;
  1996.    
  1997.    INC (i);         
  1998.    WITH Table68K[i] DO
  1999.       Mnemonic := "DBGE";
  2000.       Op := {14, 12, 11, 10, 7, 6, 3};
  2001.       AddrModeA := ModeA{DecBr};
  2002.       AddrModeB := ModeB{};
  2003.    END;
  2004.    
  2005.    INC (i);         
  2006.    WITH Table68K[i] DO
  2007.       Mnemonic := "DBGT";
  2008.       Op := {14, 12, 11, 10, 9, 7, 6, 3};
  2009.       AddrModeA := ModeA{DecBr};
  2010.       AddrModeB := ModeB{};
  2011.    END;
  2012.    
  2013.    INC (i);         
  2014.    WITH Table68K[i] DO
  2015.       Mnemonic := "DBHI";
  2016.       Op := {14, 12, 9, 7, 6, 3};
  2017.       AddrModeA := ModeA{DecBr};
  2018.       AddrModeB := ModeB{};
  2019.    END;
  2020.    
  2021.    INC (i);         
  2022.    WITH Table68K[i] DO
  2023.       Mnemonic := "DBLE";
  2024.       Op := {14, 12, 11, 10, 9, 8, 7, 6, 3};
  2025.       AddrModeA := ModeA{DecBr};
  2026.       AddrModeB := ModeB{};
  2027.    END;
  2028.    
  2029.    INC (i);         
  2030.    WITH Table68K[i] DO
  2031.       Mnemonic := "DBLS";
  2032.       Op := {14, 12, 9, 8, 7, 6, 3};
  2033.       AddrModeA := ModeA{DecBr};
  2034.       AddrModeB := ModeB{};
  2035.    END;
  2036.    
  2037.    INC (i);         
  2038.    WITH Table68K[i] DO
  2039.       Mnemonic := "DBLT";
  2040.       Op := {14, 12, 11, 10, 8, 7, 6, 3};
  2041.       AddrModeA := ModeA{DecBr};
  2042.       AddrModeB := ModeB{};
  2043.    END;
  2044.    
  2045.    INC (i);         
  2046.    WITH Table68K[i] DO
  2047.       Mnemonic := "DBMI";
  2048.       Op := {14, 12, 11, 9, 8, 7, 6, 3};
  2049.       AddrModeA := ModeA{DecBr};
  2050.       AddrModeB := ModeB{};
  2051.    END;
  2052.    
  2053.    INC (i);         
  2054.    WITH Table68K[i] DO
  2055.       Mnemonic := "DBNE";
  2056.       Op := {14, 12, 10, 9, 7, 6, 3};
  2057.       AddrModeA := ModeA{DecBr};
  2058.       AddrModeB := ModeB{};
  2059.    END;
  2060.    
  2061.    INC (i);         
  2062.    WITH Table68K[i] DO
  2063.       Mnemonic := "DBPL";
  2064.       Op := {14, 12, 11, 9, 7, 6, 3};
  2065.       AddrModeA := ModeA{DecBr};
  2066.       AddrModeB := ModeB{};
  2067.    END;
  2068.    
  2069.    INC (i);         
  2070.    WITH Table68K[i] DO
  2071.       Mnemonic := "DBRA";
  2072.       Op := {14, 12, 8, 7, 6, 3};
  2073.       AddrModeA := ModeA{DecBr};
  2074.       AddrModeB := ModeB{};
  2075.    END;
  2076.  
  2077.    INC (i);         
  2078.    WITH Table68K[i] DO
  2079.       Mnemonic := "DBT";
  2080.       Op := {14, 12, 7, 6, 3};
  2081.       AddrModeA := ModeA{DecBr};
  2082.       AddrModeB := ModeB{};
  2083.    END;
  2084.    
  2085.    INC (i);         
  2086.    WITH Table68K[i] DO
  2087.       Mnemonic := "DBVC";
  2088.       Op := {14, 12, 11, 7, 6, 3};
  2089.       AddrModeA := ModeA{DecBr};
  2090.       AddrModeB := ModeB{};
  2091.    END;
  2092.    
  2093.    INC (i);         
  2094.    WITH Table68K[i] DO
  2095.       Mnemonic := "DBVS";
  2096.       Op := {14, 12, 11, 8, 7, 6, 3};
  2097.       AddrModeA := ModeA{DecBr};
  2098.       AddrModeB := ModeB{};
  2099.    END;
  2100.    
  2101.    INC (i);         
  2102.    WITH Table68K[i] DO
  2103.       Mnemonic := "DIVS";
  2104.       Op := {15, 8, 7, 6};
  2105.       AddrModeA := ModeA{Rx911};
  2106.       AddrModeB := ModeB{EA05b};
  2107.    END;
  2108.    
  2109.    INC (i);         
  2110.    WITH Table68K[i] DO
  2111.       Mnemonic := "DIVU";
  2112.       Op := {15, 7, 6};
  2113.       AddrModeA := ModeA{Rx911};
  2114.       AddrModeB := ModeB{EA05b};
  2115.    END;
  2116.    
  2117.    INC (i);         
  2118.    WITH Table68K[i] DO
  2119.       Mnemonic := "EOR";
  2120.       Op := {15, 13, 12};
  2121.       AddrModeA := ModeA{OpM68X};
  2122.       AddrModeB := ModeB{EA05e};
  2123.    END;
  2124.    
  2125.    INC (i);         
  2126.    WITH Table68K[i] DO
  2127.       Mnemonic := "EORI";
  2128.       Op := {11, 9};
  2129.       AddrModeA := ModeA{};
  2130.       AddrModeB := ModeB{Size67, EA05e, Exten};
  2131.    END;
  2132.    
  2133.    INC (i);         
  2134.    WITH Table68K[i] DO
  2135.       Mnemonic := "EXG";
  2136.       Op := {15, 14, 8};
  2137.       AddrModeA := ModeA{OpM37};
  2138.       AddrModeB := ModeB{};
  2139.    END;
  2140.    
  2141.    INC (i);         
  2142.    WITH Table68K[i] DO
  2143.       Mnemonic := "EXT";
  2144.       Op := {14, 11};
  2145.       AddrModeA := ModeA{OpM68S};
  2146.       AddrModeB := ModeB{};
  2147.    END;
  2148.    
  2149.    INC (i);         
  2150.    WITH Table68K[i] DO
  2151.       Mnemonic := "ILLEGAL";
  2152.       Op := {14, 11, 9, 7, 6, 5, 4, 3, 2};
  2153.       AddrModeA := ModeA{};
  2154.       AddrModeB := ModeB{};
  2155.    END;
  2156.    
  2157.    INC (i);         
  2158.    WITH Table68K[i] DO
  2159.       Mnemonic := "JMP";
  2160.       Op := {14, 11, 10, 9, 7, 6};
  2161.       AddrModeA := ModeA{};
  2162.       AddrModeB := ModeB{EA05f};
  2163.    END;
  2164.    
  2165.    INC (i);         
  2166.    WITH Table68K[i] DO
  2167.       Mnemonic := "JSR";
  2168.       Op := {14, 11, 10, 9, 7};
  2169.       AddrModeA := ModeA{};
  2170.       AddrModeB := ModeB{EA05f};
  2171.    END;
  2172.    
  2173.    INC (i);         
  2174.    WITH Table68K[i] DO
  2175.       Mnemonic := "LEA";
  2176.       Op := {14, 8, 7, 6};
  2177.       AddrModeA := ModeA{Rx911};
  2178.       AddrModeB := ModeB{EA05f};
  2179.    END;
  2180.    
  2181.    INC (i);         
  2182.    WITH Table68K[i] DO
  2183.       Mnemonic := "LINK";
  2184.       Op := {14, 11, 10, 9, 6, 4};
  2185.       AddrModeA := ModeA{Ry02};
  2186.       AddrModeB := ModeB{Exten};
  2187.    END;
  2188.    
  2189.    INC (i);         
  2190.    WITH Table68K[i] DO
  2191.       Mnemonic := "LSL";
  2192.       Op := {15, 14, 13, 9, 8, 3};
  2193.       AddrModeA := ModeA{CntR911};
  2194.       AddrModeB := ModeB{};
  2195.    END;
  2196.    
  2197.    INC (i);         
  2198.    WITH Table68K[i] DO
  2199.       Mnemonic := "LSR";
  2200.       Op := {15, 14, 13, 9, 3};
  2201.       AddrModeA := ModeA{CntR911};
  2202.       AddrModeB := ModeB{};
  2203.    END;
  2204.    
  2205.    INC (i);         
  2206.    WITH Table68K[i] DO
  2207.       Mnemonic := "MOVE"; 
  2208.       Op := {};
  2209.       AddrModeA := ModeA{};
  2210.       AddrModeB := ModeB{Size1213A, EA611};
  2211.    END;
  2212.    
  2213.    INC (i);         
  2214.    WITH Table68K[i] DO
  2215.       Mnemonic := "MOVEA";
  2216.       Op := {6};
  2217.       AddrModeA := ModeA{Rx911};
  2218.       AddrModeB := ModeB{Size1213, EA05a};
  2219.    END;
  2220.    
  2221.    INC (i);         
  2222.    WITH Table68K[i] DO
  2223.       Mnemonic := "MOVEM";
  2224.       Op := {14, 11, 7};
  2225.       AddrModeA := ModeA{};
  2226.       AddrModeB := ModeB{Size6, EA05z, Exten};
  2227.    END;
  2228.    
  2229.    INC (i);         
  2230.    WITH Table68K[i] DO
  2231.       Mnemonic := "MOVEP";
  2232.       Op := {3};
  2233.       AddrModeA := ModeA{OpM68R};
  2234.       AddrModeB := ModeB{Exten};
  2235.    END;
  2236.    
  2237.    INC (i);         
  2238.    WITH Table68K[i] DO
  2239.       Mnemonic := "MOVEQ";
  2240.       Op := {14, 13, 12};
  2241.       AddrModeA := ModeA{Data07};
  2242.       AddrModeB := ModeB{};
  2243.    END;
  2244.    
  2245.    INC (i);         
  2246.    WITH Table68K[i] DO
  2247.       Mnemonic := "MULS";
  2248.       Op := {15, 14, 8, 7, 6};
  2249.       AddrModeA := ModeA{Rx911};
  2250.       AddrModeB := ModeB{EA05b};
  2251.    END;
  2252.    
  2253.    INC (i);         
  2254.    WITH Table68K[i] DO
  2255.       Mnemonic := "MULU";
  2256.       Op := {15, 14, 7, 6};
  2257.       AddrModeA := ModeA{Rx911};
  2258.       AddrModeB := ModeB{EA05b};
  2259.    END;
  2260.    
  2261.    INC (i);         
  2262.    WITH Table68K[i] DO
  2263.       Mnemonic := "NBCD";
  2264.       Op := {14, 11};
  2265.       AddrModeA := ModeA{};
  2266.       AddrModeB := ModeB{EA05e};
  2267.    END;
  2268.    
  2269.    INC (i);            
  2270.    WITH Table68K[i] DO
  2271.       Mnemonic := "NEG";
  2272.       Op := {14, 10};
  2273.       AddrModeA := ModeA{};
  2274.       AddrModeB := ModeB{Size67, EA05e};
  2275.    END;
  2276.    
  2277.    INC (i);         
  2278.    WITH Table68K[i] DO
  2279.       Mnemonic := "NEGX";
  2280.       Op := {14};
  2281.       AddrModeA := ModeA{};
  2282.       AddrModeB := ModeB{Size67, EA05e};
  2283.    END;
  2284.    
  2285.    INC (i);         
  2286.    WITH Table68K[i] DO
  2287.       Mnemonic := "NOP";
  2288.       Op := {14, 11, 10, 9, 6, 5, 4, 0};
  2289.       AddrModeA := ModeA{};
  2290.       AddrModeB := ModeB{};
  2291.    END;
  2292.    
  2293.    INC (i);         
  2294.    WITH Table68K[i] DO
  2295.       Mnemonic := "NOT";
  2296.       Op := {14, 10, 9};
  2297.       AddrModeA := ModeA{};
  2298.       AddrModeB := ModeB{Size67, EA05e};
  2299.    END;
  2300.    
  2301.    INC (i);            
  2302.    WITH Table68K[i] DO
  2303.       Mnemonic := "OR";
  2304.       Op := {15};
  2305.       AddrModeA := ModeA{OpM68D};
  2306.       AddrModeB := ModeB{EA05x};
  2307.    END;
  2308.    
  2309.    INC (i);         
  2310.    WITH Table68K[i] DO
  2311.       Mnemonic := "ORI";
  2312.       Op := {};
  2313.       AddrModeA := ModeA{};
  2314.       AddrModeB := ModeB{Size67, EA05e, Exten};
  2315.    END;
  2316.    
  2317.    INC (i);         
  2318.    WITH Table68K[i] DO
  2319.       Mnemonic := "PEA";
  2320.       Op := {14, 11, 6};
  2321.       AddrModeA := ModeA{};
  2322.       AddrModeB := ModeB{EA05f};
  2323.    END;
  2324.    
  2325.    INC (i);         
  2326.    WITH Table68K[i] DO
  2327.       Mnemonic := "RESET";
  2328.       Op := {14, 11, 10, 9, 6, 5, 4};
  2329.       AddrModeA := ModeA{};
  2330.       AddrModeB := ModeB{};
  2331.    END;
  2332.    
  2333.    INC (i);         
  2334.    WITH Table68K[i] DO
  2335.       Mnemonic := "ROL";
  2336.       Op := {15, 14, 13, 10, 9, 8, 4, 3};
  2337.       AddrModeA := ModeA{CntR911};
  2338.       AddrModeB := ModeB{};
  2339.    END;
  2340.    
  2341.    INC (i);         
  2342.    WITH Table68K[i] DO
  2343.       Mnemonic := "ROR";
  2344.       Op := {15, 14, 13, 10, 9, 4, 3};
  2345.       AddrModeA := ModeA{CntR911};
  2346.       AddrModeB := ModeB{};
  2347.    END;
  2348.    
  2349.    INC (i);         
  2350.    WITH Table68K[i] DO
  2351.       Mnemonic := "ROXL";
  2352.       Op := {15, 14, 13, 10, 8, 4};
  2353.       AddrModeA := ModeA{CntR911};
  2354.       AddrModeB := ModeB{};
  2355.    END;
  2356.    
  2357.    INC (i);         
  2358.    WITH Table68K[i] DO
  2359.       Mnemonic := "ROXR";
  2360.       Op := {15, 14, 13, 10, 4};
  2361.       AddrModeA := ModeA{CntR911};
  2362.       AddrModeB := ModeB{};
  2363.    END;
  2364.    
  2365.    INC (i);         
  2366.    WITH Table68K[i] DO
  2367.       Mnemonic := "RTE";
  2368.       Op := {14, 11, 10, 9, 6, 5, 4, 1, 0};
  2369.       AddrModeA := ModeA{};
  2370.       AddrModeB := ModeB{};
  2371.    END;
  2372.    
  2373.    INC (i);         
  2374.    WITH Table68K[i] DO
  2375.       Mnemonic := "RTR";
  2376.       Op := {14, 11, 10, 9, 6, 5, 4, 2, 1, 0};
  2377.       AddrModeA := ModeA{};
  2378.       AddrModeB := ModeB{};
  2379.    END;
  2380.    
  2381.    INC (i);         
  2382.    WITH Table68K[i] DO
  2383.       Mnemonic := "RTS";
  2384.       Op := {14, 11, 10, 9, 6, 5, 4, 2, 0};
  2385.       AddrModeA := ModeA{};
  2386.       AddrModeB := ModeB{};
  2387.    END;
  2388.    
  2389.    INC (i);         
  2390.    WITH Table68K[i] DO
  2391.       Mnemonic := "SBCD";
  2392.       Op := {15, 8};
  2393.       AddrModeA := ModeA{Rx911, RegMem3, Ry02};
  2394.       AddrModeB := ModeB{};
  2395.    END;
  2396.    
  2397.    INC (i);         
  2398.    WITH Table68K[i] DO
  2399.       Mnemonic := "SCC";
  2400.       Op := {14, 12, 10, 7, 6};
  2401.       AddrModeA := ModeA{};
  2402.       AddrModeB := ModeB{EA05e};
  2403.    END;
  2404.    
  2405.    INC (i);         
  2406.    WITH Table68K[i] DO
  2407.       Mnemonic := "SCS";
  2408.       Op := {14, 12, 10, 8, 7, 6};
  2409.       AddrModeA := ModeA{};
  2410.       AddrModeB := ModeB{EA05e};
  2411.    END;
  2412.    
  2413.    INC (i);         
  2414.    WITH Table68K[i] DO
  2415.       Mnemonic := "SEQ";
  2416.       Op := {14, 12, 10, 9, 8, 7, 6};
  2417.       AddrModeA := ModeA{};
  2418.       AddrModeB := ModeB{EA05e};
  2419.    END;
  2420.    
  2421.    INC (i);         
  2422.    WITH Table68K[i] DO
  2423.       Mnemonic := "SF";
  2424.       Op := {14, 12, 8, 7, 6};
  2425.       AddrModeA := ModeA{};
  2426.       AddrModeB := ModeB{EA05e};
  2427.    END;
  2428.    
  2429.    INC (i);         
  2430.    WITH Table68K[i] DO
  2431.       Mnemonic := "SGE";
  2432.       Op := {14, 12, 11, 10, 7, 6};
  2433.       AddrModeA := ModeA{};
  2434.       AddrModeB := ModeB{EA05e};
  2435.    END;
  2436.    
  2437.    INC (i);         
  2438.    WITH Table68K[i] DO
  2439.       Mnemonic := "SGT";
  2440.       Op := {14, 12, 11, 10, 9, 7, 6};
  2441.       AddrModeA := ModeA{};
  2442.       AddrModeB := ModeB{EA05e};
  2443.    END;
  2444.    
  2445.    INC (i);         
  2446.    WITH Table68K[i] DO
  2447.       Mnemonic := "SHI";
  2448.       Op := {14, 12, 9, 7, 6};
  2449.       AddrModeA := ModeA{};
  2450.       AddrModeB := ModeB{EA05e};
  2451.    END;
  2452.    
  2453.    INC (i);         
  2454.    WITH Table68K[i] DO
  2455.       Mnemonic := "SLE";
  2456.       Op := {14, 12, 11, 10, 9, 8, 7, 6};
  2457.       AddrModeA := ModeA{};
  2458.       AddrModeB := ModeB{EA05e};
  2459.    END;
  2460.    
  2461.    INC (i);         
  2462.    WITH Table68K[i] DO
  2463.       Mnemonic := "SLS";
  2464.       Op := {14, 12, 9, 8, 7, 6};
  2465.       AddrModeA := ModeA{};
  2466.       AddrModeB := ModeB{EA05e};
  2467.    END;
  2468.    
  2469.    INC (i);         
  2470.    WITH Table68K[i] DO
  2471.       Mnemonic := "SLT";
  2472.       Op := {14, 12, 11, 10, 8, 7, 6};
  2473.       AddrModeA := ModeA{};
  2474.       AddrModeB := ModeB{EA05e};
  2475.    END;
  2476.    
  2477.    INC (i);         
  2478.    WITH Table68K[i] DO
  2479.       Mnemonic := "SMI";
  2480.       Op := {14, 12, 11, 9, 8, 7, 6};
  2481.       AddrModeA := ModeA{};
  2482.       AddrModeB := ModeB{EA05e};
  2483.    END;
  2484.    
  2485.    INC (i);         
  2486.    WITH Table68K[i] DO
  2487.       Mnemonic := "SNE";
  2488.       Op := {14, 12, 10, 9, 7, 6};
  2489.       AddrModeA := ModeA{};
  2490.       AddrModeB := ModeB{EA05e};
  2491.    END;
  2492.    
  2493.    INC (i);         
  2494.    WITH Table68K[i] DO
  2495.       Mnemonic := "SPL";
  2496.       Op := {14, 12, 11, 9, 7, 6};
  2497.       AddrModeA := ModeA{};
  2498.       AddrModeB := ModeB{EA05e};
  2499.    END;
  2500.    
  2501.    INC (i);         
  2502.    WITH Table68K[i] DO
  2503.       Mnemonic := "ST";
  2504.       Op := {14, 12, 7, 6};
  2505.       AddrModeA := ModeA{};
  2506.       AddrModeB := ModeB{EA05e};
  2507.    END;
  2508.    
  2509.    INC (i);         
  2510.    WITH Table68K[i] DO
  2511.       Mnemonic := "STOP";
  2512.       Op := {14, 11, 10, 9, 6, 5, 4, 1};
  2513.       AddrModeA := ModeA{};
  2514.       AddrModeB := ModeB{Exten};
  2515.    END;
  2516.    
  2517.    INC (i);         
  2518.    WITH Table68K[i] DO
  2519.       Mnemonic := "SUB";
  2520.       Op := {15, 12};
  2521.       AddrModeA := ModeA{OpM68D};
  2522.       AddrModeB := ModeB{EA05y};
  2523.    END;
  2524.    
  2525.    INC (i);         
  2526.    WITH Table68K[i] DO
  2527.       Mnemonic := "SUBA";
  2528.       Op := {15, 12};
  2529.       AddrModeA := ModeA{OpM68A};
  2530.       AddrModeB := ModeB{EA05a};
  2531.    END;
  2532.    
  2533.    INC (i);         
  2534.    WITH Table68K[i] DO
  2535.       Mnemonic := "SUBI";
  2536.       Op := {10};
  2537.       AddrModeA := ModeA{};
  2538.       AddrModeB := ModeB{Size67, EA05e, Exten};
  2539.    END;
  2540.    
  2541.    INC (i);         
  2542.    WITH Table68K[i] DO
  2543.       Mnemonic := "SUBQ";
  2544.       Op := {14, 12, 8};
  2545.       AddrModeA := ModeA{Data911};
  2546.       AddrModeB := ModeB{Size67, EA05d};
  2547.    END;
  2548.    
  2549.    INC (i);         
  2550.    WITH Table68K[i] DO
  2551.       Mnemonic := "SUBX";
  2552.       Op := {15, 12, 8};
  2553.       AddrModeA := ModeA{Rx911, RegMem3, Ry02};
  2554.       AddrModeB := ModeB{Size67};
  2555.    END;
  2556.    
  2557.    INC (i);         
  2558.    WITH Table68K[i] DO
  2559.       Mnemonic := "SVC";
  2560.       Op := {14, 12, 11, 7, 6};
  2561.       AddrModeA := ModeA{};
  2562.       AddrModeB := ModeB{EA05e};
  2563.    END;
  2564.    
  2565.    INC (i);         
  2566.    WITH Table68K[i] DO
  2567.       Mnemonic := "SVS";
  2568.       Op := {14, 12, 11, 8, 7, 6};
  2569.       AddrModeA := ModeA{};
  2570.       AddrModeB := ModeB{EA05e};
  2571.    END;
  2572.    
  2573.    INC (i);         
  2574.    WITH Table68K[i] DO
  2575.       Mnemonic := "SWAP";
  2576.       Op := {14, 11, 6};
  2577.       AddrModeA := ModeA{Ry02};
  2578.       AddrModeB := ModeB{};
  2579.    END;
  2580.    
  2581.    INC (i);         
  2582.    WITH Table68K[i] DO
  2583.       Mnemonic := "TAS";
  2584.       Op := {14, 11, 9, 7, 6};
  2585.       AddrModeA := ModeA{};
  2586.       AddrModeB := ModeB{EA05e};
  2587.    END;
  2588.    
  2589.    INC (i);         
  2590.    WITH Table68K[i] DO
  2591.       Mnemonic := "TRAP";
  2592.       Op := {14, 11, 10, 9, 6};
  2593.       AddrModeA := ModeA{Data03};
  2594.       AddrModeB := ModeB{};
  2595.    END;
  2596.    
  2597.    INC (i);         
  2598.    WITH Table68K[i] DO
  2599.       Mnemonic := "TRAPV";
  2600.       Op := {14, 11, 10, 9, 6, 5, 4, 2, 1};
  2601.       AddrModeA := ModeA{};
  2602.       AddrModeB := ModeB{};
  2603.    END;
  2604.    
  2605.    INC (i);
  2606.    WITH Table68K[i] DO
  2607.       Mnemonic := "TST";
  2608.       Op := {14, 11, 9};
  2609.       AddrModeA := ModeA{};
  2610.       AddrModeB := ModeB{Size67, EA05e};
  2611.    END;
  2612.    
  2613.    INC (i);         
  2614.    WITH Table68K[i] DO
  2615.       Mnemonic := "UNLK";
  2616.       Op := {14, 11, 10, 9, 6, 4, 3};
  2617.       AddrModeA := ModeA{Ry02};
  2618.       AddrModeB := ModeB{};
  2619.    END;
  2620.  
  2621.    IF Create (f, "OPCODE.DAT") # FileOK THEN
  2622.       WriteString ("Unable to create OpCode File.");
  2623.       WriteLn;
  2624.       HALT;
  2625.    END;
  2626.  
  2627.    FOR i := FIRST TO LAST DO
  2628.       WriteRec (f, Table68K[i]);
  2629.    END;
  2630.  
  2631.    IF Close (f) # FileOK THEN
  2632.       WriteString ("Unable to close OpCode File.");
  2633.       WriteLn;
  2634.    END;
  2635. END InitOperationCodes.
  2636.  
  2637. ----------------------------------------
  2638.                         
  2639.  
  2640.  
  2641.  
  2642.  
  2643. IMPLEMENTATION MODULE CodeGenerator;
  2644. (* Uses information supplied by Parser, OperationCodes, *)
  2645. (* and SyntaxAnalyzer to produce the object code.       *)
  2646.  
  2647.    FROM Strings IMPORT
  2648.       Length, CompareStr;
  2649.  
  2650.    FROM SymbolTable IMPORT
  2651.       FillSymTab, ReadSymTab;
  2652.  
  2653.    FROM Parser IMPORT
  2654.       TOKEN, OPERAND, OpLoc, SrcLoc, DestLoc;
  2655.  
  2656.    FROM LongNumbers IMPORT
  2657.       LONG, LongAdd, LongSub, LongInc, LongDec, 
  2658.       LongClear, CardToLong, LongToCard, LongToInt,
  2659.       LongCompare, AddrBoundW, AddrBoundL;
  2660.  
  2661.    FROM OperationCodes IMPORT
  2662.       ModeTypeA, ModeTypeB, ModeA, ModeB, Instructions;
  2663.  
  2664.    FROM ErrorX68 IMPORT
  2665.       ErrorType, Error;
  2666.  
  2667.    FROM SyntaxAnalyzer IMPORT
  2668.       OpMode, Xtype, SizeType, OpConfig, Src, Dest, 
  2669.       Size, Op, AddrModeA, AddrModeB, InstSize,
  2670.       GetValue, GetSize, GetInstModeSize, GetOperand, GetMultReg;
  2671.  
  2672.  
  2673.    CONST
  2674.       JMP = {14, 11, 10, 9, 7, 6};
  2675.       JSR = {14, 11, 10, 9, 7};
  2676.       RTE = {14, 11, 10, 9, 6, 5, 4, 1, 0};
  2677.       RTR = {14, 11, 10, 9, 6, 5, 4, 2, 1, 0};
  2678.       RTS = {14, 11, 10, 9, 6, 5, 4, 2, 0};
  2679.       TRAPV = {14, 11, 10, 9, 6, 5, 4, 2, 1};
  2680.       STOP = {14, 11, 10, 9, 6, 5, 4, 1};
  2681.       LINK = {14, 11, 10, 9, 6, 4};
  2682.       SWAP = {14, 11, 6};
  2683.       UNLK = {14, 11, 10, 9, 6, 4, 3};
  2684.       Quote = 47C;
  2685.  
  2686.  
  2687.    VAR
  2688.    (*---     
  2689.       (* Defined in DEFINITION MODULE *)
  2690.       LZero, AddrCnt : LONG;
  2691.       Pass2 : BOOLEAN;                 
  2692.                                        ---*)
  2693.       AddrAdv : LONG;
  2694.       TempL : LONG;     (* Temporary variables *)
  2695.       TempI : INTEGER;
  2696.       TempC : CARDINAL;
  2697.       BrValue : LONG;   (* Used to calculate relative branches *)
  2698.       RevBr : BOOLEAN;
  2699.  
  2700.  
  2701.  
  2702.    PROCEDURE BuildSymTable (VAR AddrCnt : LONG;
  2703.                             Label, OpCode : TOKEN; SrcOp, DestOp : OPERAND);
  2704.    (* Builds symbol table from symbolic information of Source File *)
  2705.  
  2706.       VAR
  2707.          Value : LONG;
  2708.          Full : BOOLEAN;
  2709.          PseudoOp : BOOLEAN;
  2710.  
  2711.       BEGIN
  2712.          Value := LZero;
  2713.          AddrAdv := LZero;
  2714.          InstSize := 0;
  2715.          PseudoOp := FALSE;
  2716.          Size := S0;
  2717.  
  2718.          IF Length (OpCode) = 0 THEN
  2719.             RETURN;   (* Nothing added to symbol table, AddrCnt not changed *)
  2720.          END;
  2721.  
  2722.          GetSize (OpCode, Size);
  2723.   
  2724.          IF CompareStr (OpCode, "ORG") = 0 THEN
  2725.             GetValue (SrcOp, AddrCnt);
  2726.             AddrBoundW (AddrCnt);
  2727.             Value := AddrCnt;
  2728.             PseudoOp := TRUE;
  2729.          ELSIF CompareStr (OpCode, "EQU") = 0 THEN
  2730.             GetValue (SrcOp, Value);
  2731.             PseudoOp := TRUE;
  2732.          ELSIF CompareStr (OpCode, "DC") = 0 THEN
  2733.             CASE Size OF
  2734.                Word  :  AddrBoundW (AddrCnt);
  2735.             |  Long  :  AddrBoundL (AddrCnt);
  2736.             |  Byte  :  ;
  2737.             END;
  2738.  
  2739.             IF SrcOp[0] = Quote THEN   (* String Constant *)
  2740.                TempC := Length (SrcOp);
  2741.                IF TempC > 2 THEN
  2742.                   InstSize := TempC - 2;
  2743.                END;
  2744.             ELSE
  2745.                InstSize := ORD (Size);
  2746.             END;    
  2747.             CardToLong (InstSize, AddrAdv);
  2748.             Value := AddrCnt;
  2749.             PseudoOp := TRUE;
  2750.          ELSIF CompareStr (OpCode, "DS") = 0 THEN
  2751.             GetValue (SrcOp, AddrAdv);
  2752.             Value := AddrCnt;
  2753.             PseudoOp := TRUE;
  2754.          ELSIF CompareStr (OpCode, "EVEN") = 0 THEN
  2755.             AddrBoundW (AddrCnt);
  2756.             Value := AddrCnt;
  2757.             PseudoOp := TRUE;
  2758.          ELSIF CompareStr (OpCode, "END") = 0 THEN
  2759.             PseudoOp := TRUE;
  2760.          ELSE
  2761.             Value := AddrCnt;
  2762.          END;
  2763.  
  2764.          IF Length (Label) # 0 THEN
  2765.             FillSymTab (Label, Value, Full);
  2766.             IF Full THEN
  2767.                Error (0, SymFull);
  2768.             END;
  2769.          END;
  2770.  
  2771.          IF NOT PseudoOp THEN
  2772.             Instructions (OpCode, OpLoc, Op, AddrModeA, AddrModeB);       
  2773.  
  2774.             AddrBoundW (AddrCnt);
  2775.             Src.Loc := SrcLoc;   Dest.Loc := DestLoc;
  2776.             GetOperand (SrcOp, Src);
  2777.             GetOperand (DestOp, Dest);
  2778.             InstSize := 2;   (* minimum size of instruction *)
  2779.  
  2780.             IF Brnch IN AddrModeA THEN
  2781.                IF Size # Byte THEN
  2782.                   INC (InstSize, 2);
  2783.                END;
  2784.             ELSIF DecBr IN AddrModeA THEN
  2785.                INC (InstSize, 2);
  2786.             ELSE   
  2787.                IF (Op = JMP) OR (Op = JSR) THEN   (* Allows for 'JMP.S' *)
  2788.                   IF (Size = Byte) AND (Src.Mode = AbsL) THEN
  2789.                      Src.Mode := AbsW;
  2790.                   END;
  2791.                END;
  2792.  
  2793.                TempC := GetInstModeSize (Src.Mode, Size, InstSize);
  2794.                TempC := GetInstModeSize (Dest.Mode, Size, InstSize);
  2795.             END;
  2796.  
  2797.             IF (Src.Mode = Imm) AND 
  2798.              ((Data911 IN AddrModeA) OR (Data03 IN AddrModeA) OR
  2799.               (Data07 IN AddrModeA) OR (CntR911 IN AddrModeA)) THEN
  2800.                (* Quick instruction *)
  2801.                InstSize := 2;
  2802.             END;
  2803.             CardToLong (InstSize, AddrAdv);   
  2804.          END;
  2805.       END BuildSymTable;
  2806.  
  2807.  
  2808.  
  2809.    PROCEDURE MergeModes (VAR SrcOp, DestOp : OPERAND;
  2810.                          VAR ObjOp, ObjSrc, ObjDest : LONG;
  2811.                          VAR nO,    nS,     nD      : CARDINAL);
  2812.    (*  Uses information from Instructions & GetOperand (among others)  *)
  2813.    (*  to complete calculation of Object Code.                         *)
  2814.    (*  Op, AddrModeA, AddrModeB, Size, and Src & Dest records are all  *)
  2815.    (*  Global variables imported from the SyntaxAnalyzer MODULE.       *)
  2816.  
  2817.       CONST
  2818.          (* BITSETs of the modes MISSING from effective address modes  *)
  2819.           ea = {};                 (* Effective addressing - all modes *)
  2820.          dea = {1};                (* Data effective addressing        *)
  2821.          mea = {1, 0};             (* Memory effective addressing      *)
  2822.          cea = {11, 4, 3, 1, 0};   (* Control effective addressing     *)
  2823.          aea = {11, 10, 9};        (* Alterable effective addressing   *)
  2824.          xxx = {15, 14, 13};       (* extra modes: CCR/SR/USP          *)
  2825.          (* 2 "AND" masks to turn off switch bits for shift/rotate *)
  2826.          Off910 = {15, 14, 13, 12, 11, 8, 7, 6, 5, 4, 3, 2, 1, 0};
  2827.          Off34 = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 2, 1, 0};
  2828.  
  2829.       VAR
  2830.          M : CARDINAL;
  2831.          i : CARDINAL;
  2832.          Ext : BITSET;      (* Bit pattern for instruction extension word *)
  2833.          ExtL : LONG;
  2834.          Xext : BITSET;
  2835.          Quick : BOOLEAN;
  2836.  
  2837.  
  2838.       PROCEDURE OperExt (VAR EA : OpConfig);
  2839.       (* Calculate Operand Extension word, and check range of Operands *)
  2840.  
  2841.          VAR
  2842.             GoodCard, GoodInt : BOOLEAN;
  2843.  
  2844.          BEGIN
  2845.             GoodCard := LongToCard (EA.Value, TempC);
  2846.             GoodInt := LongToInt (EA.Value, TempI);
  2847.  
  2848.             CASE EA.Mode OF
  2849.                AbsL     :  ;   (* No range checking needed *)
  2850.             |  AbsW     :  IF NOT GoodCard THEN
  2851.                               Error (EA.Loc, SizeErr);
  2852.                            END;
  2853.             |  ARDisp,  
  2854.                PCDisp   :  IF NOT GoodInt THEN
  2855.                               Error (EA.Loc, SizeErr);
  2856.                            END;
  2857.             |  ARDisX,
  2858.                PCDisX   :  IF (TempI < -128) OR (TempI > 127) THEN
  2859.                               Error (EA.Loc, SizeErr);
  2860.                            END;
  2861.                            Xext := BITSET (EA.Xn * 4096);
  2862.                            IF EA.X = Areg THEN
  2863.                               Xext := Xext + {15};
  2864.                            END;
  2865.                            IF EA.Xsize = Long THEN
  2866.                               Xext := Xext + {11};
  2867.                            END;
  2868.                            CardToLong (CARDINAL (Xext), TempL);
  2869.                            EA.Value[3] := TempL[3];
  2870.                            EA.Value[4] := TempL[4];
  2871.             |  Imm      :  IF Size = Long THEN
  2872.                               (* No range check needed *)
  2873.                            ELSE
  2874.                               IF GoodInt THEN
  2875.                                  IF Size = Byte THEN
  2876.                                     IF (TempI < -128) OR (TempI > 127) THEN
  2877.                                        Error (EA.Loc, SizeErr);
  2878.                                     END;
  2879.                                  END;
  2880.                               ELSE
  2881.                                  Error (EA.Loc, SizeErr);
  2882.                               END;
  2883.                            END;
  2884.             ELSE
  2885.                (* No Action *)
  2886.             END;
  2887.          END OperExt;
  2888.  
  2889.       PROCEDURE EffAdr (VAR EA : OpConfig; Bad : BITSET);
  2890.       (* adds effective address field to Op (BITSET representing opcode) *)
  2891.  
  2892.          VAR
  2893.             M : CARDINAL;
  2894.             i : CARDINAL;
  2895.             Xext : BITSET;
  2896.  
  2897.          BEGIN
  2898.             M := ORD (EA.Mode);
  2899.  
  2900.             IF M IN Bad THEN
  2901.                Error (EA.Loc, ModeErr);
  2902.                RETURN;
  2903.             ELSIF M > 11 THEN
  2904.                RETURN;
  2905.             ELSIF M < 7 THEN
  2906.                Op := Op + BITSET (M * 8) + BITSET (EA.Rn);
  2907.             ELSE   (*    7  <=  M  <=  11   *)
  2908.                Op := Op + {5, 4, 3} + BITSET (M - 7);
  2909.             END;
  2910.  
  2911.             OperExt (EA);
  2912.          END EffAdr;
  2913.  
  2914.       BEGIN   (* MergeModes *)
  2915.          ExtL := LZero;
  2916.          Quick := FALSE;
  2917.  
  2918.          (* Check for 5 special cases first *)
  2919.  
  2920.          IF (Op = RTE) OR (Op = RTR) OR (Op = RTS) OR (Op = TRAPV) THEN
  2921.             IF Src.Mode # Null THEN
  2922.                Error (SrcLoc, OperErr);
  2923.             END;
  2924.          END;
  2925.  
  2926.          IF Op = STOP THEN
  2927.             IF (Src.Mode # Imm) OR (Dest.Mode # Null) THEN
  2928.                Error (SrcLoc, OperErr);
  2929.             END;
  2930.          END;
  2931.  
  2932.          IF Op = LINK THEN
  2933.             Op := Op + BITSET (Src.Rn);
  2934.             IF (Src.Mode # ARDir) OR (Dest.Mode # Imm) THEN
  2935.                Error (SrcLoc, ModeErr);
  2936.             END;
  2937.          END;
  2938.  
  2939.          IF Op = SWAP THEN
  2940.             IF EA05f IN AddrModeB THEN
  2941.                (* Ignore, this is PEA instruction! *)
  2942.             ELSE
  2943.                Op := Op + BITSET (Src.Rn);
  2944.                IF (Src.Mode # DReg) OR (Dest.Mode # Null) THEN
  2945.                   Error (SrcLoc, OperErr);
  2946.                END;
  2947.             END;
  2948.          END;
  2949.  
  2950.          IF Op = UNLK THEN
  2951.             Op := Op + BITSET (Src.Rn);
  2952.             IF (Src.Mode # ARDir) OR (Dest.Mode # Null) THEN
  2953.                Error (SrcLoc, OperErr);
  2954.             END;
  2955.          END;
  2956.  
  2957.          (* Now do generalized address modes *)
  2958.  
  2959.          IF (Ry02 IN AddrModeA) AND (Rx911 IN AddrModeA) THEN
  2960.             Op := Op + BITSET (Src.Rn) + BITSET (Dest.Rn * 512);
  2961.             (* Now do some error checking! *)
  2962.             IF RegMem3 IN AddrModeA THEN
  2963.                IF Src.Mode = DReg THEN
  2964.                   IF Dest.Mode # DReg THEN
  2965.                      Error (DestLoc, ModeErr);
  2966.                   END;
  2967.                ELSIF Src.Mode = ARPre THEN
  2968.                   Op := Op + {3};
  2969.                   IF Dest.Mode # ARPre THEN
  2970.                      Error (DestLoc, ModeErr);
  2971.                   END;
  2972.                ELSE
  2973.                   Error (SrcLoc, OperErr);
  2974.                END;
  2975.             ELSE
  2976.                IF Src.Mode = ARPost THEN
  2977.                   IF Dest.Mode # ARPost THEN
  2978.                      Error (DestLoc, ModeErr);
  2979.                   END;
  2980.                ELSE
  2981.                   Error (SrcLoc, OperErr);
  2982.                END;
  2983.             END;
  2984.          END;
  2985.  
  2986.          IF Data911 IN AddrModeA THEN
  2987.             Quick := TRUE;
  2988.             IF Src.Mode = Imm THEN
  2989.                IF LongToInt (Src.Value, TempI) 
  2990.                 AND (TempI > 0)
  2991.                  AND (TempI <= 8) THEN
  2992.                   IF TempI < 8 THEN   (* Data of 8 is coded as 000 *)
  2993.                      Op := Op + BITSET (TempI * 512);
  2994.                   END;
  2995.                ELSE
  2996.                   Error (SrcLoc, SizeErr);
  2997.                END;
  2998.             ELSE
  2999.                Error (SrcLoc, OperErr);
  3000.             END;
  3001.          END;
  3002.  
  3003.          IF CntR911 IN AddrModeA THEN
  3004.             (* Only Shift/Rotate use this *)
  3005.             IF Dest.Mode = DReg THEN
  3006.                Op := (Op * Off910) + BITSET (Dest.Rn);
  3007.                CASE Size OF
  3008.                   Byte : ;
  3009.                |  Word : Op := Op + {6};
  3010.                |  Long : Op := Op + {7};
  3011.                END;
  3012.                IF Src.Mode = DReg THEN
  3013.                   Op := Op + {5} + BITSET (Src.Rn * 512);               
  3014.                ELSIF Src.Mode = Imm THEN
  3015.                   Quick := TRUE; 
  3016.                   (* Range Check *)
  3017.                   IF LongToInt (Src.Value, TempI) 
  3018.                    AND (TempI > 0)
  3019.                     AND (TempI <= 8) THEN
  3020.                      IF TempI < 8 THEN   (* Data of 8 is coded as 000 *)
  3021.                         Op := Op + BITSET (TempI * 512);
  3022.                      END;
  3023.                   ELSE
  3024.                      Error (SrcLoc, SizeErr);
  3025.                   END;
  3026.                ELSE
  3027.                   Error (SrcLoc, OperErr);
  3028.                END;                    
  3029.             ELSIF Dest.Mode = Null THEN
  3030.                Op := (Op * Off34) + {7, 6};
  3031.                EffAdr (Src, (mea + aea));
  3032.             ELSE
  3033.                Error (SrcLoc, OperErr);
  3034.             END;
  3035.          END;
  3036.  
  3037.          IF Data03 IN AddrModeA THEN
  3038.             Quick := TRUE;
  3039.             IF Src.Mode = Imm THEN
  3040.                IF LongToInt (Src.Value, TempI)
  3041.                 AND (TempI >= 0)
  3042.                  AND (TempI < 16) THEN
  3043.                   Op := Op + BITSET (TempI);
  3044.                ELSE
  3045.                   Error (SrcLoc, SizeErr);
  3046.                END;
  3047.             ELSE
  3048.                Error (SrcLoc, OperErr);
  3049.             END;
  3050.          END;
  3051.  
  3052.          IF Data07 IN AddrModeA THEN
  3053.             Quick := TRUE;
  3054.             IF (Src.Mode = Imm) AND (Dest.Mode = DReg) THEN
  3055.                IF LongToInt (Src.Value, TempI) 
  3056.                 AND (TempI >= -128) 
  3057.                  AND (TempI <= 127) THEN
  3058.                   Op := Op + (BITSET (TempI) * {7, 6, 5, 4, 3, 2, 1, 0}) 
  3059.                            + BITSET (Dest.Rn * 512);
  3060.                ELSE
  3061.                   Error (SrcLoc, SizeErr);
  3062.                END;
  3063.             ELSE
  3064.                Error (SrcLoc, OperErr);
  3065.             END;
  3066.          END;
  3067.  
  3068.          IF OpM68D IN AddrModeA THEN
  3069.             IF Dest.Mode = DReg THEN
  3070.                Op := Op + BITSET (Dest.Rn * 512);
  3071.                IF (Src.Mode = ARDir) AND (Size = Byte) THEN
  3072.                   Error (SrcLoc, SizeErr);
  3073.                END;
  3074.             ELSE   (* Assume Src.Mode = DReg -- Error trapped elsewhere *)
  3075.                Op := Op + BITSET (Src.Rn * 512);
  3076.                Op := Op + {8};
  3077.             END;
  3078.  
  3079.             CASE Size OF
  3080.                Byte : ;
  3081.             |  Word : Op := Op + {6};
  3082.             |  Long : Op := Op + {7};
  3083.             END;
  3084.          END;
  3085.  
  3086.          IF OpM68A IN AddrModeA THEN
  3087.             IF Dest.Mode = ARDir THEN
  3088.                Op := Op + BITSET (Dest.Rn * 512);
  3089.             ELSE
  3090.                Error (DestLoc, ModeErr);
  3091.             END;
  3092.  
  3093.             CASE Size OF
  3094.                Byte : Error (OpLoc, SizeErr);
  3095.             |  Word : Op := Op + {7, 6};
  3096.             |  Long : Op := Op + {8, 7, 6};
  3097.             END;
  3098.          END;
  3099.  
  3100.          IF OpM68C IN AddrModeA THEN
  3101.             IF Dest.Mode = DReg THEN
  3102.                Op := Op + BITSET (Dest.Rn * 512);
  3103.             ELSE
  3104.                Error (DestLoc, ModeErr);
  3105.             END;
  3106.             
  3107.             CASE Size OF
  3108.                Byte : IF Src.Mode = ARDir THEN
  3109.                          Error (OpLoc, SizeErr);
  3110.                       END;
  3111.             |  Word : Op := Op + {6};
  3112.             |  Long : Op := Op + {7};
  3113.             END;
  3114.          END;
  3115.  
  3116.          IF OpM68X IN AddrModeA THEN
  3117.             IF Src.Mode = DReg THEN
  3118.                Op := Op + BITSET (Src.Rn * 512);
  3119.             ELSE
  3120.                Error (SrcLoc, ModeErr);
  3121.             END;
  3122.  
  3123.             CASE Size OF
  3124.                Byte : Op := Op + {8};
  3125.             |  Word : Op := Op + {8, 6};
  3126.             |  Long : Op := Op + {8, 7};
  3127.             END;
  3128.          END;
  3129.  
  3130.          IF OpM68S IN AddrModeA THEN
  3131.             IF Src.Mode = DReg THEN
  3132.                Op := Op + BITSET (Src.Rn);
  3133.             ELSE
  3134.                Error (SrcLoc, ModeErr);
  3135.             END;
  3136.  
  3137.             CASE Size OF
  3138.                Byte : Error (OpLoc, SizeErr);
  3139.             |  Word : Op := Op + {7};
  3140.             |  Long :   Op := Op + {7, 6};
  3141.             END;
  3142.          END;
  3143.  
  3144.          IF OpM68R IN AddrModeA THEN
  3145.             IF (Src.Mode = DReg) AND (Dest.Mode = ARDisp) THEN
  3146.                CASE Size OF
  3147.                   Byte : Error (OpLoc, SizeErr);
  3148.                |  Word : Op := Op + {8, 7};
  3149.                |  Long : Op := Op + {8, 7, 6};
  3150.                END;
  3151.                Op := Op + BITSET (Src.Rn * 512) + BITSET (Dest.Rn);
  3152.             ELSIF (Src.Mode = ARDisp) AND (Dest.Mode = DReg) THEN
  3153.                CASE Size OF
  3154.                   Byte : Error (OpLoc, SizeErr);
  3155.                |  Word : Op := Op + {8};
  3156.                |  Long : Op := Op + {8, 6};
  3157.                END;
  3158.                Op := Op + BITSET (Src.Rn) + BITSET (Dest.Rn * 512);
  3159.             ELSE
  3160.                Error (SrcLoc, ModeErr);
  3161.             END;
  3162.          END;
  3163.  
  3164.          IF OpM37 IN AddrModeA THEN
  3165.             IF (Src.Mode = DReg) AND (Dest.Mode = DReg) THEN
  3166.                Op := Op + {6} + BITSET (Src.Rn * 512) + BITSET (Dest.Rn);
  3167.             ELSIF (Src.Mode = ARDir) AND (Dest.Mode = ARDir) THEN
  3168.                Op := Op + {6, 3} + BITSET (Src.Rn * 512) + BITSET (Dest.Rn);
  3169.             ELSIF (Src.Mode = ARDir) AND (Dest.Mode = DReg) THEN
  3170.                Op := Op + {7, 3} + BITSET (Dest.Rn * 512) + BITSET (Src.Rn);
  3171.             ELSIF (Src.Mode = DReg) AND (Dest.Mode = ARDir) THEN
  3172.                Op := Op + {7, 3} + BITSET (Src.Rn * 512) + BITSET (Dest.Rn);
  3173.             ELSE
  3174.                Error (SrcLoc, ModeErr);
  3175.             END;
  3176.          END;
  3177.  
  3178.          IF Bit811 IN AddrModeB THEN
  3179.             IF Src.Mode = DReg THEN
  3180.                Op := Op + {8} + BITSET (Src.Rn * 512);
  3181.             ELSIF Src.Mode = Imm THEN
  3182.                Op := Op + {11};
  3183.             ELSE
  3184.                Error (SrcLoc, ModeErr);
  3185.             END;
  3186.          END;
  3187.  
  3188.          IF Size67 IN AddrModeB THEN
  3189.             CASE Size OF
  3190.                Byte : ;(* No action -- bits already 0's *)
  3191.             |  Word : Op := Op + {6};
  3192.             |  Long : Op := Op + {7};
  3193.             END;
  3194.          END;
  3195.  
  3196.          IF Size6 IN AddrModeB THEN
  3197.             CASE Size OF
  3198.                Byte : Error (OpLoc, SizeErr);
  3199.             |  Word : (* No Action -- BIT is already 0 *)
  3200.             |  Long : Op := Op + {6};
  3201.             END;
  3202.          END;
  3203.  
  3204.          IF Size1213A IN AddrModeB THEN
  3205.             CASE Size OF
  3206.                Byte : Op := Op + {12};
  3207.             |  Word : Op := Op + {13, 12};
  3208.             |  Long : Op := Op + {13};
  3209.             END;
  3210.          END;
  3211.  
  3212.          IF Size1213 IN AddrModeB THEN
  3213.             Op := Op + BITSET (Dest.Rn * 512);
  3214.             CASE Size OF
  3215.                Byte : Error (OpLoc, SizeErr);
  3216.             |  Word : Op := Op + {13, 12};
  3217.             |  Long : Op := Op + {13};
  3218.             END;
  3219.          END;
  3220.  
  3221.          IF EA05a IN AddrModeB THEN
  3222.             IF (Dest.Mode = DReg) OR (Dest.Mode = ARDir) THEN
  3223.                EffAdr (Src, ea);
  3224.             ELSE
  3225.                Error (DestLoc, ModeErr);
  3226.             END;
  3227.          END;
  3228.  
  3229.          IF EA05b IN AddrModeB THEN
  3230.             IF Dest.Mode = DReg THEN
  3231.                EffAdr (Src, dea);
  3232.                Op := Op + BITSET (Dest.Rn * 512);
  3233.             ELSE
  3234.                Error (DestLoc, ModeErr);
  3235.             END;
  3236.          END;
  3237.  
  3238.          IF EA05c IN AddrModeB THEN
  3239.             EffAdr (Dest, {11, 1});
  3240.          END;
  3241.  
  3242.          IF EA05d IN AddrModeB THEN
  3243.             EffAdr (Dest, aea);
  3244.             IF (Dest.Mode = ARDir) AND (Size = Byte) THEN
  3245.                Error (OpLoc, SizeErr);
  3246.             END;
  3247.          END;
  3248.  
  3249.          IF EA05e IN AddrModeB THEN
  3250.             IF Dest.Mode = Null THEN
  3251.                EffAdr (Src, (dea + aea));
  3252.             ELSIF (Src.Mode = Imm) OR (Src.Mode = DReg) THEN
  3253.                EffAdr (Dest, (dea + aea));
  3254.             ELSE
  3255.                Error (SrcLoc, ModeErr);
  3256.             END;
  3257.          END;
  3258.  
  3259.          IF EA05f IN AddrModeB THEN   (* LEA & PEA / JMP & JSR *)
  3260.             EffAdr (Src, cea);
  3261.             IF Rx911 IN AddrModeA THEN
  3262.                IF Dest.Mode = ARDir THEN
  3263.                   Op := Op + BITSET (Dest.Rn * 512);
  3264.                ELSE
  3265.                   Error (DestLoc, ModeErr);
  3266.                END;
  3267.             ELSE
  3268.                IF Dest.Mode # Null THEN
  3269.                   Error (DestLoc, OperErr);
  3270.                END;
  3271.             END;
  3272.          END;
  3273.  
  3274.          IF EA05x IN AddrModeB THEN
  3275.             IF Dest.Mode = DReg THEN
  3276.                EffAdr (Src, dea);
  3277.             ELSIF Src.Mode = DReg THEN
  3278.                EffAdr (Dest, mea + aea);               
  3279.             ELSE
  3280.                Error (SrcLoc, OperErr);
  3281.             END;
  3282.          END;
  3283.  
  3284.          IF EA05y IN AddrModeB THEN
  3285.             IF Dest.Mode = DReg THEN
  3286.                EffAdr (Src, ea);
  3287.                IF (Src.Mode = ARDir) AND (Size = Byte) THEN
  3288.                   Error (OpLoc, SizeErr);
  3289.                END;
  3290.             ELSIF Src.Mode = DReg THEN
  3291.                EffAdr (Dest, (mea + aea));               
  3292.             ELSE
  3293.                Error (SrcLoc, ModeErr);
  3294.             END;
  3295.          END;
  3296.  
  3297.          IF EA05z IN AddrModeB THEN
  3298.             IF Src.Mode = MultiM THEN
  3299.                EffAdr (Dest, (mea + aea + {3}));
  3300.                GetMultReg (SrcOp, (Dest.Mode = ARPre), SrcLoc, Ext);
  3301.             ELSIF Dest.Mode = MultiM THEN
  3302.                EffAdr (Src, (mea + {11, 4}));
  3303.                GetMultReg (DestOp, (Src.Mode = ARPre), DestLoc, Ext);
  3304.                Op := Op + {10};   (* set direction *)
  3305.             ELSE
  3306.                Error (SrcLoc, OperErr);
  3307.             END;
  3308.  
  3309.             INC (nO, 4);   (* extension is part of OpCode *)
  3310.             INC (InstSize, 2);
  3311.             CardToLong (CARDINAL (Ext), ExtL);
  3312.          END;
  3313.  
  3314.          IF EA611 IN AddrModeB THEN
  3315.             IF Dest.Mode = CCR THEN
  3316.                Op := {14, 10, 7, 6};
  3317.                EffAdr (Src, dea);               
  3318.             ELSIF Dest.Mode = SR THEN
  3319.                Op := {14, 10, 9, 7, 6};
  3320.                EffAdr (Src, dea);               
  3321.             ELSIF Src.Mode = SR THEN
  3322.                Op := {14, 7, 6};
  3323.                EffAdr (Dest, dea + aea);               
  3324.             ELSIF Dest.Mode = USP THEN
  3325.                Op := {14, 11, 10, 9, 6, 5};
  3326.                IF Src.Mode = ARDir THEN
  3327.                   Op := Op + BITSET (Src.Rn);
  3328.                ELSE
  3329.                   Error (SrcLoc, ModeErr);
  3330.                END;
  3331.             ELSIF Src.Mode = USP THEN
  3332.                Op := {14, 11, 10, 9, 6, 5, 3};
  3333.                IF Dest.Mode = ARDir THEN
  3334.                   Op := Op + BITSET (Dest.Rn);
  3335.                ELSE
  3336.                   Error (DestLoc, ModeErr);
  3337.                END;
  3338.             ELSE
  3339.                EffAdr (Src, (ea + xxx));
  3340.                IF (Size = Byte) AND (Src.Mode = ARDir) THEN
  3341.                   Error (SrcLoc, SizeErr);
  3342.                END;
  3343.  
  3344.                M := ORD (Dest.Mode);
  3345.                IF (M IN (dea + aea)) OR (M > 11) THEN
  3346.                   Error (DestLoc, ModeErr);
  3347.                ELSIF M < 7 THEN
  3348.                   Op := Op + BITSET (M * 64) + BITSET (Dest.Rn * 512);
  3349.                ELSE   (*  7  <=  M  <=  11  *)
  3350.                   Op := Op + {8, 7, 6} + BITSET ((M - 7) * 512);
  3351.                END;
  3352.  
  3353.                OperExt (Dest);
  3354.             END;
  3355.          END;
  3356.  
  3357.          IF (Dest.Mode = CCR) AND (Src.Mode = Imm) THEN
  3358.             IF (Size67 IN AddrModeB) 
  3359.              AND (EA05e IN AddrModeB) 
  3360.               AND (Exten IN AddrModeB) THEN
  3361.                IF 10 IN Op THEN   (* NOT ANDI/EORI/ORI *)
  3362.                   Error (DestLoc, ModeErr);
  3363.                ELSE
  3364.                   Op := Op * {15, 14, 13, 12, 11, 10, 9, 8};   (* AND mask *)
  3365.                   Op := Op + {5, 4, 3, 2};                     (*  OR mask *)
  3366.                END;
  3367.             END;
  3368.          END;
  3369.  
  3370.          IF (Dest.Mode = SR) AND (Src.Mode = Imm) THEN
  3371.             IF (Size67 IN AddrModeB) 
  3372.              AND (EA05e IN AddrModeB) 
  3373.               AND (Exten IN AddrModeB) THEN
  3374.                IF 10 IN Op THEN   (* NOT ANDI/EORI/ORI *)
  3375.                   Error (DestLoc, ModeErr);
  3376.                ELSE
  3377.                   Op := Op * {15, 14, 13, 12, 11, 10, 9, 8};   (* AND mask *)
  3378.                   Op := Op + {6, 5, 4, 3, 2};                  (*  OR mask *)
  3379.                END;
  3380.             END;
  3381.          END;
  3382.  
  3383.          CardToLong (CARDINAL (Op), ObjOp);
  3384.          INC (InstSize, 2);
  3385.          INC (nO, 4);
  3386.          IF nO > 4 THEN
  3387.             FOR i := 1 TO 4 DO   (* move ObjOp -- make room for extension *)
  3388.                ObjOp[i + 4] := ObjOp[i];
  3389.                ObjOp[i] := ExtL[i];
  3390.             END;
  3391.          END;
  3392.  
  3393.          nS := GetInstModeSize (Src.Mode, Size, InstSize);
  3394.          ObjSrc := Src.Value;
  3395.          nD := GetInstModeSize (Dest.Mode, Size, InstSize);
  3396.          ObjDest := Dest.Value;
  3397.  
  3398.          IF Quick THEN
  3399.             InstSize := 2;
  3400.             nS := 0;   nD := 0;
  3401.          END;
  3402.          CardToLong (InstSize, AddrAdv);
  3403.    
  3404.       END MergeModes;
  3405.  
  3406.  
  3407.  
  3408.    TYPE
  3409.       DirType = (None, Org, Equ, DC, DS, Even, End);
  3410.  
  3411.    PROCEDURE ObjDir (OpCode : TOKEN; SrcOp : OPERAND; Size : SizeType;
  3412.                      VAR AddrCnt, ObjOp, ObjSrc, ObjDest : LONG;
  3413.                      VAR   nA,      nO,    nS,     nD    : CARDINAL) : DirType;
  3414.    (* Generates Object Code for Assembler Directives *)
  3415.  
  3416.       VAR
  3417.          Dir : DirType;
  3418.          i, j : CARDINAL;
  3419.          LongString : ARRAY [1..20] OF INTEGER;
  3420.  
  3421.       BEGIN
  3422.          AddrAdv := LZero;
  3423.  
  3424.          IF CompareStr (OpCode, "ORG") = 0 THEN
  3425.             GetValue (SrcOp, AddrCnt);
  3426.             AddrBoundW (AddrCnt);
  3427.             Dir := Org;
  3428.          ELSIF CompareStr (OpCode, "EQU") = 0 THEN
  3429.             GetValue (SrcOp, ObjSrc);
  3430.             nS := 8;
  3431.             Dir := Equ;
  3432.          ELSIF CompareStr (OpCode, "DC") = 0 THEN
  3433.             CASE Size OF
  3434.                Word  :  AddrBoundW (AddrCnt);
  3435.             |  Long  :  AddrBoundL (AddrCnt);
  3436.             |  Byte  :  ;
  3437.             END;
  3438.             
  3439.             IF SrcOp[0] = Quote THEN   (* String constant *)
  3440.                TempC := Length (SrcOp);
  3441.                IF TempC > 2 THEN
  3442.                   InstSize := TempC - 2;   (* Don't count the Quotes *)
  3443.                END;
  3444.                   
  3445.                i := 1;   j := 20;
  3446.                WHILE i <= InstSize DO   (* Change from ASCII to LONG *)
  3447.                   CardToLong (ORD (SrcOp[i]), TempL);
  3448.                   LongString[j] := TempL[2];
  3449.                   LongString[j - 1] := TempL[1];
  3450.                   INC (i);   DEC (j, 2);
  3451.                END;
  3452.  
  3453.                i := 1;   INC (j);
  3454.                WHILE j <= 20 DO   (* Left Justify String *)
  3455.                   LongString[i] := LongString[j];
  3456.                   INC (i);   INC (j);
  3457.                END;
  3458.  
  3459.                DEC (i);
  3460.                WHILE i > 16 DO   (* Transfer 2 bytes to OpCode *)
  3461.                   ObjOp[i - 16] := LongString[i];
  3462.                   INC (nO);   DEC (i);
  3463.                END;
  3464.  
  3465.                WHILE i > 8 DO   (* Transfer 4 bytes to Source Operand *)
  3466.                   ObjSrc[i - 8] := LongString[i];
  3467.                   INC (nS);   DEC (i);
  3468.                END;
  3469.                                              
  3470.                WHILE i > 0 DO   (* Transfer 4 bytes to Destination Operand *)
  3471.                   ObjDest[i] := LongString[i];
  3472.                   INC (nD);   DEC (i);
  3473.                END;
  3474.  
  3475.                IF SrcOp[InstSize + 1] # Quote THEN
  3476.                   Error ((SrcLoc + InstSize + 1), OperErr);
  3477.                END;
  3478.             ELSE   (* not a string constant *)
  3479.                GetValue (SrcOp, ObjSrc);
  3480.                InstSize := ORD (Size);
  3481.                nS := InstSize * 2;
  3482.             END;
  3483.             CardToLong (InstSize, AddrAdv);
  3484.             nA := 6;
  3485.             Dir := DC;
  3486.          ELSIF CompareStr (OpCode, "DS") = 0 THEN
  3487.             GetValue (SrcOp, AddrAdv);
  3488.             nA := 6;   nS := 2;   ObjSrc := LZero;
  3489.             Dir := DS;
  3490.          ELSIF CompareStr (OpCode, "EVEN") = 0 THEN
  3491.             AddrBoundW (AddrCnt);
  3492.             Dir := Even;
  3493.          ELSIF CompareStr (OpCode, "END") = 0 THEN
  3494.             nA := 6;
  3495.             Dir := End;
  3496.          ELSE
  3497.             Dir := None;
  3498.          END;
  3499.  
  3500.          RETURN (Dir);
  3501.       END ObjDir;
  3502.  
  3503.  
  3504.  
  3505.    PROCEDURE AdvAddrCnt (VAR AddrCnt : LONG);
  3506.    (* Advances the address counter based on the length of the instruction *)
  3507.       BEGIN
  3508.          LongAdd (AddrCnt, AddrAdv, AddrCnt);
  3509.       END AdvAddrCnt;
  3510.  
  3511.  
  3512.  
  3513.    PROCEDURE GetObjectCode (Label, OpCode : TOKEN;
  3514.                             SrcOp, DestOp : OPERAND;
  3515.                             VAR AddrCnt, ObjOp, ObjSrc, ObjDest : LONG;
  3516.                             VAR   nA,      nO,    nS,     nD    : CARDINAL);
  3517.    (* Determines the object code for the operation as well as the operands *)
  3518.    (* Returns each (up to 3 fields), along with the length of each.        *) 
  3519.  
  3520.       VAR
  3521.          Dummy : BOOLEAN;
  3522.          Dir : DirType;
  3523.  
  3524.       BEGIN
  3525.          AddrAdv := LZero;
  3526.          InstSize := 0;
  3527.          nA := 0;   nO := 0;   nS := 0;   nD := 0;
  3528.  
  3529.          IF Length (OpCode) = 0 THEN
  3530.             (* ensure no code generated *)
  3531.             RETURN;
  3532.          END;
  3533.          
  3534.          GetSize (OpCode, Size);
  3535.  
  3536.          Dir := ObjDir (OpCode, SrcOp, Size,
  3537.                         AddrCnt, ObjOp, ObjSrc, ObjDest,
  3538.                           nA,      nO,    nS,     nD    );
  3539.  
  3540.          IF (Length (Label) # 0) AND (Dir # Equ) THEN
  3541.          (* Check for phase error *)
  3542.             Dummy := ReadSymTab (Label, TempL, Dummy);
  3543.             IF LongCompare (TempL, AddrCnt) # 0 THEN
  3544.                Error (0, Phase);
  3545.             END;
  3546.          END;
  3547.  
  3548.          IF Dir = None THEN   (* Instruction *)
  3549.             AddrBoundW (AddrCnt);   
  3550.          ELSE
  3551.             RETURN;
  3552.          END;
  3553.  
  3554.          Instructions (OpCode, OpLoc, Op, AddrModeA, AddrModeB);       
  3555.          Src.Loc := SrcLoc;   Dest.Loc := DestLoc;  
  3556.          GetOperand (SrcOp, Src);   (* Src & Dest are RECORDS *)
  3557.          GetOperand (DestOp, Dest);
  3558.  
  3559.          IF DecBr IN AddrModeA THEN   (* Decrement & Branch *)
  3560.             IF Src.Mode # DReg THEN
  3561.                Error (SrcLoc, ModeErr);
  3562.             END;
  3563.  
  3564.             BrValue := Dest.Value;
  3565.             TempL := AddrCnt;
  3566.             TempC := 32767;   (* Maximum Branch *)
  3567.             LongInc (TempL, 2);   (* move past instruction for Rel Adr Calc *)
  3568.  
  3569.             IF LongCompare (BrValue, TempL) < 0 THEN
  3570.                RevBr := TRUE;
  3571.                LongSub (TempL, BrValue, BrValue);
  3572.                INC (TempC);   (* can branch 1 farther in reverse *)
  3573.             ELSE
  3574.                RevBr := FALSE;
  3575.                LongSub (BrValue, TempL, BrValue);
  3576.             END;
  3577.  
  3578.             CardToLong (TempC, TempL);   (* Maximum Branch distance *)
  3579.  
  3580.             IF LongCompare (BrValue, TempL) > 0 THEN
  3581.                Error (DestLoc, BraErr);
  3582.             END;
  3583.             IF RevBr THEN   (* Make Negative *)
  3584.                LongSub (LZero, BrValue, BrValue)
  3585.             END;
  3586.  
  3587.             CardToLong (4, AddrAdv);
  3588.             nA := 6;   nO := 4;   nS := 4;  
  3589.             CardToLong (CARDINAL (Op + BITSET (Src.Rn)), ObjOp);
  3590.             ObjSrc := BrValue;
  3591.             RETURN;
  3592.          END;
  3593.  
  3594.          IF Brnch IN AddrModeA THEN   (* Branch *)
  3595.             BrValue := Src.Value;   (* Destination of Branch *)
  3596.             TempL := AddrCnt;
  3597.             LongInc (TempL, 2);
  3598.  
  3599.             IF Size # Byte THEN   (* Byte Size ---> Short Branch *)
  3600.                TempC := 32767;   (* Set maximum branch distance *)
  3601.             ELSE                  
  3602.                TempC := 127;
  3603.             END;
  3604.  
  3605.             CASE LongCompare (BrValue, TempL) OF
  3606.                -1 :  (* Reverse Branch *)
  3607.                      RevBr := TRUE;
  3608.                      INC (TempC);   (* can branch 1 farther in reverse *)
  3609.                      LongSub (TempL, BrValue, BrValue);
  3610.             |  +1 :  (* Forward Branch *)
  3611.                      RevBr := FALSE;
  3612.                      LongSub (BrValue, TempL, BrValue);
  3613.             |   0 :  IF Size = Byte THEN
  3614.                         Error (SrcLoc, BraErr);
  3615.                      END;
  3616.             END;
  3617.          
  3618.             CardToLong (TempC, TempL);
  3619.  
  3620.             IF LongCompare (BrValue, TempL) > 0 THEN
  3621.                Error (SrcLoc, BraErr);
  3622.             END;
  3623.  
  3624.             IF RevBr THEN
  3625.                LongSub (LZero, BrValue, BrValue);   (* Make negative *)
  3626.             END;
  3627.  
  3628.             IF Size # Byte THEN
  3629.                InstSize := 4;
  3630.                nS := 4;
  3631.                ObjSrc := BrValue; 
  3632.             ELSE
  3633.                InstSize := 2;
  3634.                Dummy := LongToInt (BrValue, TempI);
  3635.                Op := Op + (BITSET (TempI) * {7, 6, 5, 4, 3, 2, 1, 0});
  3636.             END;
  3637.  
  3638.             nA := 6;   nO := 4;
  3639.             CardToLong (InstSize, AddrAdv);
  3640.             CardToLong (CARDINAL (Op), ObjOp);
  3641.             RETURN;
  3642.          END;
  3643.  
  3644.          nA := 6;
  3645.          IF (Op = JMP) OR (Op = JSR) THEN   (* Allows for 'JMP.S' *)
  3646.             IF (Size = Byte) AND (Src.Mode = AbsL) THEN
  3647.                Src.Mode := AbsW;
  3648.             END;
  3649.          END;
  3650.          MergeModes (SrcOp, DestOp, ObjOp, ObjSrc, ObjDest, nO, nS, nD);
  3651.  
  3652.       END GetObjectCode;
  3653.  
  3654.  
  3655. BEGIN   (* MODULE Initialization *)
  3656.    LongClear (LZero);   (* Used as a constant *)
  3657.    AddrCnt := LZero;
  3658.    Pass2 := FALSE;
  3659. END CodeGenerator.
  3660.  
  3661. IMPLEMENTATION MODULE SyntaxAnalyzer;
  3662. (* Analyzes the operands to provide information for CodeGenerator *)
  3663.  
  3664.    FROM Conversions IMPORT
  3665.       StrToCard;
  3666.  
  3667.    FROM Strings IMPORT
  3668.       Length;
  3669.       
  3670.    FROM LongNumbers IMPORT
  3671.       LONG, LongAdd, LongSub, CardToLong, StringToLong;
  3672.  
  3673.    FROM SymbolTable IMPORT
  3674.       SortSymTab, ReadSymTab;
  3675.    
  3676.    FROM ErrorX68 IMPORT
  3677.       ErrorType, Error;
  3678.  
  3679.    FROM Parser IMPORT
  3680.       OPERAND, SrcLoc;
  3681.  
  3682.    FROM CodeGenerator IMPORT
  3683.       LZero, AddrCnt, Pass2;   (* BOOLEAN Switch *)
  3684.  
  3685.  
  3686.    CONST
  3687.       Zero = 30H;   (* The Ordinal value of the Character '0' *)
  3688.       Seven = 37H;   (* The Ordinal value of the Character '7' *)
  3689.       Quote = 47C;
  3690.  
  3691. (*---
  3692.    TYPE
  3693.       OpMode = (DReg,      (* Data Register *)
  3694.                 ARDir,     (* Address Register Direct *)
  3695.                 ARInd,     (* Address Register Indirect *)
  3696.                 ARPost,    (* Address Register with Post-Increment *)
  3697.                 ARPre,     (* Address Register with Pre-Decrement *)
  3698.                 ARDisp,    (* Address Register with Displacement *)
  3699.                 ARDisX,    (* Address Register with Disp. & Index *)
  3700.                 AbsW,      (* Absolute Word (16-bit Address) *)
  3701.                 AbsL,      (* Absolute Word (32-bit Address) *)
  3702.                 PCDisp,    (* Program Counter Relative, with Displacement *)
  3703.                 PCDisX,    (* Program Counter Relative, with Disp. & Index *)
  3704.                 Imm,       (* Immediate *)
  3705.                 MultiM,    (* Multiple Register Move *)
  3706.                 SR,        (* Status Register *)
  3707.                 CCR,       (* Condition Code Register *)
  3708.                 USP,       (* User's Stack Pointer *)
  3709.                 Null);     (* Error Condition, or Operand missing *)
  3710.  
  3711.       Xtype = (X0, Dreg, Areg);
  3712.       SizeType = (S0, Byte, Word, S3, Long);
  3713.  
  3714.       OpConfig = RECORD                 (* OPERAND CONFIGURATION *)
  3715.                     Mode : OpMode;
  3716.                     Value : LONG;
  3717.                     Loc : CARDINAL;     (* Location of Operand on line *)
  3718.                     Rn : CARDINAL;      (* Register number *)
  3719.                     Xn : CARDINAL;      (* Index Reg. nbr. *)
  3720.                     Xsize : SizeType;   (* size of Index *)
  3721.                     X : Xtype;          (* Is index Data or Address reg? *)
  3722.                  END;
  3723.  
  3724.  
  3725.    VAR
  3726.       Size : SizeType;       (* size for OpCode *)  
  3727.       AbsSize : SizeType;    (* size of operand (Absolute only) *)
  3728.       InstSize : CARDINAL;   (* Size of instruction, including operands *)
  3729.       AddrModeA : ModeA;     (* Addressing modes for this instruction *)
  3730.       AddrModeB : ModeB;     (*               ditto                   *)
  3731.       Op : BITSET;           (* Raw bit pattern for OpCode *)
  3732.       Src, Dest : OpConfig;
  3733.                                                                       ---*)
  3734.  
  3735.  
  3736.    PROCEDURE CalcValue (Operand : OPERAND; VAR Value : LONG);
  3737.    (* Calculates left and right values for GetValue *)
  3738.  
  3739.       VAR
  3740.          Full : BOOLEAN;
  3741.          Neg : BOOLEAN;
  3742.          Dup : BOOLEAN;
  3743.          Num : CARDINAL;
  3744.          NumSyms : CARDINAL;
  3745.  
  3746.       BEGIN
  3747.          IF Operand[0] = '-' THEN
  3748.             Neg := TRUE;
  3749.             Operand[0] := '0';
  3750.          ELSE
  3751.             Neg := FALSE;
  3752.          END;
  3753.  
  3754.          IF StrToCard (Operand, Num) THEN   
  3755.             (* It is a number *)
  3756.             CardToLong (Num, Value);
  3757.             IF Neg THEN
  3758.                LongSub (LZero, Value, Value);
  3759.             END;
  3760.          ELSIF StringToLong (Operand, Value) THEN   
  3761.             (* It is a HEX number *)
  3762.          ELSIF (Operand[0] = Quote) AND (Operand[2] = Quote) THEN
  3763.             CardToLong (ORD (Operand[1]), Value);
  3764.          ELSIF (Length (Operand) = 1) AND (Operand[0] = '*') THEN
  3765.             Value := AddrCnt;
  3766.          ELSE   
  3767.             (* It is a label, but may be undefined! *)
  3768.             IF NOT Pass2 THEN
  3769.                SortSymTab (NumSyms);
  3770.             END;
  3771.             IF NOT ReadSymTab (Operand, Value, Dup) THEN
  3772.                Error (SrcLoc, Undef);
  3773.             END;
  3774.             IF Dup THEN
  3775.                Error (SrcLoc, SymDup);
  3776.             END;
  3777.          END;
  3778.       END CalcValue;
  3779.  
  3780.  
  3781.  
  3782.    PROCEDURE GetValue (Operand : OPERAND; VAR Value : LONG);
  3783.    (* determines value of operand (in Decimal, HEX, or via Symbol Table) *)
  3784.  
  3785.       VAR
  3786.          TempOp : OPERAND;
  3787.          TempVal : LONG;
  3788.          c, op : CHAR;
  3789.          i, j : CARDINAL;
  3790.          InQuotes : BOOLEAN;
  3791.  
  3792.       BEGIN
  3793.          i := 0;   
  3794.          Value := LZero;
  3795.          InQuotes := FALSE;
  3796.          op := '+';
  3797.          REPEAT
  3798.             j := 0;
  3799.             LOOP
  3800.                c := Operand[i];
  3801.                TempOp[j] := c;
  3802.                IF c = Quote THEN
  3803.                   InQuotes := NOT InQuotes;
  3804.                END;
  3805.                INC (i);   INC (j);
  3806.                IF c = 0C THEN
  3807.                   EXIT;
  3808.                END;
  3809.                IF (c = '+') AND (NOT InQuotes) THEN
  3810.                   EXIT;
  3811.                END;
  3812.                IF (c = '-') AND (i > 1) AND (NOT InQuotes) THEN
  3813.                   EXIT;
  3814.                END;
  3815.             END;
  3816.             TempOp[j - 1] := 0C;   (* in case c is +/- *)
  3817.             CalcValue (TempOp, TempVal);
  3818.             IF op = '-' THEN
  3819.                LongSub (Value, TempVal, Value);
  3820.             ELSE
  3821.                LongAdd (Value, TempVal, Value);
  3822.             END;
  3823.             op := c;
  3824.          UNTIL op = 0C;
  3825.       END GetValue;
  3826.  
  3827.  
  3828.  
  3829.    PROCEDURE GetSize (VAR Symbol : ARRAY OF CHAR; VAR Size : SizeType);
  3830.    (* determines size of opcode/operand: Byte, Word, Long *)
  3831.  
  3832.       VAR
  3833.          i : CARDINAL;
  3834.          c : CHAR;
  3835.  
  3836.       BEGIN
  3837.          i := 0;
  3838.          REPEAT
  3839.             c := Symbol[i];
  3840.             INC (i);
  3841.          UNTIL (c = 0C) OR (c = '.');
  3842.  
  3843.          IF c = 0C THEN
  3844.             Size := Word;   (* Default to size Word = 16 bits *)
  3845.          ELSE
  3846.             c := Symbol[i];   (* Record size extension *)
  3847.             Symbol[i - 1] := 0C;   (* Chop size extension off *)
  3848.             IF (c = 'B') OR (c = 'S') THEN   (* Byte or Short Branch/Jump *)
  3849.                Size := Byte;
  3850.             ELSIF c = 'L' THEN
  3851.                Size := Long;
  3852.             ELSE
  3853.                Size := Word;   (* Default size *)
  3854.             END;
  3855.          END;
  3856.       END GetSize;
  3857.  
  3858.  
  3859.  
  3860.    PROCEDURE GetAbsSize (VAR Symbol : ARRAY OF CHAR; VAR AbsSize : SizeType);
  3861.    (* determines size of operand: Word or Long *)
  3862.  
  3863.       VAR
  3864.          i : CARDINAL;
  3865.          c : CHAR;
  3866.          ParCnt : INTEGER;
  3867.  
  3868.       BEGIN
  3869.          ParCnt := 0;
  3870.          i := 0;
  3871.          REPEAT
  3872.             c := Symbol[i];
  3873.             IF c = '(' THEN
  3874.                INC (ParCnt);
  3875.             END;
  3876.             IF c = ')' THEN
  3877.                DEC (ParCnt);
  3878.             END;
  3879.             INC (i);
  3880.          UNTIL (c = 0C) OR ((c = '.') AND (ParCnt = 0));
  3881.  
  3882.          IF c = 0C THEN
  3883.             AbsSize := Long;
  3884.          ELSE
  3885.             c := Symbol[i];   (* Record size extension *)
  3886.             Symbol[i - 1] := 0C;   (* Chop size extension off *)
  3887.             IF (c = 'W') OR (c = 'S') THEN
  3888.                AbsSize := Word;
  3889.             ELSE
  3890.                AbsSize := Long;
  3891.             END;
  3892.          END;
  3893.       END GetAbsSize;
  3894.  
  3895.  
  3896.  
  3897.    PROCEDURE GetInstModeSize (Mode : OpMode; Size : SizeType;
  3898.                               VAR InstSize : CARDINAL) : CARDINAL;
  3899.    (* Determines the size for the various instruction modes.    *)
  3900.  
  3901.       VAR
  3902.          n : CARDINAL;
  3903.  
  3904.       BEGIN
  3905.          CASE Mode OF
  3906.             ARDisp,
  3907.             ARDisX,
  3908.             PCDisp,
  3909.             PCDisX,
  3910.             AbsW     :  n := 2;
  3911.          |  AbsL     :  n := 4;
  3912.          |  MultiM   :  IF Pass2 THEN
  3913.                            n := 0;   (* accounted for by code generator *)
  3914.                         ELSE
  3915.                            n := 2;
  3916.                         END;
  3917.          |  Imm      :  IF Size = Long THEN
  3918.                            n := 4;
  3919.                         ELSE
  3920.                            n := 2;
  3921.                         END;
  3922.          ELSE
  3923.                         n := 0;
  3924.          END;
  3925.  
  3926.          INC (InstSize, n);
  3927.          RETURN (n * 2);
  3928.       END GetInstModeSize;
  3929.  
  3930.  
  3931.  
  3932.    PROCEDURE GetOperand (Oper : OPERAND; VAR Op : OpConfig);  
  3933.    (* Finds mode and value for source or destination operand *)
  3934.  
  3935.       VAR
  3936.          ch : CHAR;
  3937.          C : CARDINAL;   (* holds the ordinal value of a charcter *)
  3938.          i, j : CARDINAL;
  3939.          Len : CARDINAL;   (* Calculated Length of Oper *)
  3940.          TempOp : OPERAND;
  3941.          MultFlag : BOOLEAN;
  3942.  
  3943.       BEGIN
  3944.          Op.Mode := Null;   Op.X := X0;
  3945.          Len := Length (Oper);
  3946.  
  3947.          IF Len = 0 THEN
  3948.             RETURN;   
  3949.          END;
  3950.  
  3951.          GetAbsSize (Oper, AbsSize);
  3952.  
  3953.          IF Oper[0] = '#' THEN   (* Immediate *)
  3954.             IF Pass2 THEN
  3955.                i := 0;
  3956.                REPEAT
  3957.                   INC (i);
  3958.                   Oper[i - 1] := Oper[i];
  3959.                UNTIL Oper[i] = 0C;
  3960.                GetValue (Oper, Op.Value);
  3961.             END;
  3962.             Op.Mode := Imm;
  3963.             RETURN;
  3964.          END;
  3965.  
  3966.          IF Len = 2 THEN   (* possible Addr or Data Register *)
  3967.             C := ORD (Oper[1]);
  3968.             IF (Oper[0] = 'S') AND (Oper[1] = 'R') THEN
  3969.                (* Status Register *)
  3970.                Op.Mode := SR;
  3971.                RETURN;
  3972.             ELSIF (Oper[0] = 'S') AND (Oper[1] = 'P') THEN
  3973.                (* Stack Pointer *)
  3974.                Op.Mode := ARDir;
  3975.                Op.Rn := 7;
  3976.                RETURN;
  3977.             ELSIF (C >= Zero) AND (C <= Seven) THEN   
  3978.                (* Looks Like an Addr or Data Reg *)
  3979.                IF Oper[0] = 'A' THEN   (* Address Register *)
  3980.                   Op.Mode := ARDir;
  3981.                   Op.Rn := C - Zero;
  3982.                   RETURN;
  3983.                ELSIF Oper[0] = 'D' THEN   (* Data Register *)
  3984.                   Op.Mode := DReg;
  3985.                   Op.Rn := C - Zero;
  3986.                   RETURN;
  3987.                ELSE
  3988.                   (* may be a label -- ignore for now *)
  3989.                END;
  3990.             ELSE
  3991.                (* may be a label -- ignore for now *)
  3992.             END;
  3993.          END;
  3994.  
  3995.          IF Len = 3 THEN
  3996.             IF (Oper[0] = 'C') AND (Oper[1] = 'C') AND (Oper[2] = 'R') THEN
  3997.                (* Condition Code Register *)
  3998.                Op.Mode := CCR;
  3999.                RETURN;
  4000.             ELSIF (Oper[0] = 'U') AND (Oper[1] = 'S') AND (Oper[2] = 'P') THEN
  4001.                (* User's Stack Pointer *)
  4002.                Op.Mode := USP;
  4003.                RETURN;
  4004.             ELSE
  4005.                (* may be a label -- ignore for now *)
  4006.             END;
  4007.          END;
  4008.  
  4009.          IF (Len = 4) AND (Oper[0] = '(') AND (Oper[3] = ')') THEN
  4010.             IF (Oper[1] = 'S') AND (Oper[2] = 'P') THEN
  4011.                Op.Mode := ARInd;
  4012.                Op.Rn := 7;
  4013.                RETURN;
  4014.             ELSIF Oper[1] = 'A' THEN
  4015.                C := ORD (Oper[2]);
  4016.                IF (C >= Zero) AND (C <= Seven) THEN
  4017.                   Op.Mode := ARInd;
  4018.                   Op.Rn := C - Zero;
  4019.                   RETURN;
  4020.                ELSE
  4021.                   Error (Op.Loc, SizeErr);
  4022.                   RETURN;
  4023.                END;   
  4024.             ELSE
  4025.                Error (Op.Loc, AddrErr);
  4026.                RETURN;
  4027.             END;
  4028.          END;
  4029.           
  4030.          IF (Len = 5) AND (Oper[0] = '(')
  4031.           AND (Oper[3] = ')') AND (Oper[4] = '+') THEN
  4032.            (* Address Indirect with Post Inc *)
  4033.             IF (Oper[1] = 'S') AND (Oper[2] = 'P') THEN
  4034.                (* System Stack Pointer *)
  4035.                Op.Mode := ARPost;
  4036.                Op.Rn := 7;
  4037.                RETURN
  4038.             ELSIF Oper[1] = 'A' THEN
  4039.                C := ORD (Oper[2]);
  4040.                IF (C >= Zero) AND (C <= Seven) THEN
  4041.                   Op.Mode := ARPost;
  4042.                   Op.Rn := C - Zero;
  4043.                   RETURN;
  4044.                ELSE
  4045.                   Error (Op.Loc, SizeErr);
  4046.                   RETURN;
  4047.                END;   
  4048.             ELSE
  4049.                Error (Op.Loc, AddrErr);
  4050.                RETURN;
  4051.             END;
  4052.          END;
  4053.  
  4054.          IF (Len = 5) AND (Oper[0] = '-') 
  4055.           AND (Oper[1] = '(') AND (Oper[4] = ')') THEN
  4056.             IF (Oper[2] = 'S') AND (Oper[3] = 'P') THEN
  4057.                (* System Stack Pointer *)
  4058.                Op.Mode := ARPre;
  4059.                Op.Rn := 7;
  4060.                RETURN;
  4061.             ELSIF Oper[2] = 'A' THEN
  4062.                C := ORD (Oper[3]);
  4063.                IF (C >= Zero) AND (C <= Seven) THEN
  4064.                   Op.Mode := ARPre;
  4065.                   Op.Rn := C - Zero;
  4066.                   RETURN;
  4067.                ELSE
  4068.                   Error (Op.Loc, SizeErr);
  4069.                   RETURN;
  4070.                END;
  4071.             ELSE
  4072.                Error (Op.Loc, AddrErr);
  4073.                RETURN;
  4074.             END;
  4075.          END;
  4076.  
  4077.          (* Try to split off displacement (if present) *)
  4078.          i := 0;
  4079.          ch := Oper[i];
  4080.          WHILE (ch # '(') AND (ch # 0C) DO   (* move to TempOp *)
  4081.             TempOp[i] := ch;
  4082.             INC (i);
  4083.             ch := Oper[i];
  4084.          END;
  4085.          TempOp[i] := 0C;   (* Displacement (it it exists) now in TempOp *)
  4086.  
  4087.          IF ch = '(' THEN   (* looks like a displacement mode *)
  4088.             IF Pass2 THEN
  4089.                GetValue (TempOp, Op.Value);   (* Value of Disp. *)
  4090.             END;
  4091.             j := 0;
  4092.             REPEAT   (* put rest of operand (eg. (An,Xi) in TempOp *)
  4093.                ch := Oper[i];
  4094.                TempOp[j] := ch;
  4095.                INC (i);   INC (j);
  4096.             UNTIL ch = 0C;
  4097.             IF Length (TempOp) > 4 THEN   (* Index may be present *)
  4098.                i := 4;   (* Index starts at 4 *)
  4099.                j := 0;
  4100.                REPEAT                       (* put Xi in Oper *)
  4101.                   ch := TempOp[i];
  4102.                   Oper[j] := ch;
  4103.                   INC (i);   INC (j);
  4104.                UNTIL ch = 0C;
  4105.  
  4106.                IF Oper[j - 2] = ')' THEN
  4107.                   Oper[j - 2] := 0C;
  4108.                ELSE
  4109.                   Error (Op.Loc, AddrErr);
  4110.                   RETURN;
  4111.                END;
  4112.  
  4113.                GetSize (Oper, Op.Xsize);
  4114.                IF Op.Xsize = Byte THEN
  4115.                   Error (Op.Loc, SizeErr);
  4116.                   RETURN;
  4117.                END;
  4118.  
  4119.                C := ORD (Oper[1]);
  4120.                IF (Oper[0] = 'S') AND (Oper[1] = 'P') THEN
  4121.                   (* Stack Pointer *)
  4122.                   Op.X := Areg;
  4123.                   Op.Xn := 7;
  4124.                ELSIF Oper[0] = 'A' THEN
  4125.                   IF (C >= Zero) AND (C <= Seven) THEN
  4126.                      Op.X := Areg;
  4127.                      Op.Xn := C - Zero;
  4128.                   ELSE
  4129.                      Error (Op.Loc, SizeErr);
  4130.                      RETURN;
  4131.                   END;
  4132.                ELSIF Oper[0] = 'D' THEN
  4133.                   IF (C >= Zero) AND (C <= Seven) THEN
  4134.                      Op.X := Dreg;
  4135.                      Op.Xn := C - Zero;
  4136.                   ELSE
  4137.                      Error (Op.Loc, SizeErr);
  4138.                      RETURN;
  4139.                   END;
  4140.                ELSE
  4141.                   Error (Op.Loc, AddrErr);
  4142.                   RETURN;
  4143.                END;
  4144.  
  4145.                IF (TempOp[1] = 'P') AND (TempOp[2] = 'C') THEN
  4146.                   Op.Mode :=PCDisX;
  4147.                   RETURN;    
  4148.                ELSIF (TempOp[1] = 'S') AND (TempOp[2] = 'P') THEN
  4149.                   (* Stack Pointer *)
  4150.                   Op.Rn := 7;
  4151.                   Op.Mode := ARDisX;
  4152.                   RETURN;
  4153.                ELSIF TempOp[1] = 'A' THEN
  4154.                   C := ORD (TempOp[2]);
  4155.                   IF (C >= Zero) AND (C <= Seven) THEN
  4156.                      Op.Rn := C - Zero;
  4157.                      Op.Mode := ARDisX;
  4158.                      RETURN;
  4159.                   ELSE
  4160.                      Error (Op.Loc, SizeErr);
  4161.                      RETURN;
  4162.                   END;
  4163.                ELSE
  4164.                   Error (Op.Loc, AddrErr);
  4165.                   RETURN;
  4166.                END;
  4167.             ELSE   (* No Index *)
  4168.                IF (TempOp[1] = 'P') AND (TempOp[2] = 'C') THEN
  4169.                   Op.Mode := PCDisp;
  4170.                   RETURN;    
  4171.                ELSIF (TempOp[1] = 'S') AND (TempOp[2] = 'P') THEN
  4172.                   (* Stack Pointer *)
  4173.                   Op.Mode := ARDisp;
  4174.                   Op.Rn := 7;                                                
  4175.                   RETURN;  
  4176.                ELSIF TempOp[1] = 'A' THEN
  4177.                   C := ORD (TempOp[2]);
  4178.                   IF (C >= Zero) AND (C <= Seven) THEN
  4179.                      Op.Rn := C - Zero;
  4180.                      Op.Mode := ARDisp;
  4181.                      RETURN;
  4182.                   ELSE
  4183.                      Error (Op.Loc, SizeErr);
  4184.                      RETURN;
  4185.                   END;
  4186.                ELSE
  4187.                   Error (Op.Loc, AddrErr);
  4188.                   RETURN;
  4189.                END;
  4190.             END;
  4191.          END;
  4192.  
  4193.          (* Check to see if this could be a register list for MOVEM: *)
  4194.          i := 0;
  4195.          MultFlag := FALSE;
  4196.          LOOP
  4197.             ch := Oper[i];   INC (i);
  4198.             IF ch = 0C THEN
  4199.                MultFlag := FALSE;
  4200.                EXIT;
  4201.             END;
  4202.             IF (ch = 'A') OR (ch = 'D') THEN
  4203.                ch := Oper[i];   INC (i);   C := ORD (ch);
  4204.                IF ch = 0C THEN
  4205.                   MultFlag := FALSE;
  4206.                   EXIT;
  4207.                END;
  4208.                IF (C >= Zero) AND (C <= Seven) THEN
  4209.                   ch := Oper[i];   INC (i);  
  4210.                   IF ch = 0C THEN
  4211.                      EXIT
  4212.                   END;
  4213.                   IF (ch = '/') OR (ch = '-') THEN
  4214.                      MultFlag := TRUE;
  4215.                   END;
  4216.                ELSE
  4217.                   MultFlag := FALSE;
  4218.                   EXIT;
  4219.                END;
  4220.             ELSE
  4221.                MultFlag := FALSE;
  4222.                EXIT;
  4223.             END;
  4224.          END;
  4225.          IF MultFlag THEN
  4226.             Op.Mode := MultiM;
  4227.             RETURN;
  4228.          END;
  4229.  
  4230.          (* Must be absolute mode! *)
  4231.          IF Pass2 THEN
  4232.             GetValue (Oper, Op.Value);
  4233.          END;
  4234.          IF AbsSize = Word THEN
  4235.             Op.Mode := AbsW;
  4236.          ELSE
  4237.             Op.Mode := AbsL;
  4238.          END;
  4239.       END GetOperand;
  4240.  
  4241.  
  4242.  
  4243.    PROCEDURE GetMultReg (Oper : OPERAND; PreDec : BOOLEAN;
  4244.                          Loc : CARDINAL; VAR MultExt : BITSET);
  4245.    (* Builds a BITSET marking each register used in a MOVEM instruction *)
  4246.  
  4247.       TYPE
  4248.          MReg = (D0, D1, D2, D3, D4, D5, D6, D7, 
  4249.                  A0, A1, A2, A3, A4, A5, A6, A7);
  4250.  
  4251.       VAR
  4252.          i, j : CARDINAL;
  4253.          ch : CHAR;
  4254.          C : CARDINAL;   (* ORD value of ch *)
  4255.          T1, T2 : MReg;   (* Temporary variables for registers *)
  4256.          RegStack : ARRAY [0..15] OF MReg;   (* Holds specified registers *)
  4257.          SP : CARDINAL;   (* Pointer for Register Stack *)
  4258.          RegType : (D, A, Nil);
  4259.          Range : BOOLEAN;
  4260.          
  4261.       BEGIN
  4262.          SP := 0;
  4263.          Range := FALSE;
  4264.          RegType := Nil;
  4265.          i := 0;
  4266.  
  4267.          ch := Oper[i];
  4268.          WHILE ch # 0C DO
  4269.             IF SP > 15 THEN
  4270.                Error (Loc, SizeErr);
  4271.                RETURN;
  4272.             END;
  4273.  
  4274.             C := ORD (ch);
  4275.             IF ch = 'A' THEN
  4276.                IF RegType = Nil THEN
  4277.                   RegType := A;
  4278.                ELSE
  4279.                   Error (Loc, OperErr);
  4280.                   RETURN;
  4281.                END;
  4282.             ELSIF ch = 'D' THEN
  4283.                IF RegType = Nil THEN
  4284.                   RegType := D;
  4285.                ELSE
  4286.                   Error (Loc, OperErr);
  4287.                   RETURN;
  4288.                END;
  4289.             ELSIF (C >= Zero) AND (C <= Seven) THEN
  4290.                IF RegType # Nil THEN
  4291.                   T2 := VAL (MReg, (ORD (RegType) * 8) + (C - Zero));
  4292.                   IF Range THEN
  4293.                      Range := FALSE;
  4294.                      T1 := RegStack[SP - 1];   (* retreive 1st Reg in range *)
  4295.                      FOR j := (ORD (T1) + 1) TO ORD (T2) DO
  4296.                         RegStack[SP] := VAL (MReg, j);
  4297.                         INC (SP);
  4298.                      END;
  4299.                   ELSE
  4300.                      RegStack[SP] := T2;
  4301.                      INC (SP);
  4302.                   END;
  4303.                ELSE
  4304.                   Error (Loc, OperErr);
  4305.                   RETURN;
  4306.                END;
  4307.             ELSIF ch = '-' THEN
  4308.                IF (Range = FALSE) AND (RegType # Nil) AND (i > 0) THEN
  4309.                   RegType := Nil;
  4310.                   Range := TRUE;
  4311.                ELSE
  4312.                   Error (Loc, OperErr);
  4313.                   RETURN;
  4314.                END;
  4315.             ELSIF ch = '/' THEN
  4316.                IF (Range = FALSE) AND (RegType # Nil) AND (i > 0) THEN
  4317.                   RegType := Nil;
  4318.                ELSE
  4319.                   Error (Loc, OperErr);
  4320.                   RETURN;
  4321.                END;
  4322.             ELSE
  4323.                Error (Loc, OperErr);
  4324.                RETURN;
  4325.             END;
  4326.             
  4327.             INC (i);
  4328.             ch := Oper[i];
  4329.          END;
  4330.  
  4331.          MultExt := {};
  4332.          FOR j := 0 TO SP - 1 DO
  4333.             C := ORD (RegStack[j]);
  4334.             IF PreDec THEN
  4335.                C := 15 - C;
  4336.             END;
  4337.             INCL (MultExt, C);
  4338.          END;
  4339.       END GetMultReg;
  4340.  
  4341. END SyntaxAnalyzer.
  4342.  
  4343. IMPLEMENTATION MODULE Listing;
  4344. (* Creates a program listing, including Addresses, Code & Source. *)
  4345.  
  4346.    FROM Files IMPORT
  4347.       FILE, Write;
  4348.  
  4349.    FROM LongNumbers IMPORT
  4350.       LONG, LongPut;
  4351.  
  4352.    FROM Parser IMPORT
  4353.       TOKEN, Line;
  4354.  
  4355.    FROM SymbolTable IMPORT
  4356.       ListSymTab;
  4357.  
  4358.    FROM Conversions IMPORT
  4359.       CardToStr;
  4360.  
  4361.    IMPORT ASCII;
  4362.  
  4363.       
  4364.    CONST
  4365.       LnMAX = 55;
  4366.  
  4367.  
  4368.    VAR
  4369.       LnCnt : CARDINAL;   (* counts number of lines per page *)
  4370.       PgCnt : CARDINAL;   (* count of page numbers *)
  4371.  
  4372.  
  4373.  
  4374.    PROCEDURE WriteStrF (f : FILE; Str : ARRAY OF CHAR);
  4375.    (* Writes a string to the file *)
  4376.  
  4377.       VAR
  4378.          i : CARDINAL;
  4379.  
  4380.       BEGIN
  4381.          i := 0;
  4382.          WHILE Str[i] # 0C DO
  4383.             Write (f, Str[i]);
  4384.             INC (i);
  4385.          END;
  4386.       END WriteStrF;
  4387.  
  4388.  
  4389.  
  4390.    PROCEDURE CheckPage (f : FILE);
  4391.    (* Checks if end of page reached yet -- if so, advances to next page. *)
  4392.  
  4393.       VAR
  4394.          i : CARDINAL;
  4395.          PgCntStr : ARRAY [0..6] OF CHAR;
  4396.       
  4397.       BEGIN
  4398.          INC (LnCnt);
  4399.          IF LnCnt >= LnMAX THEN
  4400.             LnCnt := 1;
  4401.             INC (PgCnt);
  4402.             Write (f, ASCII.ff);   (* Form Feed for new page *)
  4403.             IF CardToStr (PgCnt, PgCntStr) THEN   (* Print New Page Number *)
  4404.                FOR i := 1 TO 60 DO
  4405.                   Write (f, ' ');
  4406.                END;
  4407.  
  4408.                WriteStrF (f, "Page ");
  4409.                WriteStrF (f, PgCntStr);
  4410.             END;
  4411.             FOR i := 1 TO 3 DO
  4412.                Write (f, ASCII.cr);
  4413.                Write (f, ASCII.lf);
  4414.             END;
  4415.          END;
  4416.       END CheckPage;
  4417.  
  4418.  
  4419.  
  4420.    PROCEDURE StartListing (f : FILE);
  4421.    (* Sign on messages for listing file -- initialize *)
  4422.       BEGIN
  4423.          Write (f, ASCII.ff);   (* Start on a clean page *)
  4424.  
  4425.          WriteStrF (f, "                 68000 Cross Assembler");
  4426.          Write (f, ASCII.cr);
  4427.          Write (f, ASCII.lf);
  4428.  
  4429.          WriteStrF (f, "         Copyright (c) 1985 by Brian R. Anderson");
  4430.          Write (f, ASCII.cr);
  4431.          Write (f, ASCII.lf);
  4432.  
  4433.          Write (f, ASCII.cr);
  4434.          Write (f, ASCII.lf);
  4435.  
  4436.          LnCnt := 1;
  4437.          PgCnt := 1;
  4438.       END StartListing;
  4439.  
  4440.  
  4441.  
  4442.    PROCEDURE WriteListLine (f : FILE;
  4443.                             AddrCnt, ObjOp, ObjSrc, ObjDest : LONG;
  4444.                                nA,     nO,    nS,     nD    : CARDINAL);
  4445.    (* Writes one line to the Listing file, Including Object Code *)
  4446.  
  4447.       CONST
  4448.          ObjMAX = 30;
  4449.  
  4450.       VAR
  4451.          i : CARDINAL;
  4452.  
  4453.       BEGIN
  4454.          IF nA = 0 THEN   (* nA is always either 0 or 6.  Address field = 8 *)
  4455.             FOR i := 1 TO 8 DO
  4456.                Write (f, ' ');
  4457.             END;
  4458.          ELSE
  4459.             LongPut (f, AddrCnt, 6);
  4460.             Write (f, ' ');   
  4461.             Write (f, ' ');
  4462.          END;
  4463.          LongPut (f, ObjOp, nO);   
  4464.          LongPut (f, ObjSrc, nS);  
  4465.          LongPut (f, ObjDest, nD); 
  4466.          i := 8 + nO + nS + nD;
  4467.          WHILE i < ObjMAX DO
  4468.             Write (f, ' ');
  4469.             INC (i);
  4470.          END;
  4471.  
  4472.          WriteStrF (f, Line);
  4473.          Write (f, ASCII.cr);
  4474.          Write (f, ASCII.lf);
  4475.          
  4476.          CheckPage (f);
  4477.  
  4478.       END WriteListLine;
  4479.  
  4480.  
  4481.  
  4482.    PROCEDURE WriteSymTab (f : FILE; NumSym : CARDINAL);
  4483.    (* Lists symbol table in alphabetical order *)
  4484.  
  4485.       VAR
  4486.          Label : TOKEN;
  4487.          Value : LONG;
  4488.          i : CARDINAL;
  4489.  
  4490.       BEGIN
  4491.          LnCnt := 1;
  4492.          INC (PgCnt);
  4493.  
  4494.          WriteStrF (f, "             * * *  Symbolic Reference Table  * * *");
  4495.          FOR i := 1 TO 3 DO
  4496.             Write (f, ASCII.cr);
  4497.             Write (f, ASCII.lf);
  4498.          END;
  4499.  
  4500.          FOR i := 1 TO NumSym DO
  4501.             ListSymTab (i, Label, Value);
  4502.             WriteStrF (f, Label);
  4503.             WriteStrF (f, "  :  ");
  4504.             LongPut (f, Value, 8);
  4505.             Write (f, ASCII.cr);
  4506.             Write (f, ASCII.lf);
  4507.             CheckPage (f);
  4508.          END; 
  4509.  
  4510.          Write (f, ASCII.ff);
  4511.       END WriteSymTab;
  4512.  
  4513. END Listing.
  4514.  
  4515. IMPLEMENTATION MODULE Srecord;
  4516. (* Creates Motorola S-records of program:        *)
  4517. (*    S0 = header record,                        *)
  4518. (*    S2 = code/data records (24 bit address),   *)
  4519. (*    S8 = termination record (24 bit address).  *)
  4520.  
  4521.    FROM Files IMPORT
  4522.       FILE, Write;
  4523.  
  4524.    FROM Strings IMPORT
  4525.       Length;
  4526.  
  4527.    FROM LongNumbers IMPORT
  4528.       LONG, LongAdd, LongSub, LongInc, LongDec, LongClear, 
  4529.       LongCompare, CardToLong, LongPut;
  4530.  
  4531.    IMPORT ASCII;
  4532.  
  4533.  
  4534.    CONST
  4535.       CountMAX = 16;
  4536.       SrecMAX = CountMAX * 2;
  4537.       XrecMAX = SrecMAX;
  4538.  
  4539.  
  4540.    VAR
  4541.       StartAddr : LONG;   (* address that record starts on *)
  4542.       TempAddr : LONG;    (* running address of where we are now *)
  4543.       CheckSum : LONG;
  4544.       Count : CARDINAL;   (* count of HEX-pairs in S-record *)
  4545.       Sdata : ARRAY [1..SrecMAX] OF INTEGER;   (* S-record data, HEX digits *)
  4546.       Sindex : CARDINAL;   (* index for Sdata array *)
  4547.       Xdata : ARRAY [1..XrecMAX] OF INTEGER;   (* Overflow for Sdata *)
  4548.       Xindex : CARDINAL;   (* index for Xdata array *)
  4549.       Boundary : BOOLEAN;   (* marks Address MOD 16 boundary of S-record *)
  4550.       LZero : LONG;   (* used as a constant = 0 *)
  4551.  
  4552.  
  4553.  
  4554.    PROCEDURE Complement;   (* CheckSum *)
  4555.       BEGIN
  4556.          LongSub (LZero, CheckSum, CheckSum);   (* 2's Complement *)
  4557.          LongDec (CheckSum, 1);   (* Make it 1's Complement *)
  4558.       END Complement;
  4559.  
  4560.  
  4561.       
  4562.    PROCEDURE AppendSdata (Data : LONG; n : CARDINAL) : BOOLEAN;
  4563.    (* Transfers data to Sdata, and updates Count & CheckSum. *)
  4564.    (*    If no room: Data goes to Xdata & FALSE returned.    *)
  4565.  
  4566.       VAR
  4567.          T : LONG;   (* temporary -- used only as a 2 digit HEX number *)
  4568.  
  4569.       BEGIN
  4570.          T := LZero;
  4571.  
  4572.          WHILE (n # 0) AND (Count # CountMAX) AND (NOT Boundary) DO
  4573.             Sdata[Sindex] := Data[n];
  4574.             Sdata[Sindex - 1] := Data[n - 1];
  4575.  
  4576.             T[2] := Data[n];   T[1] := Data[n - 1];
  4577.             LongAdd (T, CheckSum, CheckSum);
  4578.  
  4579.             DEC (n, 2);
  4580.             DEC (Sindex, 2);
  4581.             INC (Count);
  4582.  
  4583.             LongInc (TempAddr, 1);
  4584.             IF TempAddr[1] = 0 THEN   (* i.e., TempAddr MOD 16 = 0 *)
  4585.                Boundary := TRUE;
  4586.             END;
  4587.          END;
  4588.    
  4589.          IF (Count = CountMAX) OR (Boundary) THEN
  4590.             WHILE n > 0 DO   (* Add Data to Xdata (in reverse) *)
  4591.                INC (Xindex);
  4592.                Xdata[Xindex] := Data[n];
  4593.                DEC (n);
  4594.             END;
  4595.  
  4596.             RETURN FALSE;   (* Sdata is full *)
  4597.          ELSE
  4598.             RETURN TRUE;
  4599.          END;         
  4600.       END AppendSdata;
  4601.  
  4602.  
  4603.  
  4604.    PROCEDURE DumpSdata (f : FILE);
  4605.    (* Writes an S2 record to the file *)
  4606.       
  4607.       VAR
  4608.          T : LONG;   (* temporary -- used to output Count & CheckSum *)
  4609.          i, j : CARDINAL;
  4610.  
  4611.       BEGIN
  4612.          IF Count = 0 THEN
  4613.             RETURN;   (* nothing to dump *)
  4614.          END;
  4615.  
  4616.          Write (f, 'S');
  4617.          Write (f, '2');
  4618.          
  4619.          CardToLong (Count + 4, T);   (* extra for Address & Checksum *)
  4620.          LongPut (f, T, 2);
  4621.          LongAdd (T, CheckSum, CheckSum);   (* Add Count to CheckSum *)
  4622.  
  4623.          LongPut (f, StartAddr, 6);
  4624.          (* Add Address to CheckSum *)
  4625.          T := LZero;
  4626.          T[1] := StartAddr[1];   T[2] := StartAddr[2];
  4627.          LongAdd (T, CheckSum, CheckSum);
  4628.          T[1] := StartAddr[3];   T[2] := StartAddr[4];
  4629.          LongAdd (T, CheckSum, CheckSum);
  4630.          T[1] := StartAddr[5];   T[2] := StartAddr[6];
  4631.          LongAdd (T, CheckSum, CheckSum);
  4632.          
  4633.          IF Count < CountMAX THEN   (* adjust short record -- shuffle down *)
  4634.             j := 1;
  4635.             FOR i := Sindex + 1 TO SrecMAX DO
  4636.                Sdata[j] := Sdata[i];
  4637.                INC (j);
  4638.             END;
  4639.          END;
  4640.          LongPut (f, Sdata, Count * 2);   (* S-record Code/Data *)
  4641.  
  4642.          Complement; (* CheckSum *)
  4643.          LongPut (f, CheckSum, 2);
  4644.  
  4645.          Write (f, ASCII.cr);
  4646.          Write (f, ASCII.lf);
  4647.  
  4648.          LongInc (StartAddr, Count);
  4649.          Sindex := SrecMAX;
  4650.          Count := 0;
  4651.          Boundary := FALSE;
  4652.          CheckSum := LZero;
  4653.       END DumpSdata;
  4654.  
  4655.  
  4656.  
  4657.    PROCEDURE GetXdata;
  4658.    (* Transfer Xdata into new Sdata line -- N.B.: Xdata stored in reverse *)
  4659.  
  4660.       VAR
  4661.          i : CARDINAL;
  4662.          T : LONG;
  4663.  
  4664.       BEGIN
  4665.          i := 1;
  4666.          T := LZero;
  4667.  
  4668.          (* No need for either of the tests (CountMAX or Boundary)   *)
  4669.          (* used in AppendSdata.  GetXdata is only ever called       *)
  4670.          (* after DumpSdata and is therefore only putting (up to 20) *)
  4671.          (* HEX digits in an empty buffer (which could hold 32).     *)
  4672.          WHILE i < Xindex DO
  4673.             Sdata[Sindex] := Xdata[i];   
  4674.             Sdata[Sindex - 1] := Xdata[i + 1];
  4675.             T[2] := Sdata[Sindex];   T[1] := Sdata[Sindex - 1];   
  4676.             LongAdd (T, CheckSum, CheckSum);
  4677.             INC (i, 2);
  4678.             DEC (Sindex, 2);
  4679.             INC (Count);
  4680.             LongInc (TempAddr, 1);
  4681.          END;
  4682.  
  4683.          Xindex := 0;            
  4684.       END GetXdata;
  4685.  
  4686.  
  4687.  
  4688.    PROCEDURE StartSrec (f : FILE; SourceFN : ARRAY OF CHAR);
  4689.    (* Writes S0 record (HEADER) and initializes *)
  4690.       
  4691.       VAR
  4692.          T : LONG;   (* temporary *)
  4693.          i : CARDINAL;
  4694.  
  4695.       BEGIN
  4696.          Write (f, 'S');
  4697.          Write (f, '0');
  4698.  
  4699.          CheckSum := LZero;
  4700.          Count := Length (SourceFN) + 3;   (* extra for Address & Checksum *)
  4701.          CardToLong (Count, T);
  4702.          LongPut (f, T, 2);
  4703.          LongAdd (T, CheckSum, CheckSum);
  4704.          
  4705.          LongPut (f, LZero, 4);   (* Address is 4 digit, all zero, for S0 *)
  4706.  
  4707.          i := 0;
  4708.          WHILE SourceFN[i] # 0C DO
  4709.             CardToLong (ORD (SourceFN[i]), T);
  4710.             LongAdd (T, CheckSum, CheckSum);
  4711.             LongPut (f, T, 2);
  4712.             INC (i);
  4713.          END;
  4714.          
  4715.          Complement;   (* CheckSum *)
  4716.          LongPut (f, CheckSum, 2);
  4717.  
  4718.          Write (f, ASCII.cr);
  4719.          Write (f, ASCII.lf);
  4720.  
  4721.          Sindex := SrecMAX;
  4722.          Xindex := 0;
  4723.          Count := 0;
  4724.          Boundary := FALSE;
  4725.          CheckSum := LZero;
  4726.          StartAddr := LZero;
  4727.          TempAddr := LZero;
  4728.       END StartSrec;
  4729.  
  4730.  
  4731.  
  4732.    PROCEDURE WriteSrecLine (f : FILE; 
  4733.                             AddrCnt, ObjOp, ObjSrc, ObjDest : LONG;
  4734.                                nA,     nO,    nS,     nD    : CARDINAL);
  4735.    (* Collects Object Code -- Writes an S2 record to file if line is full *)
  4736.  
  4737.       VAR
  4738.          dummy : BOOLEAN;
  4739.       
  4740.       BEGIN
  4741.          IF nA = 0 THEN
  4742.             RETURN;   (* Nothing to add to S-record *)
  4743.          END;
  4744.  
  4745.          IF Xindex # 0 THEN
  4746.             GetXdata;   (* transfers Xdata into Sdata *)
  4747.          END;
  4748.  
  4749.          IF LongCompare (AddrCnt, TempAddr) # 0 THEN
  4750.             DumpSdata (f);
  4751.          END;
  4752.  
  4753.          IF Count = 0 THEN
  4754.             StartAddr := AddrCnt;
  4755.             TempAddr := AddrCnt;
  4756.          END;
  4757.       
  4758.          dummy := AppendSdata (ObjOp, nO);
  4759.          dummy := AppendSdata (ObjSrc, nS);
  4760.          IF NOT AppendSdata (ObjDest, nD) THEN
  4761.             DumpSdata (f);
  4762.          END;
  4763.       END WriteSrecLine;
  4764.  
  4765.  
  4766.  
  4767.    PROCEDURE EndSrec (f : FILE);
  4768.    (* Finishes off any left-over (Partial) S2 line, *)
  4769.    (* and then writes S8 record (TRAILER)           *)
  4770.       BEGIN
  4771.          IF Xindex # 0 THEN
  4772.             GetXdata;
  4773.          END;
  4774.          DumpSdata (f);
  4775.          
  4776.          Write (f, 'S');   (* Fixed format for S8 record *)
  4777.          Write (f, '8');
  4778.          Write (f, '0');
  4779.          Write (f, '4');
  4780.          Write (f, '0');
  4781.          Write (f, '0');
  4782.          Write (f, '0');
  4783.          Write (f, '0');
  4784.          Write (f, '0');
  4785.          Write (f, '0');
  4786.          Write (f, 'F');
  4787.          Write (f, 'C');
  4788.          Write (f, ASCII.cr);
  4789.          Write (f, ASCII.lf);
  4790.          Write (f, ASCII.cr);
  4791.          Write (f, ASCII.lf);
  4792.       END EndSrec;
  4793.  
  4794. BEGIN   (* Initialization *)
  4795.    LongClear (LZero);
  4796. END Srecord.
  4797. IMPLEMENTATION MODULE ErrorX68;
  4798. (* Displays error messages for X68000 cross assembler *)
  4799.  
  4800.    FROM Terminal IMPORT
  4801.       WriteString, WriteLn;
  4802.  
  4803.    IMPORT Terminal;   (* for Read/Write *)
  4804.  
  4805.    FROM Files IMPORT
  4806.       FILE;
  4807.  
  4808.    IMPORT Files;   (* for Write *)
  4809.  
  4810.    FROM Strings IMPORT
  4811.       Length;
  4812.  
  4813.    FROM Conversions IMPORT
  4814.       CardToStr;
  4815.  
  4816.    IMPORT ASCII;
  4817.  
  4818.    FROM Parser IMPORT
  4819.       Line, LineCount;
  4820.  
  4821.  
  4822. (*---
  4823.    TYPE
  4824.       ErrorType = (Dummy, TooLong, NoCode, SymDup, Undef, SymFull, Phase,
  4825.                    ModeErr, OperErr, BraErr, AddrErr, SizeErr, EndErr);
  4826.  
  4827.    VAR
  4828.       ErrorCount : CARDINAL;
  4829.                                                                   ---*)
  4830.  
  4831.    VAR
  4832.       FirstTime : BOOLEAN;
  4833.  
  4834.  
  4835.  
  4836.    PROCEDURE FileWriteString (f : FILE; VAR Str : ARRAY OF CHAR);
  4837.  
  4838.       VAR
  4839.          i : CARDINAL;
  4840.  
  4841.       BEGIN
  4842.          i := 0;
  4843.          WHILE Str[i] # 0C DO
  4844.             Files.Write (f, Str[i]);
  4845.             INC (i);
  4846.          END;
  4847.       END FileWriteString;
  4848.  
  4849.  
  4850.  
  4851.    PROCEDURE Error (Pos : CARDINAL; ErrorNbr : ErrorType);
  4852.    (* Displays Error #ErrorNbr, then waits for any key to continue *)
  4853.  
  4854.       VAR
  4855.          i : CARDINAL;
  4856.          c : CHAR;
  4857.          CntStr : ARRAY [0..6] OF CHAR;
  4858.          dummy : BOOLEAN;
  4859.  
  4860.       BEGIN
  4861.          WriteLn;
  4862.          dummy := CardToStr (LineCount, CntStr);
  4863.          WriteString (CntStr);
  4864.          WriteString ("   ");
  4865.          WriteString (Line);   WriteLn;
  4866.  
  4867.          (* Make up for LineCnt so ^ in right spot *)
  4868.          FOR i := 1 TO Length (CntStr) DO
  4869.             Terminal.Write (' ');
  4870.          END;
  4871.          WriteString ("   ");
  4872.  
  4873.          IF Pos > 0 THEN
  4874.             FOR i := 1 TO Pos DO
  4875.                Terminal.Write (' ');
  4876.             END;
  4877.             Terminal.Write ('^');   WriteLn;
  4878.          END;
  4879.          
  4880.          CASE ErrorNbr OF
  4881.             TooLong : WriteString ("Identifier too long -- Truncated!");
  4882.          |  NoCode  : WriteString ("No such op-code.");
  4883.          |  SymDup  : WriteString ("Duplicate Symbol.");
  4884.          |  Undef   : WriteString ("Undefined Symbol.");
  4885.          |  SymFull : WriteString ("Symbol Table Full -- Maximum = 500!");
  4886.                       WriteLn;
  4887.                       WriteString ("Program Terminated.");   WriteLn;
  4888.                       HALT;
  4889.          |  Phase   : WriteString ("Pass 1/Pass 2 Address Count Mis-Match.");
  4890.          |  ModeErr : WriteString ("This addressing mode not allowed here.");
  4891.          |  OperErr : WriteString ("Error in operand format.");
  4892.          |  BraErr  : WriteString ("Error in relative branch.");
  4893.          |  AddrErr : WriteString ("Address mode error.");
  4894.          |  SizeErr : WriteString ("Operand size error.");
  4895.          |  EndErr  : WriteString ("Missing END Pseudo-Op.");
  4896.          ELSE
  4897.             WriteString ("Unknown Error.");
  4898.          END;
  4899.          WriteLn; 
  4900.  
  4901.          IF FirstTime THEN
  4902.             WriteString ("Hit any key to continue.... ");
  4903.             Terminal.Read (c);   
  4904.             WriteLn;
  4905.             FirstTime := FALSE;
  4906.          ELSE
  4907.             Terminal.Read (c);
  4908.          END;
  4909.          
  4910.          INC (ErrorCount);
  4911.          IF ErrorCount > 500 THEN
  4912.             WriteString ("Too many errors!");   WriteLn;
  4913.             WriteString ("Program Terminated.");   WriteLn;
  4914.             HALT;
  4915.          END;
  4916.       END Error;
  4917.  
  4918.  
  4919.  
  4920.    PROCEDURE WriteErrorCount (f : FILE);
  4921.    (* Error count output to Console & Listing file *)
  4922.  
  4923.       VAR
  4924.          CntStr : ARRAY [0..6] OF CHAR;
  4925.          Msg0 : ARRAY [0..25] OF CHAR;
  4926.          Msg1 : ARRAY [0..10] OF CHAR;
  4927.          Msg2 : ARRAY [0..20] OF CHAR;
  4928.          dummy : BOOLEAN;
  4929.  
  4930.       BEGIN
  4931.          Msg0 := "--->   END OF ASSEMBLY";
  4932.          Msg1 := "--->   ";
  4933.          Msg2 := " ASSEMBLY ERROR(S).";
  4934.          dummy := CardToStr (ErrorCount, CntStr);
  4935.             
  4936.          (* Messages to console *)
  4937.          WriteLn;
  4938.          WriteLn;
  4939.          WriteString (Msg0);   WriteLn;
  4940.          WriteString (Msg1);
  4941.          WriteString (CntStr);
  4942.          WriteString (Msg2);
  4943.          WriteLn;
  4944.  
  4945.          (* Messages to listing file *)
  4946.          Files.Write (f, ASCII.cr);   
  4947.          Files.Write (f, ASCII.lf);
  4948.          Files.Write (f, ASCII.cr);   
  4949.          Files.Write (f, ASCII.lf);
  4950.  
  4951.          FileWriteString (f, Msg0);
  4952.          Files.Write (f, ASCII.cr);   
  4953.          Files.Write (f, ASCII.lf);
  4954.  
  4955.          FileWriteString (f, Msg1);
  4956.          FileWriteString (f, CntStr);
  4957.          FileWriteString (f, Msg2);
  4958.          Files.Write (f, ASCII.cr);   
  4959.          Files.Write (f, ASCII.lf);
  4960.  
  4961.          Files.Write (f, ASCII.ff);   (* feed up next page *)
  4962.       END WriteErrorCount;
  4963.  
  4964.  
  4965. BEGIN   (* MODULE Initialization *)
  4966.    FirstTime := TRUE;
  4967.    ErrorCount := 0;
  4968. END ErrorX68.
  4969.  
  4970.