Bläddra i källkod

+ more m68k fixes

carl 23 år sedan
förälder
incheckning
f46268dbf6
3 ändrade filer med 2277 tillägg och 99 borttagningar
  1. 0 0
      compiler/m68k/aggas.pas
  2. 0 99
      compiler/m68k/cpuswtch.pas
  3. 2277 0
      compiler/m68k/rasm.pas

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 0
compiler/m68k/aggas.pas


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 99
compiler/m68k/cpuswtch.pas


+ 2277 - 0
compiler/m68k/rasm.pas

@@ -0,0 +1,2277 @@
+{
+    $Id$
+    Copyright (c) 1998-2000 by Carl Eric Codere
+
+    This unit does the parsing process for the motorola inline assembler
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+Unit Rasm;
+{**********************************************************************}
+{ WARNING                                                              }
+{**********************************************************************}
+{  Any modification in the order or removal of terms in the tables     }
+{  in m68k.pas and asmo68k.pas  will BREAK the code in this unit,      }
+{  unless the appropriate changes are made to this unit. Addition      }
+{  of terms though, will not change the code herein.                   }
+{**********************************************************************}
+
+{---------------------------------------------------------------------------}
+{ LEFT TO DO                                                                }
+{---------------------------------------------------------------------------}
+{  o Add support for sized indexing such as in d0.l                         }
+{      presently only (an,dn) is supported for indexing --                  }
+{        size defaults to LONG.                                             }
+{  o Add support for MC68020 opcodes.                                       }
+{  o Add support for MC68020 adressing modes.                               }
+{  o Add operand checking with m68k opcode table in ConcatOpCode            }
+{  o Add Floating point support                                             }
+{---------------------------------------------------------------------------}
+
+Interface
+
+Uses
+  globtype,cpubase,tree;
+
+   function assemble: ptree;
+
+const
+ { this variable is TRUE if the lookup tables have already been setup  }
+ { for fast access. On the first call to assemble the tables are setup }
+ { and stay set up.                                                    }
+ _asmsorted: boolean = FALSE;
+ firstasmreg       = R_D0;
+ lastasmreg        = R_FPSR;
+
+type
+ tiasmops = array[firstop..lastop] of string[7];
+ piasmops = ^tiasmops;
+
+ tasmkeyword = string[6];
+
+var
+ { sorted tables of opcodes }
+ iasmops: piasmops;
+ { uppercased tables of registers }
+ iasmregs: array[firstasmreg..lastasmreg] of string[6];
+
+
+Implementation
+
+uses
+  files,globals,systems,RAUtils,strings,hcodegen,scanner,aasm,
+  cpuasm,cobjects,verbose,symconst,symtable;
+
+
+type
+ tmotorolatoken = (
+   AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_HEXNUM,AS_OCTALNUM,
+   AS_BINNUM,AS_COMMA,AS_LBRACKET,AS_RBRACKET,AS_LPAREN,
+   AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,AS_INTNUM,
+   AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_APPT,AS_REALNUM,
+   AS_ALIGN,
+     {------------------ Assembler directives --------------------}
+   AS_DB,AS_DW,AS_DD,AS_XDEF,AS_END,
+     {------------------ Assembler Operators  --------------------}
+   AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR);
+
+const
+   firstdirective = AS_DB;
+   lastdirective  = AS_END;
+   firstoperator  = AS_MOD;
+   lastoperator   = AS_XOR;
+
+   _count_asmdirectives = longint(lastdirective)-longint(firstdirective);
+   _count_asmoperators  = longint(lastoperator)-longint(firstoperator);
+
+   _asmdirectives : array[0.._count_asmdirectives] of tasmkeyword =
+    ('DC.B','DC.W','DC.L','XDEF','END');
+
+    { problems with shl,shr,not,and,or and xor, they are }
+    { context sensitive.                                 }
+    _asmoperators : array[0.._count_asmoperators] of tasmkeyword = (
+    'MOD','SHL','SHR','NOT','AND','OR','XOR');
+
+
+const
+  newline = #10;
+  firsttoken : boolean = TRUE;
+  operandnum : byte = 0;
+var
+ p : paasmoutput;
+ actasmtoken: tmotorolatoken;
+ actasmpattern: string;
+ c: char;
+ Instr: TInstruction;
+ old_exit : pointer;
+
+   Procedure SetupTables;
+   { creates uppercased symbol tables for speed access }
+   var
+     i: tasmop;
+     j: tregister;
+   Begin
+     {Message(asmr_d_creating_lookup_tables);}
+     { opcodes }
+     new(iasmops);
+     for i:=firstop to lastop do
+      iasmops^[i] := upper(mot_op2str[i]);
+     { opcodes }
+     for j:=firstasmreg to lastasmreg do
+      iasmregs[j] := upper(mot_reg2str[j]);
+   end;
+
+
+  {---------------------------------------------------------------------}
+  {                     Routines for the tokenizing                     }
+  {---------------------------------------------------------------------}
+
+
+   function is_asmopcode(s: string):Boolean;
+  {*********************************************************************}
+  { FUNCTION is_asmopcode(s: string):Boolean                            }
+  {  Description: Determines if the s string is a valid opcode          }
+  {  if so returns TRUE otherwise returns FALSE.                        }
+  {  Remark: Suffixes are also checked, as long as they are valid.      }
+  {*********************************************************************}
+   var
+    i: tasmop;
+    j: byte;
+   Begin
+     is_asmopcode := FALSE;
+     { first of all we remove the suffix }
+     j:=pos('.',s);
+     if j<>0 then
+      delete(s,j,2);
+     for i:=firstop to lastop do
+     begin
+       if  s = iasmops^[i] then
+       begin
+          is_asmopcode:=TRUE;
+          exit;
+       end;
+     end;
+   end;
+
+
+
+   Procedure is_asmdirective(const s: string; var token: tmotorolatoken);
+  {*********************************************************************}
+  { FUNCTION is_asmdirective(s: string; var token: tinteltoken):Boolean }
+  {  Description: Determines if the s string is a valid directive       }
+  { (an operator can occur in operand fields, while a directive cannot) }
+  {  if so returns the directive token, otherwise does not change token.}
+  {*********************************************************************}
+   var
+    i:byte;
+   Begin
+     for i:=0 to _count_asmdirectives do
+     begin
+        if s=_asmdirectives[i] then
+        begin
+           token := tmotorolatoken(longint(firstdirective)+i);
+           exit;
+        end;
+     end;
+   end;
+
+
+   Procedure is_register(const s: string; var token: tmotorolatoken);
+  {*********************************************************************}
+  { PROCEDURE is_register(s: string; var token: tinteltoken);           }
+  {  Description: Determines if the s string is a valid register, if    }
+  {  so return token equal to A_REGISTER, otherwise does not change token}
+  {*********************************************************************}
+   Var
+    i: tregister;
+   Begin
+     for i:=firstasmreg to lastasmreg do
+     begin
+      if s=iasmregs[i] then
+      begin
+        token := AS_REGISTER;
+        exit;
+      end;
+     end;
+     { take care of other name for sp }
+     if s = 'A7' then
+     begin
+      token:=AS_REGISTER;
+      exit;
+     end;
+   end;
+
+
+
+  Function GetToken: tmotorolatoken;
+  {*********************************************************************}
+  { FUNCTION GetToken: tinteltoken;                                     }
+  {  Description: This routine returns intel assembler tokens and       }
+  {  does some minor syntax error checking.                             }
+  {*********************************************************************}
+  var
+   token: tmotorolatoken;
+   forcelabel: boolean;
+  begin
+    forcelabel := FALSE;
+    actasmpattern :='';
+    {* INIT TOKEN TO NOTHING *}
+    token := AS_NONE;
+    { while space and tab , continue scan... }
+    while c in [' ',#9] do
+     c:=current_scanner^.asmgetchar;
+
+    if not (c in [newline,#13,'{',';']) then
+     current_scanner^.gettokenpos;
+    { Possiblities for first token in a statement:                }
+    {   Local Label, Label, Directive, Prefix or Opcode....       }
+    if firsttoken and not (c in [newline,#13,'{',';']) then
+    begin
+
+      firsttoken := FALSE;
+      if c = '@' then
+      begin
+        token := AS_LLABEL;   { this is a local label }
+        { Let us point to the next character }
+        c := current_scanner^.asmgetchar;
+      end;
+
+
+
+      while c in ['A'..'Z','a'..'z','0'..'9','_','@','.'] do
+      begin
+         { if there is an at_sign, then this must absolutely be a label }
+         if c = '@' then forcelabel:=TRUE;
+         actasmpattern := actasmpattern + c;
+         c := current_scanner^.asmgetchar;
+      end;
+
+      uppervar(actasmpattern);
+
+      if c = ':' then
+      begin
+           case token of
+             AS_NONE: token := AS_LABEL;
+             AS_LLABEL: ; { do nothing }
+           end; { end case }
+           { let us point to the next character }
+           c := current_scanner^.asmgetchar;
+           gettoken := token;
+           exit;
+      end;
+
+      { Are we trying to create an identifier with }
+      { an at-sign...?                             }
+      if forcelabel then
+       Message(asmr_e_none_label_contain_at);
+
+      If is_asmopcode(actasmpattern) then
+      Begin
+       gettoken := AS_OPCODE;
+       exit;
+      end;
+      is_asmdirective(actasmpattern, token);
+      if (token <> AS_NONE) then
+      Begin
+        gettoken := token;
+        exit
+      end
+      else
+      begin
+         gettoken := AS_NONE;
+         Message1(asmr_e_invalid_or_missing_opcode,actasmpattern);
+      end;
+    end
+    else { else firsttoken }
+    { Here we must handle all possible cases                              }
+    begin
+      case c of
+
+         '@':   { possiblities : - local label reference , such as in jmp @local1 }
+                {                - @Result, @Code or @Data special variables.     }
+                            begin
+                             actasmpattern := c;
+                             c:= current_scanner^.asmgetchar;
+                             while c in  ['A'..'Z','a'..'z','0'..'9','_','@','.'] do
+                             begin
+                               actasmpattern := actasmpattern + c;
+                               c := current_scanner^.asmgetchar;
+                             end;
+                             uppervar(actasmpattern);
+                             gettoken := AS_ID;
+                             exit;
+                            end;
+      { identifier, register, opcode, prefix or directive }
+         'A'..'Z','a'..'z','_': begin
+                             actasmpattern := c;
+                             c:= current_scanner^.asmgetchar;
+                             while c in  ['A'..'Z','a'..'z','0'..'9','_','.'] do
+                             begin
+                               actasmpattern := actasmpattern + c;
+                               c := current_scanner^.asmgetchar;
+                             end;
+                             uppervar(actasmpattern);
+
+                             If is_asmopcode(actasmpattern) then
+                             Begin
+                                    gettoken := AS_OPCODE;
+                                    exit;
+                             end;
+                             is_register(actasmpattern, token);
+                             {is_asmoperator(actasmpattern,token);}
+                             is_asmdirective(actasmpattern,token);
+                             { if found }
+                             if (token <> AS_NONE) then
+                             begin
+                               gettoken := token;
+                               exit;
+                             end
+                             { this is surely an identifier }
+                             else
+                               token := AS_ID;
+                             gettoken := token;
+                             exit;
+                          end;
+           { override operator... not supported }
+           '&':       begin
+                         c:=current_scanner^.asmgetchar;
+                         gettoken := AS_AND;
+                      end;
+           { string or character }
+           '''' :
+                      begin
+                         actasmpattern:='';
+                         while true do
+                         begin
+                           if c = '''' then
+                           begin
+                              c:=current_scanner^.asmgetchar;
+                              if c=newline then
+                              begin
+                                 Message(scan_f_string_exceeds_line);
+                                 break;
+                              end;
+                              repeat
+                                  if c=''''then
+                                   begin
+                                       c:=current_scanner^.asmgetchar;
+                                       if c='''' then
+                                        begin
+                                               actasmpattern:=actasmpattern+'''';
+                                               c:=current_scanner^.asmgetchar;
+                                               if c=newline then
+                                               begin
+                                                    Message(scan_f_string_exceeds_line);
+                                                    break;
+                                               end;
+                                        end
+                                        else break;
+                                   end
+                                   else
+                                   begin
+                                          actasmpattern:=actasmpattern+c;
+                                          c:=current_scanner^.asmgetchar;
+                                          if c=newline then
+                                            begin
+                                               Message(scan_f_string_exceeds_line);
+                                               break
+                                            end;
+                                   end;
+                              until false; { end repeat }
+                           end
+                           else break; { end if }
+                         end; { end while }
+                   token:=AS_STRING;
+                   gettoken := token;
+                   exit;
+                 end;
+           '$' :  begin
+                    c:=current_scanner^.asmgetchar;
+                    while c in ['0'..'9','A'..'F','a'..'f'] do
+                    begin
+                      actasmpattern := actasmpattern + c;
+                      c := current_scanner^.asmgetchar;
+                    end;
+                   gettoken := AS_HEXNUM;
+                   exit;
+                  end;
+           ',' : begin
+                   gettoken := AS_COMMA;
+                   c:=current_scanner^.asmgetchar;
+                   exit;
+                 end;
+           '(' : begin
+                   gettoken := AS_LPAREN;
+                   c:=current_scanner^.asmgetchar;
+                   exit;
+                 end;
+           ')' : begin
+                   gettoken := AS_RPAREN;
+                   c:=current_scanner^.asmgetchar;
+                   exit;
+                 end;
+           ':' : begin
+                   gettoken := AS_COLON;
+                   c:=current_scanner^.asmgetchar;
+                   exit;
+                 end;
+{           '.' : begin
+                   gettoken := AS_DOT;
+                   c:=current_scanner^.asmgetchar;
+                   exit;
+                 end; }
+           '+' : begin
+                   gettoken := AS_PLUS;
+                   c:=current_scanner^.asmgetchar;
+                   exit;
+                 end;
+           '-' : begin
+                   gettoken := AS_MINUS;
+                   c:=current_scanner^.asmgetchar;
+                   exit;
+                 end;
+           '*' : begin
+                   gettoken := AS_STAR;
+                   c:=current_scanner^.asmgetchar;
+                   exit;
+                 end;
+           '/' : begin
+                   gettoken := AS_SLASH;
+                   c:=current_scanner^.asmgetchar;
+                   exit;
+                 end;
+           '<' : begin
+                   c := current_scanner^.asmgetchar;
+                   { invalid characters }
+                   if c <> '<' then
+                    Message(asmr_e_invalid_char_smaller);
+                   { still assume << }
+                   gettoken := AS_SHL;
+                   c := current_scanner^.asmgetchar;
+                   exit;
+                 end;
+           '>' : begin
+                   c := current_scanner^.asmgetchar;
+                   { invalid characters }
+                   if c <> '>' then
+                    Message(asmr_e_invalid_char_greater);
+                   { still assume << }
+                   gettoken := AS_SHR;
+                   c := current_scanner^.asmgetchar;
+                   exit;
+                 end;
+           '|' : begin
+                   gettoken := AS_OR;
+                   c := current_scanner^.asmgetchar;
+                   exit;
+                 end;
+           '^' : begin
+                  gettoken := AS_XOR;
+                  c := current_scanner^.asmgetchar;
+                  exit;
+                 end;
+           '#' : begin
+                  gettoken:=AS_APPT;
+                  c:=current_scanner^.asmgetchar;
+                  exit;
+                 end;
+           '%' : begin
+                   c:=current_scanner^.asmgetchar;
+                   while c in ['0','1'] do
+                   Begin
+                     actasmpattern := actasmpattern + c;
+                     c := current_scanner^.asmgetchar;
+                   end;
+                   gettoken := AS_BINNUM;
+                   exit;
+                 end;
+           { integer number }
+           '0'..'9': begin
+                        actasmpattern := c;
+                        c := current_scanner^.asmgetchar;
+                        while c in ['0'..'9'] do
+                          Begin
+                             actasmpattern := actasmpattern + c;
+                             c:= current_scanner^.asmgetchar;
+                          end;
+                        gettoken := AS_INTNUM;
+                        exit;
+                     end;
+         ';' : begin
+                  repeat
+                     c:=current_scanner^.asmgetchar;
+                  until c=newline;
+                  firsttoken := TRUE;
+                  gettoken:=AS_SEPARATOR;
+               end;
+
+         '{',#13,newline : begin
+                            c:=current_scanner^.asmgetchar;
+                            firsttoken := TRUE;
+                            gettoken:=AS_SEPARATOR;
+                           end;
+            else
+             Begin
+               Message(scan_f_illegal_char);
+             end;
+
+      end; { end case }
+    end; { end else if }
+  end;
+
+
+  {---------------------------------------------------------------------}
+  {                     Routines for the parsing                        }
+  {---------------------------------------------------------------------}
+
+     procedure consume(t : tmotorolatoken);
+
+     begin
+       if t<>actasmtoken then
+        Message(asmr_e_syntax_error);
+       actasmtoken:=gettoken;
+       { if the token must be ignored, then }
+       { get another token to parse.        }
+       if actasmtoken = AS_NONE then
+          actasmtoken := gettoken;
+      end;
+
+
+
+
+
+   function findregister(const s : string): tregister;
+  {*********************************************************************}
+  { FUNCTION findregister(s: string):tasmop;                            }
+  {  Description: Determines if the s string is a valid register,       }
+  {  if so returns correct tregister token, or R_NO if not found.       }
+  {*********************************************************************}
+   var
+    i: tregister;
+   begin
+     findregister := R_NO;
+     for i:=firstasmreg to lastasmreg do
+       if s = iasmregs[i] then
+       Begin
+         findregister := i;
+         exit;
+       end;
+    if s = 'A7' then
+    Begin
+      findregister := R_SP;
+      exit;
+    end;
+   end;
+
+
+   function findopcode(s: string): tasmop;
+  {*********************************************************************}
+  { FUNCTION findopcode(s: string): tasmop;                             }
+  {  Description: Determines if the s string is a valid opcode          }
+  {  if so returns correct tasmop token.                                }
+  {*********************************************************************}
+   var
+    i: tasmop;
+    j: byte;
+    op_size: string;
+   Begin
+     findopcode := A_NONE;
+     j:=pos('.',s);
+     if j<>0 then
+     begin
+       op_size:=copy(s,j+1,1);
+       case op_size[1] of
+       { For the motorola only opsize size is used to }
+       { determine the size of the operands.             }
+       'B': instr.opsize := S_B;
+       'W': instr.opsize := S_W;
+       'L': instr.opsize := S_L;
+       'S': instr.opsize := S_FS;
+       'D': instr.opsize := S_FL;
+       'X': instr.opsize := S_FX;
+       else
+        Message1(asmr_e_unknown_opcode,s);
+       end;
+       { delete everything starting from dot }
+       delete(s,j,length(s));
+     end;
+     for i:=firstop to lastop do
+       if  s = iasmops^[i] then
+       begin
+          findopcode:=i;
+          exit;
+       end;
+   end;
+
+  Procedure InitAsmRef(var instr: TInstruction);
+  {*********************************************************************}
+  {  Description: This routine first check if the instruction is of     }
+  {  type OPR_NONE, or OPR_REFERENCE , if not it gives out an error.    }
+  {  If the operandtype = OPR_NONE or <> OPR_REFERENCE then it sets up  }
+  {  the operand type to OPR_REFERENCE, as well as setting up the ref   }
+  {  to point to the default segment.                                   }
+  {*********************************************************************}
+   Begin
+     With instr do
+     Begin
+        case operands[operandnum]^.opr.typ of
+          OPR_REFERENCE: exit;
+          OPR_NONE: ;
+        else
+          Message(asmr_e_invalid_operand_type);
+        end;
+        operands[operandnum]^.opr.ref.direction := dir_none;
+        operands[operandnum]^.opr.typ := OPR_REFERENCE;
+        operands[operandnum]^.opr.ref.segment := R_DEFAULT_SEG;
+     end;
+   end;
+
+
+
+
+  Function CalculateExpression(expression: string): longint;
+  var
+    expr: TExprParse;
+  Begin
+   expr.Init;
+   CalculateExpression := expr.Evaluate(expression);
+   expr.Done;
+  end;
+
+
+  Procedure ConcatOpCode(var instr: TInstruction);
+  var
+    fits : boolean;
+    instruc: tasmop;
+  Begin
+     fits := FALSE;
+    { setup specific instructions for first pass }
+    instruc := instr.opcode;
+
+    { Setup special operands }
+    { Convert to general form as to conform to the m68k opcode table }
+    if (instruc = A_ADDA) or (instruc = A_ADDI)
+       then instruc := A_ADD
+    else
+    { CMPM excluded because of GAS v1.34 BUG }
+    if (instruc = A_CMPA) or
+       (instruc = A_CMPI) then
+       instruc := A_CMP
+    else
+    if instruc = A_EORI then
+      instruc := A_EOR
+    else
+    if instruc = A_MOVEA then
+     instruc := A_MOVE
+    else
+    if instruc = A_ORI then
+      instruc := A_OR
+    else
+    if (instruc = A_SUBA) or (instruc = A_SUBI) then
+      instruc :=  A_SUB;
+
+    { Setup operand types }
+
+(*
+    in instruc <> A_MOVEM then
+    Begin
+
+      while not(fits) do
+        begin
+         { set the instruction cache, if the instruction }
+         { occurs the first time                         }
+         if (it[i].i=instruc) and (ins_cache[instruc]=-1) then
+             ins_cache[instruc]:=i;
+
+         if (it[i].i=instruc) and (instr.ops=it[i].ops) then
+         begin
+            { first fit }
+           case instr.ops of
+             0 : begin
+                   fits:=true;
+                   break;
+                end;
+            1 :
+                Begin
+                  if (optyp1 and it[i].o1)<>0 then
+                  Begin
+                    fits:=true;
+                     break;
+                  end;
+                end;
+            2 : if ((optyp1 and it[i].o1)<>0) and
+                 ((optyp2 and it[i].o2)<>0) then
+                 Begin
+                       fits:=true;
+                       break;
+                 end
+            3 : if ((optyp1 and it[i].o1)<>0) and
+                 ((optyp2 and it[i].o2)<>0) and
+                 ((optyp3 and it[i].o3)<>0) then
+                 Begin
+                   fits:=true;
+                   break;
+                 end;
+           end; { end case }
+        end; { endif }
+        if it[i].i=A_NONE then
+        begin
+          { NO MATCH! }
+          Message(asmr_e_invalid_combination_opcode_and_operand);
+          exit;
+        end;
+        inc(i);
+       end; { end while }
+             *)
+  fits:=TRUE;
+
+  { We add the opcode to the opcode linked list }
+  if fits then
+  Begin
+    case instr.ops of
+
+     0:
+        if instr.opsize <> S_NO then
+          p^.concat(new(paicpu,op_none(instruc,instr.opsize)))
+        else
+          p^.concat(new(paicpu,op_none(instruc,S_NO)));
+     1: Begin
+          case instr.operands[1]^.opr.typ of
+           OPR_SYMBOL: Begin
+                             p^.concat(new(paicpu,op_sym_ofs(instruc,
+                               instr.opsize, instr.operands[1]^.opr.symbol,instr.operands[1]^.opr.symofs)));
+                         end;
+           OPR_CONSTANT: Begin
+                             p^.concat(new(paicpu,op_const(instruc,
+                               instr.opsize, instr.operands[1]^.opr.val)));
+                         end;
+           OPR_REGISTER:  p^.concat(new(paicpu,op_reg(instruc,
+                            instr.opsize,instr.operands[1]^.opr.reg)));
+           OPR_REFERENCE:
+                          if instr.opsize <> S_NO then
+                          Begin
+                           p^.concat(new(paicpu,op_ref(instruc,
+                            instr.opsize,newreference(instr.operands[1]^.opr.ref))));
+                          end
+                          else
+                          Begin
+                              { special jmp and call case with }
+                              { symbolic references.           }
+                              if instruc in [A_BSR,A_JMP,A_JSR,A_BRA,A_PEA] then
+                              Begin
+                                p^.concat(new(paicpu,op_ref(instruc,
+                                  S_NO,newreference(instr.operands[1]^.opr.ref))));
+                              end
+                              else
+                                Message(asmr_e_invalid_opcode_and_operand);
+                          end;
+           OPR_NONE: Begin
+                       Message(asmr_e_invalid_opcode_and_operand);
+                     end;
+          else
+           Begin
+             Message(asmr_e_invalid_opcode_and_operand);
+           end;
+          end;
+        end;
+     2:
+        Begin
+                With instr do
+                Begin
+                { source }
+                  case operands[1]^.opr.typ of
+                  { reg,reg     }
+                  { reg,ref     }
+                   OPR_REGISTER:
+                     Begin
+                       case operands[2]^.opr.typ of
+                         OPR_REGISTER:
+                            Begin
+                               p^.concat(new(paicpu,op_reg_reg(instruc,
+                               opsize,operands[1]^.opr.reg,operands[2]^.opr.reg)));
+                            end;
+                         OPR_REFERENCE:
+                                  p^.concat(new(paicpu,op_reg_ref(instruc,
+                                  opsize,operands[1]^.opr.reg,newreference(operands[2]^.opr.ref))));
+                       else { else case }
+                         Begin
+                           Message(asmr_e_invalid_opcode_and_operand);
+                         end;
+                       end; { end second operand case for OPR_REGISTER }
+                     end;
+                  { reglist, ref }
+                   OPR_REGLIST:
+                          Begin
+                            case operands[2]^.opr.typ of
+                              OPR_REFERENCE :
+                                  p^.concat(new(paicpu,op_reglist_ref(instruc,
+                                  opsize,operands[1]^.opr.reglist^,newreference(operands[2]^.opr.ref))));
+                            else
+                             Begin
+                               Message(asmr_e_invalid_opcode_and_operand);
+                             end;
+                            end; { end second operand case for OPR_REGLIST }
+                          end;
+
+                  { const,reg   }
+                  { const,const }
+                  { const,ref   }
+                   OPR_CONSTANT:
+                      case instr.operands[2]^.opr.typ of
+                      { constant, constant does not have a specific size. }
+                        OPR_CONSTANT:
+                           p^.concat(new(paicpu,op_const_const(instruc,
+                           S_NO,operands[1]^.opr.val,operands[2]^.opr.val)));
+                        OPR_REFERENCE:
+                           Begin
+                                 p^.concat(new(paicpu,op_const_ref(instruc,
+                                 opsize,operands[1]^.opr.val,
+                                 newreference(operands[2]^.opr.ref))))
+                           end;
+                        OPR_REGISTER:
+                           Begin
+                                 p^.concat(new(paicpu,op_const_reg(instruc,
+                                 opsize,operands[1]^.opr.val,
+                                 operands[2]^.opr.reg)))
+                           end;
+                      else
+                         Begin
+                           Message(asmr_e_invalid_opcode_and_operand);
+                         end;
+                      end; { end second operand case for OPR_CONSTANT }
+                   { ref,reg     }
+                   { ref,ref     }
+                   OPR_REFERENCE:
+                      case instr.operands[2]^.opr.typ of
+                         OPR_REGISTER:
+                            Begin
+                              p^.concat(new(paicpu,op_ref_reg(instruc,
+                               opsize,newreference(operands[1]^.opr.ref),
+                               operands[2]^.opr.reg)));
+                            end;
+                         OPR_REGLIST:
+                            Begin
+                              p^.concat(new(paicpu,op_ref_reglist(instruc,
+                               opsize,newreference(operands[1]^.opr.ref),
+                               operands[2]^.opr.reglist^)));
+                            end;
+                         OPR_REFERENCE: { special opcodes }
+                            p^.concat(new(paicpu,op_ref_ref(instruc,
+                            opsize,newreference(operands[1]^.opr.ref),
+                            newreference(operands[2]^.opr.ref))));
+                      else
+                         Begin
+                           Message(asmr_e_invalid_opcode_and_operand);
+                         end;
+                      end; { end second operand case for OPR_REFERENCE }
+           OPR_SYMBOL: case operands[2]^.opr.typ of
+                        OPR_REFERENCE:
+                           Begin
+                                 p^.concat(new(paicpu,op_sym_ofs_ref(instruc,
+                                   opsize,instr.operands[1]^.opr.symbol,instr.operands[1]^.opr.symofs,
+                                   newreference(operands[2]^.opr.ref))))
+                           end;
+                        OPR_REGISTER:
+                           Begin
+                                 p^.concat(new(paicpu,op_sym_ofs_reg(instruc,
+                                   opsize,instr.operands[1]^.opr.symbol,instr.operands[1]^.opr.symofs,
+                                   operands[2]^.opr.reg)))
+                           end;
+                      else
+                         Begin
+                           Message(asmr_e_invalid_opcode_and_operand);
+                         end;
+                      end; { end second operand case for OPR_SYMBOL }
+                  else
+                     Begin
+                       Message(asmr_e_invalid_opcode_and_operand);
+                     end;
+                  end; { end first operand case }
+                end; { end with }
+        end;
+     3: Begin
+           if (instruc = A_DIVSL) or (instruc = A_DIVUL) or (instruc = A_MULU)
+           or (instruc = A_MULS) or (instruc = A_DIVS) or (instruc = A_DIVU) then
+           Begin
+             if (instr.operands[1]^.opr.typ <> OPR_REGISTER)
+             or (instr.operands[2]^.opr.typ <> OPR_REGISTER)
+             or (instr.operands[3]^.opr.typ <> OPR_REGISTER) then
+             Begin
+               Message(asmr_e_invalid_opcode_and_operand);
+             end
+             else
+             Begin
+               p^.concat(new(paicpu, op_reg_reg_reg(instruc,instr.opsize,
+                 instr.operands[1]^.opr.reg,instr.operands[2]^.opr.reg,instr.operands[3]^.opr.reg)));
+             end;
+           end
+           else
+            Message(asmr_e_invalid_opcode_and_operand);
+        end;
+  end; { end case }
+ end;
+ end;
+
+
+    Procedure ConcatLabeledInstr(var instr: TInstruction);
+    Begin
+       if ((instr.opcode >= A_BCC) and (instr.opcode <= A_BVS))
+       or (instr.opcode = A_BRA) or (instr.opcode = A_BSR)
+       or (instr.opcode = A_JMP) or (instr.opcode = A_JSR)
+       or ((instr.opcode >= A_FBEQ) and (instr.opcode <= A_FBNGLE))
+       then
+       Begin
+        if instr.ops > 2 then
+          Message(asmr_e_invalid_opcode_and_operand)
+        else if instr.operands[1]^.opr.typ <> OPR_SYMBOL then
+          Message(asmr_e_invalid_opcode_and_operand)
+        else if (instr.operands[1]^.opr.typ = OPR_SYMBOL) and
+         (instr.ops = 1) then
+           if assigned(instr.operands[1]^.opr.symbol) and
+              (instr.operands[1]^.opr.symofs=0) then
+             p^.concat(new(pai_labeled,init_sym(instr.opcode,
+               instr.operands[1]^.opr.symbol)))
+           else
+            Message(asmr_e_invalid_opcode_and_operand);
+       end
+       else
+       if ((instr.opcode >= A_DBCC) and (instr.opcode <= A_DBF))
+       or ((instr.opcode >= A_FDBEQ) and (instr.opcode <= A_FBDNGLE)) then
+       begin
+         if (instr.ops<>2) or
+            (instr.operands[1]^.opr.typ <> OPR_REGISTER) or
+            (instr.operands[2]^.opr.typ <> OPR_SYMBOL) or
+            (instr.operands[2]^.opr.symofs <> 0) then
+           Message(asmr_e_invalid_opcode_and_operand)
+         else
+          p^.concat(new(pai_labeled,init_reg_sym(instr.opcode,
+           instr.operands[2]^.opr.symbol,instr.operands[1]^.opr.reg)));
+       end
+       else
+        Message(asmr_e_invalid_opcode_and_operand);
+    end;
+
+    Function BuildExpression(allow_symbol : boolean; asmsym : pstring) : longint;
+  {*********************************************************************}
+  { FUNCTION BuildExpression: longint                                   }
+  {  Description: This routine calculates a constant expression to      }
+  {  a given value. The return value is the value calculated from       }
+  {  the expression.                                                    }
+  { The following tokens (not strings) are recognized:                  }
+  {    (,),SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants.  }
+  {*********************************************************************}
+  { ENTRY: On entry the token should be any valid expression token.     }
+  { EXIT:  On Exit the token points to either COMMA or SEPARATOR        }
+  { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
+  {  invalid tokens.                                                    }
+  {*********************************************************************}
+  var expr: string;
+      hs, tempstr: string;
+      sym : psym;
+      hl : pasmlabel;
+      l : longint;
+      errorflag: boolean;
+  Begin
+    errorflag := FALSE;
+    expr := '';
+    tempstr := '';
+    if allow_symbol then
+      asmsym^:='';
+    Repeat
+      Case actasmtoken of
+      AS_LPAREN: Begin
+                  Consume(AS_LPAREN);
+                  expr := expr + '(';
+                end;
+      AS_RPAREN: Begin
+                  Consume(AS_RPAREN);
+                  expr := expr + ')';
+                end;
+      AS_SHL:    Begin
+                  Consume(AS_SHL);
+                  expr := expr + '<';
+                end;
+      AS_SHR:    Begin
+                  Consume(AS_SHR);
+                  expr := expr + '>';
+                end;
+      AS_SLASH:  Begin
+                  Consume(AS_SLASH);
+                  expr := expr + '/';
+                end;
+      AS_MOD:    Begin
+                  Consume(AS_MOD);
+                  expr := expr + '%';
+                end;
+      AS_STAR:   Begin
+                  Consume(AS_STAR);
+                  expr := expr + '*';
+                end;
+      AS_PLUS:   Begin
+                  Consume(AS_PLUS);
+                  expr := expr + '+';
+                end;
+      AS_MINUS:  Begin
+                  Consume(AS_MINUS);
+                  expr := expr + '-';
+                end;
+      AS_AND:    Begin
+                  Consume(AS_AND);
+                  expr := expr + '&';
+                end;
+      AS_NOT:    Begin
+                  Consume(AS_NOT);
+                  expr := expr + '~';
+                end;
+      AS_XOR:    Begin
+                  Consume(AS_XOR);
+                  expr := expr + '^';
+                end;
+      AS_OR:     Begin
+                  Consume(AS_OR);
+                  expr := expr + '|';
+                end;
+      AS_ID:    Begin
+                  if SearchIConstant(actasmpattern,l) then
+                  Begin
+                    str(l, tempstr);
+                    expr := expr + tempstr;
+                    Consume(AS_ID);
+                  End else
+                  if not allow_symbol then
+                  Begin
+                    Message(asmr_e_syn_constant);
+                    l := 0;
+                  End else
+                  Begin
+                    hs:='';
+                    if (expr[Length(expr)]='+') then
+                      Delete(expr,Length(expr),1)
+                    else if expr<>'' then
+                      Begin
+                        Message(asmr_e_invalid_constant_expression);
+                        break;
+                      End;
+                    tempstr:=actasmpattern;
+                    consume(AS_ID);
+                    if (length(tempstr)>1) and (tempstr[1]='@') then
+                      begin
+                        CreateLocalLabel(tempstr,hl,false);
+                        hs:=hl^.name
+                      end
+                    else if SearchLabel(tempstr,hl,false) then
+                      hs:=hl^.name
+                    else
+                      begin
+                        getsym(tempstr,false);
+                        sym:=srsym;
+                        if assigned(sym) then
+                          begin
+                             case srsym^.typ of
+                               varsym :
+                                 begin
+                                   if sym^.owner^.symtabletype in [localsymtable,parasymtable] then
+                                    Message(asmr_e_no_local_or_para_allowed);
+                                   hs:=pvarsym(srsym)^.mangledname;
+                                 end;
+                               typedconstsym :
+                                 hs:=ptypedconstsym(srsym)^.mangledname;
+                               procsym :
+                                 hs:=pprocsym(srsym)^.mangledname;
+                               else
+                                 Message(asmr_e_wrong_sym_type);
+                             end;
+                          end
+                        else
+                           Message1(sym_e_unknown_id,tempstr);
+                      end;
+                     { symbol found? }
+                     if hs<>'' then
+                      begin
+                        if asmsym^='' then
+                         asmsym^:=hs
+                        else
+                         Message(asmr_e_cant_have_multiple_relocatable_symbols);
+                      end;
+                  end;
+                end;
+      AS_INTNUM:  Begin
+                   expr := expr + actasmpattern;
+                   Consume(AS_INTNUM);
+                  end;
+      AS_BINNUM:  Begin
+                      tempstr := tostr(ValBinary(actasmpattern));
+                      if tempstr = '' then
+                       Message(asmr_e_error_converting_binary);
+                      expr:=expr+tempstr;
+                      Consume(AS_BINNUM);
+                  end;
+
+      AS_HEXNUM: Begin
+                    tempstr := tostr(ValHexadecimal(actasmpattern));
+                    if tempstr = '' then
+                     Message(asmr_e_error_converting_hexadecimal);
+                    expr:=expr+tempstr;
+                    Consume(AS_HEXNUM);
+                end;
+      AS_OCTALNUM: Begin
+                    tempstr := tostr(ValOctal(actasmpattern));
+                    if tempstr = '' then
+                     Message(asmr_e_error_converting_octal);
+                    expr:=expr+tempstr;
+                    Consume(AS_OCTALNUM);
+                  end;
+      { go to next term }
+      AS_COMMA: Begin
+                  if not ErrorFlag then
+                    BuildExpression := CalculateExpression(expr)
+                  else
+                    BuildExpression := 0;
+                  Exit;
+               end;
+      { go to next symbol }
+      AS_SEPARATOR: Begin
+                      if not ErrorFlag then
+                        BuildExpression := CalculateExpression(expr)
+                      else
+                        BuildExpression := 0;
+                      Exit;
+                   end;
+      else
+        Begin
+          { only write error once. }
+          if not errorflag then
+           Message(asmr_e_invalid_constant_expression);
+          { consume tokens until we find COMMA or SEPARATOR }
+          Consume(actasmtoken);
+          errorflag := TRUE;
+        End;
+      end;
+    Until false;
+  end;
+
+
+  Procedure BuildRealConstant(typ : tfloattype);
+  {*********************************************************************}
+  { PROCEDURE BuilRealConst                                             }
+  {  Description: This routine calculates a constant expression to      }
+  {  a given value. The return value is the value calculated from       }
+  {  the expression.                                                    }
+  { The following tokens (not strings) are recognized:                  }
+  {    +/-,numbers and real numbers                                     }
+  {*********************************************************************}
+  { ENTRY: On entry the token should be any valid expression token.     }
+  { EXIT:  On Exit the token points to either COMMA or SEPARATOR        }
+  { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
+  {  invalid tokens.                                                    }
+  {*********************************************************************}
+  var expr: string;
+      r : extended;
+      code : word;
+      negativ : boolean;
+      errorflag: boolean;
+  Begin
+    errorflag := FALSE;
+    Repeat
+    negativ:=false;
+    expr := '';
+    if actasmtoken=AS_PLUS then Consume(AS_PLUS)
+    else if actasmtoken=AS_MINUS then
+      begin
+         negativ:=true;
+         consume(AS_MINUS);
+      end;
+    Case actasmtoken of
+      AS_INTNUM:  Begin
+                   expr := actasmpattern;
+                   Consume(AS_INTNUM);
+                 end;
+      AS_REALNUM:  Begin
+                   expr := actasmpattern;
+                   { in ATT syntax you have 0d in front of the real }
+                   { should this be forced ?  yes i think so, as to }
+                   { conform to gas as much as possible.            }
+                   if (expr[1]='0') and (upper(expr[2])='D') then
+                     expr:=copy(expr,3,255);
+                   Consume(AS_REALNUM);
+                 end;
+      AS_BINNUM:  Begin
+                      { checking for real constants with this should use  }
+                      { real DECODING otherwise the compiler will crash!  }
+                      Message(asmr_e_invalid_float_expr);
+                      expr:='0.0';
+                      Consume(AS_BINNUM);
+                 end;
+
+      AS_HEXNUM: Begin
+                      { checking for real constants with this should use  }
+                      { real DECODING otherwise the compiler will crash!  }
+                    Message(asmr_e_invalid_float_expr);
+                    expr:='0.0';
+                    Consume(AS_HEXNUM);
+                end;
+      AS_OCTALNUM: Begin
+                      { checking for real constants with this should use    }
+                      { real DECODING otherwise the compiler will crash!    }
+                      { xxxToDec using reals could be a solution, but the   }
+                      { problem is that these will crash the m68k compiler  }
+                      { when compiling -- because of lack of good fpu       }
+                      { support.                                           }
+                    Message(asmr_e_invalid_float_expr);
+                    expr:='0.0';
+                    Consume(AS_OCTALNUM);
+                  end;
+         else
+           Begin
+             { only write error once. }
+             if not errorflag then
+              Message(asmr_e_invalid_float_expr);
+             { consume tokens until we find COMMA or SEPARATOR }
+             Consume(actasmtoken);
+             errorflag := TRUE;
+           End;
+
+         end;
+      { go to next term }
+      if (actasmtoken=AS_COMMA) or (actasmtoken=AS_SEPARATOR) then
+        Begin
+          if negativ then expr:='-'+expr;
+          val(expr,r,code);
+          if code<>0 then
+            Begin
+               r:=0;
+               Message(asmr_e_invalid_float_expr);
+               ConcatRealConstant(p,r,typ);
+            End
+          else
+            Begin
+              ConcatRealConstant(p,r,typ);
+            End;
+        end
+      else
+        Message(asmr_e_invalid_float_expr);
+    Until actasmtoken=AS_SEPARATOR;
+  end;
+
+
+
+  Procedure BuildScaling(Var instr: TInstruction);
+  {*********************************************************************}
+  {  Takes care of parsing expression starting from the scaling value   }
+  {  up to and including possible field specifiers.                     }
+  { EXIT CONDITION:  On exit the routine should point to  AS_SEPARATOR  }
+  { or AS_COMMA. On entry should point to the AS_STAR  token.           }
+  {*********************************************************************}
+  var str:string;
+      l: longint;
+      code: integer;
+  Begin
+     Consume(AS_STAR);
+     if (instr.operands[operandnum]^.opr.ref.scalefactor <> 0)
+     and (instr.operands[operandnum]^.opr.ref.scalefactor <> 1) then
+      Message(asmr_e_wrong_base_index);
+     case actasmtoken of
+        AS_INTNUM: str := actasmpattern;
+        AS_HEXNUM: str := Tostr(ValHexadecimal(actasmpattern));
+        AS_BINNUM: str := Tostr(ValBinary(actasmpattern));
+        AS_OCTALNUM: str := Tostr(ValOctal(actasmpattern));
+     else
+        Message(asmr_e_syntax_error);
+     end;
+     val(str, l, code);
+     if code <> 0 then
+      Message(asmr_e_wrong_scale_factor);
+     if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) and (code = 0) then
+     begin
+        instr.operands[operandnum]^.opr.ref.scalefactor := l;
+     end
+     else
+     Begin
+        Message(asmr_e_wrong_scale_factor);
+        instr.operands[operandnum]^.opr.ref.scalefactor := 0;
+     end;
+     if instr.operands[operandnum]^.opr.ref.index = R_NO then
+     Begin
+        Message(asmr_e_wrong_base_index);
+        instr.operands[operandnum]^.opr.ref.scalefactor := 0;
+     end;
+    { Consume the scaling number }
+    Consume(actasmtoken);
+    if actasmtoken = AS_RPAREN then
+        Consume(AS_RPAREN)
+    else
+       Message(asmr_e_wrong_scale_factor);
+    { // .Field.Field ... or separator/comma // }
+    if actasmtoken in [AS_COMMA,AS_SEPARATOR] then
+    Begin
+    end
+    else
+     Message(asmr_e_syntax_error);
+  end;
+
+
+  Function BuildRefExpression: longint;
+  {*********************************************************************}
+  { FUNCTION BuildExpression: longint                                   }
+  {  Description: This routine calculates a constant expression to      }
+  {  a given value. The return value is the value calculated from       }
+  {  the expression.                                                    }
+  { The following tokens (not strings) are recognized:                  }
+  {    SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants.      }
+  {*********************************************************************}
+  { ENTRY: On entry the token should be any valid expression token.     }
+  { EXIT:  On Exit the token points to the LPAREN token.                }
+  { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
+  {  invalid tokens.                                                    }
+  {*********************************************************************}
+  var tempstr: string;
+      expr: string;
+    l : longint;
+    errorflag : boolean;
+  Begin
+    errorflag := FALSE;
+    tempstr := '';
+    expr := '';
+    Repeat
+      Case actasmtoken of
+      AS_RPAREN: Begin
+                   Message(asmr_e_syntax_error);
+                  Consume(AS_RPAREN);
+                end;
+      AS_SHL:    Begin
+                  Consume(AS_SHL);
+                  expr := expr + '<';
+                end;
+      AS_SHR:    Begin
+                  Consume(AS_SHR);
+                  expr := expr + '>';
+                end;
+      AS_SLASH:  Begin
+                  Consume(AS_SLASH);
+                  expr := expr + '/';
+                end;
+      AS_MOD:    Begin
+                  Consume(AS_MOD);
+                  expr := expr + '%';
+                end;
+      AS_STAR:   Begin
+                  Consume(AS_STAR);
+                  expr := expr + '*';
+                end;
+      AS_PLUS:   Begin
+                  Consume(AS_PLUS);
+                  expr := expr + '+';
+                end;
+      AS_MINUS:  Begin
+                  Consume(AS_MINUS);
+                  expr := expr + '-';
+                end;
+      AS_AND:    Begin
+                  Consume(AS_AND);
+                  expr := expr + '&';
+                end;
+      AS_NOT:    Begin
+                  Consume(AS_NOT);
+                  expr := expr + '~';
+                end;
+      AS_XOR:    Begin
+                  Consume(AS_XOR);
+                  expr := expr + '^';
+                end;
+      AS_OR:     Begin
+                  Consume(AS_OR);
+                  expr := expr + '|';
+                end;
+      { End of reference }
+      AS_LPAREN: Begin
+                     if not ErrorFlag then
+                        BuildRefExpression := CalculateExpression(expr)
+                     else
+                        BuildRefExpression := 0;
+                     { no longer in an expression }
+                     exit;
+                  end;
+      AS_ID:
+                Begin
+                  if NOT SearchIConstant(actasmpattern,l) then
+                  Begin
+                    Message(asmr_e_syn_constant);
+                    l := 0;
+                  end;
+                  str(l, tempstr);
+                  expr := expr + tempstr;
+                  Consume(AS_ID);
+                end;
+      AS_INTNUM:  Begin
+                   expr := expr + actasmpattern;
+                   Consume(AS_INTNUM);
+                 end;
+      AS_BINNUM:  Begin
+                      tempstr := Tostr(ValBinary(actasmpattern));
+                      if tempstr = '' then
+                       Message(asmr_e_error_converting_binary);
+                      expr:=expr+tempstr;
+                      Consume(AS_BINNUM);
+                 end;
+
+      AS_HEXNUM: Begin
+                    tempstr := Tostr(ValHexadecimal(actasmpattern));
+                    if tempstr = '' then
+                     Message(asmr_e_error_converting_hexadecimal);
+                    expr:=expr+tempstr;
+                    Consume(AS_HEXNUM);
+                end;
+      AS_OCTALNUM: Begin
+                    tempstr := Tostr(ValOctal(actasmpattern));
+                    if tempstr = '' then
+                     Message(asmr_e_error_converting_octal);
+                    expr:=expr+tempstr;
+                    Consume(AS_OCTALNUM);
+                  end;
+      else
+        Begin
+          { write error only once. }
+          if not errorflag then
+           Message(asmr_e_invalid_constant_expression);
+          BuildRefExpression := 0;
+          if actasmtoken in [AS_COMMA,AS_SEPARATOR] then exit;
+          { consume tokens until we find COMMA or SEPARATOR }
+          Consume(actasmtoken);
+          errorflag := TRUE;
+        end;
+      end;
+    Until false;
+  end;
+
+
+  Procedure BuildReference(var Instr: TInstruction);
+  {*********************************************************************}
+  { PROCEDURE BuildBracketExpression                                    }
+  {  Description: This routine builds up an expression after a LPAREN   }
+  {  token is encountered.                                              }
+  {   On entry actasmtoken should be equal to AS_LPAREN                 }
+  {*********************************************************************}
+  { EXIT CONDITION:  On exit the routine should point to either the     }
+  {       AS_COMMA or AS_SEPARATOR token.                               }
+  {*********************************************************************}
+  var
+    l:longint;
+    code: integer;
+    str: string;
+  Begin
+     Consume(AS_LPAREN);
+     Case actasmtoken of
+        { // (reg ... // }
+        AS_REGISTER: Begin
+                        instr.operands[operandnum]^.opr.ref.base :=
+                           findregister(actasmpattern);
+                        Consume(AS_REGISTER);
+                        { can either be a register or a right parenthesis }
+                         { // (reg)       // }
+                         { // (reg)+      // }
+                         if actasmtoken=AS_RPAREN then
+                         Begin
+                           Consume(AS_RPAREN);
+                           if actasmtoken = AS_PLUS then
+                           Begin
+                             if (instr.operands[operandnum]^.opr.ref.direction <> dir_none) then
+                              Message(asmr_e_no_inc_and_dec_together)
+                             else
+                               instr.operands[operandnum]^.opr.ref.direction := dir_inc;
+                             Consume(AS_PLUS);
+                           end;
+                           if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
+                             Begin
+                               Message(asmr_e_invalid_reference_syntax);
+                               { error recovery ... }
+                               while actasmtoken <> AS_SEPARATOR do
+                                  Consume(actasmtoken);
+                             end;
+                             exit;
+                         end;
+                       { // (reg,reg .. // }
+                       Consume(AS_COMMA);
+                       if actasmtoken = AS_REGISTER then
+                       Begin
+                         instr.operands[operandnum]^.opr.ref.index :=
+                           findregister(actasmpattern);
+                         Consume(AS_REGISTER);
+                         { check for scaling ... }
+                         case actasmtoken of
+                           AS_RPAREN:
+                              Begin
+                                Consume(AS_RPAREN);
+                                if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
+                                Begin
+                                { error recovery ... }
+                                  Message(asmr_e_invalid_reference_syntax);
+                                  while actasmtoken <> AS_SEPARATOR do
+                                    Consume(actasmtoken);
+                                end;
+                                exit;
+                              end;
+                           AS_STAR:
+                              Begin
+                                BuildScaling(instr);
+                              end;
+                         else
+                           Begin
+                             Message(asmr_e_invalid_reference_syntax);
+                             while (actasmtoken <> AS_SEPARATOR) do
+                               Consume(actasmtoken);
+                           end;
+                         end; { end case }
+                       end
+                       else
+                          Begin
+                             Message(asmr_e_invalid_reference_syntax);
+                            while (actasmtoken <> AS_SEPARATOR) do
+                                Consume(actasmtoken);
+                          end;
+                     end;
+       AS_HEXNUM,AS_OCTALNUM,   { direct address }
+       AS_BINNUM,AS_INTNUM: Begin
+                                case actasmtoken of
+                                        AS_INTNUM: str := actasmpattern;
+                                        AS_HEXNUM: str := Tostr(ValHexadecimal(actasmpattern));
+                                        AS_BINNUM: str := Tostr(ValBinary(actasmpattern));
+                                        AS_OCTALNUM: str := Tostr(ValOctal(actasmpattern));
+                                else
+                                        Message(asmr_e_syntax_error);
+                                end;
+                                Consume(actasmtoken);
+                                val(str, l, code);
+                                if code <> 0 then
+                                     Message(asmr_e_invalid_reference_syntax)
+                                else
+                                     instr.operands[operandnum]^.opr.ref.offset := l;
+                                Consume(AS_RPAREN);
+                                if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
+                                Begin
+                                      { error recovery ... }
+                                      Message(asmr_e_invalid_reference_syntax);
+                                      while actasmtoken <> AS_SEPARATOR do
+                                        Consume(actasmtoken);
+                                end;
+                                exit;
+                            end;
+     else
+       Begin
+
+         Message(asmr_e_invalid_reference_syntax);
+         while (actasmtoken <> AS_SEPARATOR) do
+           Consume(actasmtoken);
+       end;
+     end; { end case }
+  end;
+
+
+  Procedure BuildOperand(var instr: TInstruction);
+  {*********************************************************************}
+  { EXIT CONDITION:  On exit the routine should point to either the     }
+  {       AS_COMMA or AS_SEPARATOR token.                               }
+  {*********************************************************************}
+  var
+    tempstr: string;
+    expr: string;
+    lab: Pasmlabel;
+    l : longint;
+    i: tregister;
+    hl: pasmlabel;
+    reg_one, reg_two: tregister;
+    reglist: set of tregister;
+  Begin
+   reglist := [];
+   tempstr := '';
+   expr := '';
+   case actasmtoken of
+   { // Memory reference //  }
+     AS_LPAREN:
+               Begin
+                  initAsmRef(instr);
+                  BuildReference(instr);
+               end;
+   { // Constant expression //  }
+     AS_APPT:  Begin
+                      Consume(AS_APPT);
+                      if not (instr.operands[operandnum]^.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+                         Message(asmr_e_invalid_operand_type);
+                      { identifiers are handled by BuildExpression }
+                      instr.operands[operandnum]^.opr.typ := OPR_CONSTANT;
+                      instr.operands[operandnum]^.opr.val :=BuildExpression(true,@tempstr);
+                      if tempstr<>'' then
+                        begin
+                          l:=instr.operands[operandnum]^.opr.val;
+                          instr.operands[operandnum]^.opr.typ := OPR_SYMBOL;
+                          instr.operands[operandnum]^.opr.symofs := l;
+                          instr.operands[operandnum]^.opr.symbol := newasmsymbol(tempstr);
+                        end;
+                 end;
+   { // Constant memory offset .              // }
+   { // This must absolutely be followed by ( // }
+     AS_HEXNUM,AS_INTNUM,
+     AS_BINNUM,AS_OCTALNUM,AS_PLUS:
+                   Begin
+                      InitAsmRef(instr);
+                      instr.operands[operandnum]^.opr.ref.offset:=BuildRefExpression;
+                      BuildReference(instr);
+                   end;
+   { // A constant expression, or a Variable ref. // }
+     AS_ID:  Begin
+              if actasmpattern[1] = '@' then
+              { // Label or Special symbol reference // }
+              Begin
+                 if actasmpattern = '@RESULT' then
+                   Begin
+                      InitAsmRef(instr);
+                      instr.operands[operandnum]^.SetUpResult;
+                   end
+                 else
+                  if (actasmpattern = '@CODE') or (actasmpattern = '@DATA') then
+                    Message(asmr_w_CODE_and_DATA_not_supported)
+                   else
+                  Begin
+                    delete(actasmpattern,1,1);
+                    if actasmpattern = '' then
+                     Message(asmr_e_null_label_ref_not_allowed);
+                    CreateLocalLabel(actasmpattern,lab,false);
+                    instr.operands[operandnum]^.opr.typ := OPR_SYMBOL;
+                    instr.operands[operandnum]^.opr.symbol := lab;
+                    instr.operands[operandnum]^.opr.symofs := 0;
+                    instr.labeled := TRUE;
+                  end;
+                Consume(AS_ID);
+                if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+                 Message(asmr_e_syntax_error);
+              end
+              { probably a variable or normal expression }
+              { or a procedure (such as in CALL ID)      }
+              else
+               Begin
+                   { is it a constant ? }
+                   if SearchIConstant(actasmpattern,l) then
+                   Begin
+                      InitAsmRef(instr);
+                      instr.operands[operandnum]^.opr.ref.offset:=BuildRefExpression;
+                      BuildReference(instr);
+
+{                      if not (instr.operands[operandnum].opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+                        Message(asmr_e_invalid_operand_type);
+                      instr.operands[operandnum].opr.typ := OPR_CONSTANT;
+                      instr.operands[operandnum].val :=BuildExpression;}
+                    end
+                   else { is it a label variable ? }
+                    Begin
+                     { // ID[ , ID.Field.Field or simple ID // }
+                     { check if this is a label, if so then }
+                     { emit it as a label.                  }
+                     if SearchLabel(actasmpattern,hl,false) then
+                     Begin
+                        instr.operands[operandnum]^.opr.typ := OPR_SYMBOL;
+                        instr.operands[operandnum]^.opr.symbol := hl;
+                        instr.operands[operandnum]^.opr.symofs := 0;
+                        instr.labeled := TRUE;
+                        Consume(AS_ID);
+                        if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+                         Message(asmr_e_syntax_error);
+                     end
+                     else
+                     { is it a normal variable ? }
+                     Begin
+                      initAsmRef(instr);
+                      if not instr.operands[operandnum]^.SetUpVar(actasmpattern,false) then
+                      Begin
+                         { not a variable.. }
+                         { check special variables.. }
+                         if actasmpattern = 'SELF' then
+                          { special self variable }
+                         Begin
+                           if assigned(procinfo^._class) then
+                             Begin
+                               instr.operands[operandnum]^.opr.ref.offset := procinfo^.selfpointer_offset;
+                               instr.operands[operandnum]^.opr.ref.base := procinfo^.framepointer;
+                             end
+                           else
+                             Message(asmr_e_cannot_use_SELF_outside_a_method);
+                         end
+                         else
+                         if (cs_compilesystem in aktmoduleswitches) then
+                         Begin
+                           if not assigned(instr.operands[operandnum]^.opr.ref.symbol) then
+                            Begin
+                             if getasmsymbol(actasmpattern) =nil then
+                               Message1(asmr_w_id_supposed_external,actasmpattern);
+                             instr.operands[operandnum]^.opr.ref.symbol:=newasmsymbol(actasmpattern);
+                            end
+                           else
+                             Message(asmr_e_syntax_error);
+                         end
+                         else
+                           Message1(asmr_e_unknown_label_identifier,actasmpattern);
+                      end;
+                      expr := actasmpattern;
+                      Consume(AS_ID);
+                      case actasmtoken of
+                           AS_LPAREN: { indexing }
+                                        BuildReference(instr);
+                           AS_SEPARATOR,AS_COMMA: ;
+                      else
+                           Message(asmr_e_syntax_error);
+                      end;
+                     end;
+                    end;
+               end;
+            end;
+   { // Pre-decrement mode reference or constant mem offset.   // }
+     AS_MINUS:    Begin
+                   Consume(AS_MINUS);
+                   if actasmtoken = AS_LPAREN then
+                   Begin
+                     InitAsmRef(instr);
+                     { indicate pre-decrement mode }
+                     instr.operands[operandnum]^.opr.ref.direction := dir_dec;
+                     BuildReference(instr);
+                   end
+                   else
+                   if actasmtoken in [AS_OCTALNUM,AS_HEXNUM,AS_BINNUM,AS_INTNUM] then
+                   Begin
+                      InitAsmRef(instr);
+                      instr.operands[operandnum]^.opr.ref.offset:=BuildRefExpression;
+                      { negate because was preceded by a negative sign! }
+                      instr.operands[operandnum]^.opr.ref.offset:=-instr.operands[operandnum]^.opr.ref.offset;
+                      BuildReference(instr);
+                   end
+                   else
+                   Begin
+                    Message(asmr_e_syntax_error);
+                    while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+                       Consume(actasmtoken);
+                   end;
+                  end;
+   { // Register, a variable reference or a constant reference // }
+     AS_REGISTER: Begin
+                   { save the type of register used. }
+                   tempstr := actasmpattern;
+                   Consume(AS_REGISTER);
+                   { // Simple register // }
+                   if (actasmtoken = AS_SEPARATOR) or (actasmtoken = AS_COMMA) then
+                   Begin
+                        if not (instr.operands[operandnum]^.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+                         Message(asmr_e_invalid_operand_type);
+                        instr.operands[operandnum]^.opr.typ := OPR_REGISTER;
+                        instr.operands[operandnum]^.opr.reg := findregister(tempstr);
+                   end
+                   else
+                   { HERE WE MUST HANDLE THE SPECIAL CASE OF MOVEM AND FMOVEM }
+                   { // Individual register listing // }
+                   if (actasmtoken = AS_SLASH) then
+                   Begin
+                     reglist := [findregister(tempstr)];
+                     Consume(AS_SLASH);
+                     if actasmtoken = AS_REGISTER then
+                     Begin
+                       While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+                       Begin
+                         case actasmtoken of
+                          AS_REGISTER: Begin
+                                        reglist := reglist + [findregister(actasmpattern)];
+                                        Consume(AS_REGISTER);
+                                       end;
+                          AS_SLASH: Consume(AS_SLASH);
+                          AS_SEPARATOR,AS_COMMA: break;
+                         else
+                          Begin
+                            Message(asmr_e_invalid_reg_list_in_movem);
+                            Consume(actasmtoken);
+                          end;
+                         end; { end case }
+                       end; { end while }
+                       instr.operands[operandnum]^.opr.typ:= OPR_REGLIST;
+                       instr.operands[operandnum]^.opr.reglist := newreglist(reglist);
+                     end
+                     else
+                      { error recovery ... }
+                      Begin
+                            Message(asmr_e_invalid_reg_list_in_movem);
+                            while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+                               Consume(actasmtoken);
+                      end;
+                   end
+                   else
+                   { // Range register listing // }
+                   if (actasmtoken = AS_MINUS) then
+                   Begin
+                     Consume(AS_MINUS);
+                     reg_one:=findregister(tempstr);
+                     if actasmtoken <> AS_REGISTER then
+                     Begin
+                       Message(asmr_e_invalid_reg_list_in_movem);
+                       while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+                         Consume(actasmtoken);
+                     end
+                     else
+                     Begin
+                      { determine the register range ... }
+                      reg_two:=findregister(actasmpattern);
+                      if reg_one > reg_two then
+                      begin
+                       for i:=reg_two to reg_one do
+                         reglist := reglist + [i];
+                      end
+                      else
+                      Begin
+                       for i:=reg_one to reg_two do
+                         reglist := reglist + [i];
+                      end;
+                      Consume(AS_REGISTER);
+                      if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+                      Begin
+                       Message(asmr_e_invalid_reg_list_in_movem);
+                       while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+                         Consume(actasmtoken);
+                      end;
+                      { set up instruction }
+                      instr.operands[operandnum]^.opr.typ:= OPR_REGLIST;
+                      instr.operands[operandnum]^.opr.reglist := newreglist(reglist);
+                     end;
+                   end
+                   else
+                   { DIVSL/DIVS/MULS/MULU with long for MC68020 only }
+                   if (actasmtoken = AS_COLON) then
+                   Begin
+                     if (aktoptprocessor = MC68020) or (cs_compilesystem in aktmoduleswitches) then
+                     Begin
+                       Consume(AS_COLON);
+                       if (actasmtoken = AS_REGISTER) then
+                       Begin
+                         { set up old field, since register is valid }
+                         instr.operands[operandnum]^.opr.typ := OPR_REGISTER;
+                         instr.operands[operandnum]^.opr.reg := findregister(tempstr);
+                         Inc(operandnum);
+                         instr.operands[operandnum]^.opr.typ := OPR_REGISTER;
+                         instr.operands[operandnum]^.opr.reg := findregister(actasmpattern);
+                         Consume(AS_REGISTER);
+                         if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+                         Begin
+                          Message(asmr_e_invalid_reg_list_for_opcode);
+                          while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+                            Consume(actasmtoken);
+                         end;
+                       end;
+                     end
+                     else
+                     Begin
+                        Message(asmr_e_68020_mode_required);
+                        if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
+                        Begin
+                          Message(asmr_e_invalid_reg_list_for_opcode);
+                          while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+                            Consume(actasmtoken);
+                        end;
+                     end;
+                   end
+                   else
+                    Message(asmr_e_invalid_register);
+                 end;
+     AS_SEPARATOR, AS_COMMA: ;
+    else
+     Begin
+      Message(asmr_e_invalid_opcode_and_operand);
+      Consume(actasmtoken);
+     end;
+  end; { end case }
+ end;
+
+
+
+  Procedure BuildConstant(maxvalue: longint);
+  {*********************************************************************}
+  { PROCEDURE BuildConstant                                             }
+  {  Description: This routine takes care of parsing a DB,DD,or DW      }
+  {  line and adding those to the assembler node. Expressions, range-   }
+  {  checking are fullly taken care of.                                 }
+  {   maxvalue: $ff -> indicates that this is a DB node.                }
+  {             $ffff -> indicates that this is a DW node.              }
+  {             $ffffffff -> indicates that this is a DD node.          }
+  {*********************************************************************}
+  { EXIT CONDITION:  On exit the routine should point to AS_SEPARATOR.  }
+  {*********************************************************************}
+  var
+   strlength: byte;
+   expr: string;
+   tempstr: string;
+   value : longint;
+  Begin
+      Repeat
+        Case actasmtoken of
+          AS_STRING: Begin
+                      if maxvalue = $ff then
+                         strlength := 1
+                      else
+                         Message(asmr_e_string_not_allowed_as_const);
+                      expr := actasmpattern;
+                      if length(expr) > 1 then
+                       Message(asmr_e_string_not_allowed_as_const);
+                      Consume(AS_STRING);
+                      Case actasmtoken of
+                       AS_COMMA: Consume(AS_COMMA);
+                       AS_SEPARATOR: ;
+                      else
+                       Message(asmr_e_invalid_string_expression);
+                      end; { end case }
+                      ConcatString(p,expr);
+                    end;
+          AS_INTNUM,AS_BINNUM,
+          AS_OCTALNUM,AS_HEXNUM:
+                    Begin
+                      value:=BuildExpression(false,nil);
+                      ConcatConstant(p,value,maxvalue);
+                    end;
+          AS_ID:
+                     Begin
+                      value:=BuildExpression(false,nil);
+                      if value > maxvalue then
+                      Begin
+                         Message(asmr_e_constant_out_of_bounds);
+                         { assuming a value of maxvalue }
+                         value := maxvalue;
+                      end;
+                      ConcatConstant(p,value,maxvalue);
+                  end;
+          { These terms can start an assembler expression }
+          AS_PLUS,AS_MINUS,AS_LPAREN,AS_NOT: Begin
+                                          value := BuildExpression(false,nil);
+                                          ConcatConstant(p,value,maxvalue);
+                                         end;
+          AS_COMMA:  BEGIN
+                       Consume(AS_COMMA);
+                     END;
+          AS_SEPARATOR: ;
+
+        else
+         Begin
+           Message(asmr_e_syntax_error);
+         end;
+    end; { end case }
+   Until actasmtoken = AS_SEPARATOR;
+  end;
+
+
+  Procedure BuildStringConstant(asciiz: boolean);
+  {*********************************************************************}
+  { PROCEDURE BuildStringConstant                                       }
+  {  Description: Takes care of a ASCII, or ASCIIZ directive.           }
+  {   asciiz: boolean -> if true then string will be null terminated.   }
+  {*********************************************************************}
+  { EXIT CONDITION:  On exit the routine should point to AS_SEPARATOR.  }
+  { On ENTRY: Token should point to AS_STRING                           }
+  {*********************************************************************}
+  var
+   expr: string;
+   errorflag : boolean;
+  Begin
+      errorflag := FALSE;
+      Repeat
+        Case actasmtoken of
+          AS_STRING: Begin
+                      expr:=actasmpattern;
+                      if asciiz then
+                       expr:=expr+#0;
+                      ConcatPasString(p,expr);
+                      Consume(AS_STRING);
+                    end;
+          AS_COMMA:  BEGIN
+                       Consume(AS_COMMA);
+                     END;
+          AS_SEPARATOR: ;
+        else
+         Begin
+          Consume(actasmtoken);
+          if not errorflag then
+           Message(asmr_e_invalid_string_expression);
+          errorflag := TRUE;
+         end;
+    end; { end case }
+   Until actasmtoken = AS_SEPARATOR;
+  end;
+
+
+
+
+  Procedure BuildOpCode;
+  {*********************************************************************}
+  { PROCEDURE BuildOpcode;                                              }
+  {  Description: Parses the intel opcode and operands, and writes it   }
+  {  in the TInstruction object.                                        }
+  {*********************************************************************}
+  { EXIT CONDITION:  On exit the routine should point to AS_SEPARATOR.  }
+  { On ENTRY: Token should point to AS_OPCODE                           }
+  {*********************************************************************}
+  var asmtok: tasmop;
+      op: tasmop;
+      expr: string;
+      segreg: tregister;
+  Begin
+    expr := '';
+    asmtok := A_NONE; { assmume no prefix          }
+    segreg := R_NO;   { assume no segment override }
+
+    { //  opcode                          // }
+    { allow for newline as in gas styled syntax }
+    { under DOS you get two AS_SEPARATOR !! }
+    while actasmtoken=AS_SEPARATOR do
+      Consume(AS_SEPARATOR);
+    if (actasmtoken <> AS_OPCODE) then
+    Begin
+      Message(asmr_e_invalid_or_missing_opcode);
+      { error recovery }
+      While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
+         Consume(actasmtoken);
+      exit;
+    end
+    else
+    Begin
+      op := findopcode(actasmpattern);
+      instr.opcode:=op;
+      Consume(AS_OPCODE);
+      { // Zero operand opcode ? // }
+      if actasmtoken = AS_SEPARATOR then
+        exit
+      else
+       operandnum := 1;
+    end;
+
+    While actasmtoken <> AS_SEPARATOR do
+    Begin
+       case actasmtoken of
+         { //  Operand delimiter // }
+         AS_COMMA: Begin
+                  if operandnum > MaxOperands then
+                    Message(asmr_e_too_many_operands)
+                  else
+                    Inc(operandnum);
+                  Consume(AS_COMMA);
+                end;
+         { // End of asm operands for this opcode // }
+         AS_SEPARATOR: ;
+       else
+         BuildOperand(instr);
+     end; { end case }
+    end; { end while }
+  end;
+
+
+
+
+  Function Assemble: Ptree;
+  {*********************************************************************}
+  { PROCEDURE Assemble;                                                 }
+  {  Description: Parses the att assembler syntax, parsing is done      }
+  {  according to GAs rules.                                            }
+  {*********************************************************************}
+  Var
+   hl: pasmlabel;
+   labelptr,nextlabel : pasmlabel;
+   commname : string;
+   store_p : paasmoutput;
+
+  Begin
+    Message(asmr_d_start_reading);
+    firsttoken := TRUE;
+    operandnum := 0;
+    { sets up all opcode and register tables in uppercase }
+    if not _asmsorted then
+    Begin
+      SetupTables;
+      _asmsorted := TRUE;
+    end;
+    p:=new(paasmoutput,init);
+    { save pointer code section }
+    store_p:=p;
+    { setup label linked list }
+    new(LocalLabelList,Init);
+    c:=current_scanner^.asmgetchar;
+    actasmtoken:=gettoken;
+    while actasmtoken<>AS_END do
+    Begin
+      case actasmtoken of
+        AS_LLABEL:
+          Begin
+            if CreateLocalLabel(actasmpattern,hl,true) then
+              ConcatLabel(p,hl);
+            Consume(AS_LLABEL);
+          end;
+        AS_LABEL: Begin
+                     { when looking for Pascal labels, these must }
+                     { be in uppercase.                           }
+                     if SearchLabel(upper(actasmpattern),hl,true) then
+                       ConcatLabel(p,hl)
+                     else
+                     Begin
+                       Message1(asmr_e_unknown_label_identifier,actasmpattern);
+                     end;
+                     Consume(AS_LABEL);
+                 end;
+        AS_DW:   Begin
+                   Consume(AS_DW);
+                   BuildConstant($ffff);
+                 end;
+        AS_DB:   Begin
+                  Consume(AS_DB);
+                  BuildConstant($ff);
+                end;
+        AS_DD:   Begin
+                 Consume(AS_DD);
+                 BuildConstant($ffffffff);
+                end;
+        AS_XDEF:
+                  Begin
+                   { normal units should not be able to declare }
+                   { direct label names like this... anyhow     }
+                   { procedural calls in asm blocks are         }
+                   { supposedely replaced automatically         }
+                   if (cs_compilesystem in aktmoduleswitches) then
+                   begin
+                     Consume(AS_XDEF);
+                      if actasmtoken <> AS_ID then
+                       Message(asmr_e_invalid_global_def)
+                      else
+                        ConcatPublic(p,actasmpattern);
+                      Consume(actasmtoken);
+                      if actasmtoken <> AS_SEPARATOR then
+                      Begin
+                        Message(asmr_e_syntax_error);
+                        while actasmtoken <> AS_SEPARATOR do
+                         Consume(actasmtoken);
+                      end;
+                   end
+                   else
+                   begin
+                     Message(asmr_w_xdef_not_supported);
+                     while actasmtoken <> AS_SEPARATOR do
+                       Consume(actasmtoken);
+                   end;
+                  end;
+        AS_ALIGN: Begin
+                    Message(asmr_w_align_not_supported);
+                    while actasmtoken <> AS_SEPARATOR do
+                     Consume(actasmtoken);
+                  end;
+        AS_OPCODE: Begin
+                   instr.init;
+                   BuildOpcode;
+                   instr.ops := operandnum;
+                   if instr.labeled then
+                     ConcatLabeledInstr(instr)
+                   else
+                     ConcatOpCode(instr);
+                   instr.done;
+                  end;
+        AS_SEPARATOR:Begin
+                     Consume(AS_SEPARATOR);
+                     { let us go back to the first operand }
+                     operandnum := 0;
+                    end;
+        AS_END: ; { end assembly block }
+    else
+      Begin
+         Message(asmr_e_syntax_error);
+         { error recovery }
+         Consume(actasmtoken);
+      end;
+    end; { end case }
+  end; { end while }
+  { Check LocalLabelList }
+  LocalLabelList^.CheckEmitted;
+  dispose(LocalLabelList,Done);
+
+  assemble := genasmnode(p);
+  Message(asmr_d_finish_reading);
+end;
+
+
+    procedure ra68kmot_exit;{$ifndef FPC}far;{$endif}
+      begin
+         if assigned(iasmops) then
+           dispose(iasmops);
+         exitproc:=old_exit;
+      end;
+
+
+Begin
+   old_exit:=exitproc;
+   exitproc:=@ra68kmot_exit;
+end.
+{
+  $Log$
+  Revision 1.1  2002-08-06 15:15:42  carl
+    + more m68k fixes
+
+  Revision 1.1.2.7  2001/08/09 11:41:08  pierre
+   + add more errors
+
+  Revision 1.1.2.6  2001/08/08 12:21:49  pierre
+   * generate correct labeled instruction for DBRA
+   * improoved checking of operands
+   + support for OPR_SYMBOL in generic instructions like MOVE
+   + support for labels in constants like movel #datalabel + const,d0
+
+  Revision 1.1.2.5  2001/08/07 15:55:33  pierre
+   + new code for NetBSD, behaves like FreeBSD for now
+
+  Revision 1.1.2.4  2001/08/01 10:58:50  pierre
+   * avoid warning about supposed external in asm label is already known
+
+  Revision 1.1.2.3  2001/07/24 23:41:32  pierre
+   * firstreg and lastreg renamed firstasmreg and lastasmreg to aviod confusions
+
+  Revision 1.1.2.2  2001/04/24 11:58:37  carl
+  * correction of DBRA problems
+
+  Revision 1.1.2.1  2001/03/04 02:19:54  carl
+  - renamefest!
+
+  Revision 1.1.2.1  2001/02/25 01:32:56  carl
+  - imported from mian directory
+
+  Revision 1.1.2.2  2001/02/23 11:20:40  pierre
+   * fix an update problem
+
+  Revision 1.1.2.1  2001/02/23 10:05:19  pierre
+   * first bunch of m68k cpu updates
+
+  Revision 1.1  2000/07/13 06:29:56  michael
+  + Initial import
+
+  Revision 1.13  2000/02/09 13:23:02  peter
+    * log truncated
+
+  Revision 1.12  2000/01/07 01:14:37  peter
+    * updated copyright to 2000
+
+  Revision 1.11  1999/11/10 00:06:08  pierre
+   * adapted to procinfo as pointer
+
+  Revision 1.10  1999/11/09 23:06:46  peter
+    * esi_offset -> selfpointer_offset to be newcg compatible
+    * hcogegen -> cgbase fixes for newcg
+
+  Revision 1.9  1999/09/16 23:05:56  florian
+    * m68k compiler is again compilable (only gas writer, no assembler reader)
+
+}
+

Vissa filer visades inte eftersom för många filer har ändrats