Browse Source

* another bunch of x86-64 fixes mainly calling convention and
assembler reader related

florian 21 years ago
parent
commit
85bed883ce

+ 8 - 1
compiler/compiler.pas

@@ -209,6 +209,9 @@ uses
 {$ifdef powerpc}
 {$ifdef powerpc}
   ,rappcgas
   ,rappcgas
 {$endif powerpc}
 {$endif powerpc}
+{$ifdef x86_64}
+  ,rax64att
+{$endif x86_64}
 {$ifdef arm}
 {$ifdef arm}
   ,raarmgas
   ,raarmgas
 {$endif arm}
 {$endif arm}
@@ -423,7 +426,11 @@ end;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.43  2003-12-04 10:46:19  mazen
+  Revision 1.44  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+
+  Revision 1.43  2003/12/04 10:46:19  mazen
   + added support for spac assembler reader
   + added support for spac assembler reader
 
 
   Revision 1.42  2003/11/17 23:23:47  florian
   Revision 1.42  2003/11/17 23:23:47  florian

+ 6 - 2
compiler/globals.pas

@@ -1779,7 +1779,7 @@ implementation
         {$IFDEF testvarsets}
         {$IFDEF testvarsets}
         initsetalloc:=0;
         initsetalloc:=0;
         {$ENDIF}
         {$ENDIF}
-        initasmmode:=asmmode_x8664_gas;
+        initasmmode:=asmmode_x86_64_gas;
 {$endif x86_64}
 {$endif x86_64}
         initinterfacetype:=it_interfacecom;
         initinterfacetype:=it_interfacecom;
         initdefproccall:=pocall_default;
         initdefproccall:=pocall_default;
@@ -1796,7 +1796,11 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.120  2004-01-12 16:36:53  peter
+  Revision 1.121  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+
+  Revision 1.120  2004/01/12 16:36:53  peter
     * removed asmmode_direct
     * removed asmmode_direct
 
 
   Revision 1.119  2004/01/02 16:50:24  jonas
   Revision 1.119  2004/01/02 16:50:24  jonas

+ 21 - 3
compiler/i386/cgcpu.pas

@@ -40,7 +40,8 @@ unit cgcpu;
 
 
     type
     type
       tcg386 = class(tcgx86)
       tcg386 = class(tcgx86)
-         class function reg_cgsize(const reg: tregister): tcgsize; override;
+        procedure init_register_allocators;override;
+        class function reg_cgsize(const reg: tregister): tcgsize; override;
      end;
      end;
 
 
       tcg64f386 = class(tcg64f32)
       tcg64f386 = class(tcg64f32)
@@ -57,7 +58,20 @@ unit cgcpu;
     uses
     uses
        globtype,globals,verbose,systems,cutils,
        globtype,globals,verbose,systems,cutils,
        symdef,symsym,defutil,paramgr,
        symdef,symsym,defutil,paramgr,
-       tgobj;
+       rgcpu,rgx86,tgobj;
+
+
+    procedure Tcg386.init_register_allocators;
+      begin
+        inherited init_register_allocators;
+        if cs_create_pic in aktmoduleswitches then
+          rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP,RS_EBX])
+        else
+          rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
+        rg[R_MMXREGISTER]:=trgcpu.create(R_MMXREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_sse_imreg,[]);
+        rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_sse_imreg,[]);
+        rgfpu:=Trgx86fpu.create;
+      end;
 
 
 
 
     class function tcg386.reg_cgsize(const reg: tregister): tcgsize;
     class function tcg386.reg_cgsize(const reg: tregister): tcgsize;
@@ -232,7 +246,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.43  2004-01-12 16:39:40  peter
+  Revision 1.44  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+
+  Revision 1.43  2004/01/12 16:39:40  peter
     * sparc updates, mostly float related
     * sparc updates, mostly float related
 
 
   Revision 1.42  2003/12/24 00:10:02  florian
   Revision 1.42  2003/12/24 00:10:02  florian

+ 6 - 2
compiler/i386/cpubase.inc

@@ -153,7 +153,7 @@
          This value can be deduced from the CALLED_USED_REGISTERS array in the
          This value can be deduced from the CALLED_USED_REGISTERS array in the
          GCC source.
          GCC source.
       }
       }
-      std_saved_registers = [RS_ESI,RS_EDI,RS_EBX];
+      saved_standard_registers : array[0..2] of tsuperregister = (RS_EBX,RS_ESI,RS_EDI);
       {# Required parameter alignment when calling a routine declared as
       {# Required parameter alignment when calling a routine declared as
          stdcall and cdecl. The alignment value should be the one defined
          stdcall and cdecl. The alignment value should be the one defined
          by GCC or the target ABI.
          by GCC or the target ABI.
@@ -165,7 +165,11 @@
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.10  2003-10-17 14:38:32  peter
+  Revision 1.11  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+
+  Revision 1.10  2003/10/17 14:38:32  peter
     * 64k registers supported
     * 64k registers supported
     * fixed some memory leaks
     * fixed some memory leaks
 
 

+ 10 - 948
compiler/i386/ra386att.pas

@@ -24,774 +24,20 @@ Unit ra386att;
 
 
 {$i fpcdefs.inc}
 {$i fpcdefs.inc}
 
 
-Interface
-
-  uses
-    cpubase,
-    raatt,rax86;
-
-  type
-    ti386attreader = class(tattreader)
-      ActOpsize : topsize;
-      function is_asmopcode(const s: string):boolean;override;
-      procedure handleopcode;override;
-      procedure BuildReference(oper : t386operand);
-      procedure BuildOperand(oper : t386operand);
-      procedure BuildOpCode(instr : t386instruction);
-      procedure handlepercent;override;
-    end;
-
-
-Implementation
+  interface
 
 
     uses
     uses
-      { helpers }
-      cutils,
-      { global }
-      globtype,globals,verbose,
-      systems,
-      { aasm }
-      cpuinfo,aasmbase,aasmtai,aasmcpu,
-      { symtable }
-      symconst,symbase,symtype,symsym,symtable,
-      { parser }
-      scanner,
-      procinfo,
-      itcpugas,
-      rabase,rautils,
-      cgbase,cgobj
-      ;
-
-    procedure ti386attreader.handlepercent;
-      var
-        len : longint;
-      begin
-        len:=1;
-        actasmpattern[len]:='%';
-        c:=current_scanner.asmgetchar;
-        { to be a register there must be a letter and not a number }
-        if c in ['0'..'9'] then
-         begin
-           actasmtoken:=AS_MOD;
-         end
-        else
-         begin
-           while c in ['a'..'z','A'..'Z','0'..'9'] do
-            Begin
-              inc(len);
-              actasmpattern[len]:=c;
-              c:=current_scanner.asmgetchar;
-            end;
-           actasmpattern[0]:=chr(len);
-           uppervar(actasmpattern);
-           if (actasmpattern = '%ST') and (c='(') then
-            Begin
-              actasmpattern:=actasmpattern+c;
-              c:=current_scanner.asmgetchar;
-              if c in ['0'..'9'] then
-               actasmpattern:=actasmpattern + c
-              else
-               Message(asmr_e_invalid_fpu_register);
-              c:=current_scanner.asmgetchar;
-              if c <> ')' then
-               Message(asmr_e_invalid_fpu_register)
-              else
-               Begin
-                 actasmpattern:=actasmpattern + c;
-                 c:=current_scanner.asmgetchar; { let us point to next character. }
-               end;
-            end;
-           if is_register(actasmpattern) then
-            exit;
-           Message(asmr_e_invalid_register);
-           actasmtoken:=raatt.AS_NONE;
-         end;
-      end;
-
-
-    Procedure ti386attreader.BuildReference(oper : t386operand);
-
-      procedure Consume_RParen;
-        begin
-          if actasmtoken <> AS_RPAREN then
-           Begin
-             Message(asmr_e_invalid_reference_syntax);
-             RecoverConsume(true);
-           end
-          else
-           begin
-             Consume(AS_RPAREN);
-             if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
-              Begin
-                Message(asmr_e_invalid_reference_syntax);
-                RecoverConsume(true);
-              end;
-           end;
-        end;
-
-
-      procedure Consume_Scale;
-        var
-          l : longint;
-        begin
-          { we have to process the scaling }
-          l:=BuildConstExpression(false,true);
-          if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
-           oper.opr.ref.scalefactor:=l
-          else
-           Begin
-             Message(asmr_e_wrong_scale_factor);
-             oper.opr.ref.scalefactor:=0;
-           end;
-        end;
+      rax86att;
 
 
-
-      begin
-        oper.InitRef;
-        Consume(AS_LPAREN);
-        Case actasmtoken of
-          AS_INTNUM,
-          AS_MINUS,
-          AS_PLUS: { absolute offset, such as fs:(0x046c) }
-            Begin
-              { offset(offset) is invalid }
-              If oper.opr.Ref.Offset <> 0 Then
-               Begin
-                 Message(asmr_e_invalid_reference_syntax);
-                 RecoverConsume(true);
-               End
-              Else
-               Begin
-                 oper.opr.Ref.Offset:=BuildConstExpression(false,true);
-                 Consume_RParen;
-               end;
-              exit;
-            End;
-          AS_REGISTER: { (reg ...  }
-            Begin
-              { Check if there is already a base (mostly ebp,esp) than this is
-                not allowed, because it will give crashing code }
-              if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
-                 ((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
-                message(asmr_e_cannot_index_relative_var);
-              oper.opr.ref.base:=actasmregister;
-              Consume(AS_REGISTER);
-              { can either be a register or a right parenthesis }
-              { (reg)        }
-              if actasmtoken=AS_RPAREN then
-               Begin
-                 Consume_RParen;
-                 exit;
-               end;
-              { (reg,reg ..  }
-              Consume(AS_COMMA);
-              if actasmtoken=AS_REGISTER then
-               Begin
-                 oper.opr.ref.index:=actasmregister;
-                 Consume(AS_REGISTER);
-                 { check for scaling ... }
-                 case actasmtoken of
-                   AS_RPAREN:
-                     Begin
-                       Consume_RParen;
-                       exit;
-                     end;
-                   AS_COMMA:
-                     Begin
-                       Consume(AS_COMMA);
-                       Consume_Scale;
-                       Consume_RParen;
-                     end;
-                 else
-                   Begin
-                     Message(asmr_e_invalid_reference_syntax);
-                     RecoverConsume(false);
-                   end;
-                 end; { end case }
-               end
-              else
-               Begin
-                 Message(asmr_e_invalid_reference_syntax);
-                 RecoverConsume(false);
-               end;
-            end; {end case }
-          AS_COMMA: { (, ...  can either be scaling, or index }
-            Begin
-              Consume(AS_COMMA);
-              { Index }
-              if (actasmtoken=AS_REGISTER) then
-               Begin
-                 oper.opr.ref.index:=actasmregister;
-                 Consume(AS_REGISTER);
-                 { check for scaling ... }
-                 case actasmtoken of
-                   AS_RPAREN:
-                     Begin
-                       Consume_RParen;
-                       exit;
-                     end;
-                   AS_COMMA:
-                     Begin
-                       Consume(AS_COMMA);
-                       Consume_Scale;
-                       Consume_RParen;
-                     end;
-                 else
-                   Begin
-                     Message(asmr_e_invalid_reference_syntax);
-                     RecoverConsume(false);
-                   end;
-                 end; {end case }
-               end
-              { Scaling }
-              else
-               Begin
-                 Consume_Scale;
-                 Consume_RParen;
-                 exit;
-               end;
-            end;
-        else
-          Begin
-            Message(asmr_e_invalid_reference_syntax);
-            RecoverConsume(false);
-          end;
-        end;
+    type
+      ti386attreader = class(tx86attreader)
       end;
       end;
 
 
 
 
-    Procedure ti386attreader.BuildOperand(oper : t386operand);
-      var
-        tempstr,
-        expr : string;
-        typesize,
-        l,k : longint;
-
-
-        procedure AddLabelOperand(hl:tasmlabel);
-          begin
-            if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
-               is_calljmp(actopcode) then
-             begin
-               oper.opr.typ:=OPR_SYMBOL;
-               oper.opr.symbol:=hl;
-             end
-            else
-             begin
-               oper.InitRef;
-               oper.opr.ref.symbol:=hl;
-             end;
-          end;
-
-
-        procedure MaybeRecordOffset;
-          var
-            hasdot  : boolean;
-            l,
-            toffset,
-            tsize   : longint;
-          begin
-            if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
-             exit;
-            l:=0;
-            hasdot:=(actasmtoken=AS_DOT);
-            if hasdot then
-             begin
-               if expr<>'' then
-                 begin
-                   BuildRecordOffsetSize(expr,toffset,tsize);
-                   inc(l,toffset);
-                   oper.SetSize(tsize,true);
-                 end;
-             end;
-            if actasmtoken in [AS_PLUS,AS_MINUS] then
-             inc(l,BuildConstExpression(true,false));
-            case oper.opr.typ of
-              OPR_LOCAL :
-                begin
-                  { don't allow direct access to fields of parameters, because that
-                    will generate buggy code. Allow it only for explicit typecasting }
-                  if hasdot and
-                     (not oper.hastype) and
-                     (tvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
-                     (current_procinfo.procdef.proccalloption<>pocall_register) then
-                    Message(asmr_e_cannot_access_field_directly_for_parameters);
-                  inc(oper.opr.localsymofs,l)
-                end;
-              OPR_CONSTANT :
-                inc(oper.opr.val,l);
-              OPR_REFERENCE :
-                inc(oper.opr.ref.offset,l);
-              else
-                internalerror(200309221);
-            end;
-          end;
-
-
-        function MaybeBuildReference:boolean;
-          { Try to create a reference, if not a reference is found then false
-            is returned }
-          begin
-            MaybeBuildReference:=true;
-            case actasmtoken of
-              AS_INTNUM,
-              AS_MINUS,
-              AS_PLUS:
-                Begin
-                  oper.opr.ref.offset:=BuildConstExpression(True,False);
-                  if actasmtoken<>AS_LPAREN then
-                    Message(asmr_e_invalid_reference_syntax)
-                  else
-                    BuildReference(oper);
-                end;
-              AS_LPAREN:
-                BuildReference(oper);
-              AS_ID: { only a variable is allowed ... }
-                Begin
-                  tempstr:=actasmpattern;
-                  Consume(AS_ID);
-                  { typecasting? }
-                  if (actasmtoken=AS_LPAREN) and
-                     SearchType(tempstr,typesize) then
-                   begin
-                     oper.hastype:=true;
-                     Consume(AS_LPAREN);
-                     BuildOperand(oper);
-                     Consume(AS_RPAREN);
-                     if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
-                       oper.SetSize(typesize,true);
-                   end
-                  else
-                   if not oper.SetupVar(tempstr,false) then
-                    Message1(sym_e_unknown_id,tempstr);
-                  { record.field ? }
-                  if actasmtoken=AS_DOT then
-                   begin
-                     BuildRecordOffsetSize(tempstr,l,k);
-                     inc(oper.opr.ref.offset,l);
-                   end;
-                  case actasmtoken of
-                    AS_END,
-                    AS_SEPARATOR,
-                    AS_COMMA: ;
-                    AS_LPAREN:
-                      BuildReference(oper);
-                  else
-                    Begin
-                      Message(asmr_e_invalid_reference_syntax);
-                      Consume(actasmtoken);
-                    end;
-                  end; {end case }
-                end;
-              else
-               MaybeBuildReference:=false;
-            end; { end case }
-          end;
-
-
-      const
-        regsize_2_size: array[S_B..S_L] of longint = (1,2,4);
-      var
-        tempreg : tregister;
-        hl      : tasmlabel;
-      Begin
-        expr:='';
-        case actasmtoken of
-          AS_LPAREN: { Memory reference or constant expression }
-            Begin
-              oper.InitRef;
-              BuildReference(oper);
-            end;
-
-          AS_DOLLAR: { Constant expression  }
-            Begin
-              Consume(AS_DOLLAR);
-              BuildConstantOperand(oper);
-            end;
-
-          AS_INTNUM,
-          AS_MINUS,
-          AS_PLUS:
-            Begin
-              { Constant memory offset }
-              { This must absolutely be followed by (  }
-              oper.InitRef;
-              oper.opr.ref.offset:=BuildConstExpression(True,False);
-              if actasmtoken<>AS_LPAREN then
-                Message(asmr_e_invalid_reference_syntax)
-              else
-                BuildReference(oper);
-            end;
+  implementation
 
 
-          AS_STAR: { Call from memory address }
-            Begin
-              Consume(AS_STAR);
-              if actasmtoken=AS_REGISTER then
-               begin
-                 oper.opr.typ:=OPR_REGISTER;
-                 oper.opr.reg:=actasmregister;
-                 oper.SetSize(regsize_2_size[reg2opsize(actasmregister)],true);
-                 Consume(AS_REGISTER);
-               end
-              else
-               begin
-                 oper.InitRef;
-                 if not MaybeBuildReference then
-                  Message(asmr_e_syn_operand);
-               end;
-              { this is only allowed for call's and jmp's }
-              if not is_calljmp(actopcode) then
-               Message(asmr_e_syn_operand);
-            end;
-
-          AS_ID: { A constant expression, or a Variable ref.  }
-            Begin
-              { Local Label ? }
-              if is_locallabel(actasmpattern) then
-               begin
-                 CreateLocalLabel(actasmpattern,hl,false);
-                 Consume(AS_ID);
-                 AddLabelOperand(hl);
-               end
-              else
-               { Check for label }
-               if SearchLabel(actasmpattern,hl,false) then
-                begin
-                  Consume(AS_ID);
-                  AddLabelOperand(hl);
-                end
-              else
-               { probably a variable or normal expression }
-               { or a procedure (such as in CALL ID)      }
-               Begin
-                 { is it a constant ? }
-                 if SearchIConstant(actasmpattern,l) then
-                  Begin
-                    if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
-                     Message(asmr_e_invalid_operand_type);
-                    BuildConstantOperand(oper);
-                  end
-                 else
-                  begin
-                    expr:=actasmpattern;
-                    Consume(AS_ID);
-                    { typecasting? }
-                    if (actasmtoken=AS_LPAREN) and
-                       SearchType(expr,typesize) then
-                     begin
-                       oper.hastype:=true;
-                       Consume(AS_LPAREN);
-                       BuildOperand(oper);
-                       Consume(AS_RPAREN);
-                       if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
-                         oper.SetSize(typesize,true);
-                     end
-                    else
-                     begin
-                       if oper.SetupVar(expr,false) then
-                        begin
-                        end
-                       else
-                        Begin
-                          { look for special symbols ... }
-                          if expr= '__HIGH' then
-                            begin
-                              consume(AS_LPAREN);
-                              if not oper.setupvar('high'+actasmpattern,false) then
-                                Message1(sym_e_unknown_id,'high'+actasmpattern);
-                              consume(AS_ID);
-                              consume(AS_RPAREN);
-                            end
-                          else
-                           if expr = '__RESULT' then
-                            oper.SetUpResult
-                          else
-                           if expr = '__SELF' then
-                            oper.SetupSelf
-                          else
-                           if expr = '__OLDEBP' then
-                            oper.SetupOldEBP
-                          else
-                            { check for direct symbolic names   }
-                            { only if compiling the system unit }
-                            if (cs_compilesystem in aktmoduleswitches) then
-                             begin
-                               if not oper.SetupDirectVar(expr) then
-                                Begin
-                                  { not found, finally ... add it anyways ... }
-                                  Message1(asmr_w_id_supposed_external,expr);
-                                  oper.InitRef;
-                                  oper.opr.ref.symbol:=objectlibrary.newasmsymbol(expr);
-                                end;
-                             end
-                          else
-                            Message1(sym_e_unknown_id,expr);
-                        end;
-                     end;
-                  end;
-                  if actasmtoken=AS_DOT then
-                    MaybeRecordOffset;
-                  { add a constant expression? }
-                  if (actasmtoken=AS_PLUS) then
-                   begin
-                     l:=BuildConstExpression(true,false);
-                     case oper.opr.typ of
-                       OPR_CONSTANT :
-                         inc(oper.opr.val,l);
-                       OPR_LOCAL :
-                         inc(oper.opr.localsymofs,l);
-                       OPR_REFERENCE :
-                         inc(oper.opr.ref.offset,l);
-                       else
-                         internalerror(200309202);
-                     end;
-                   end
-               end;
-              { Do we have a indexing reference, then parse it also }
-              if actasmtoken=AS_LPAREN then
-                BuildReference(oper);
-            end;
-
-          AS_REGISTER: { Register, a variable reference or a constant reference  }
-            Begin
-              { save the type of register used. }
-              tempreg:=actasmregister;
-              Consume(AS_REGISTER);
-              if actasmtoken = AS_COLON then
-               Begin
-                 Consume(AS_COLON);
-                 oper.InitRef;
-                 oper.opr.ref.segment:=tempreg;
-                 { This must absolutely be followed by a reference }
-                 if not MaybeBuildReference then
-                  Begin
-                    Message(asmr_e_invalid_seg_override);
-                    Consume(actasmtoken);
-                  end;
-               end
-              { Simple register  }
-              else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
-                Begin
-                  if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
-                    Message(asmr_e_invalid_operand_type);
-                  oper.opr.typ:=OPR_REGISTER;
-                  oper.opr.reg:=tempreg;
-                  oper.SetSize(tcgsize2size[cg.reg_cgsize(oper.opr.reg)],true);
-                end
-              else
-                Message(asmr_e_syn_operand);
-            end;
-          AS_END,
-          AS_SEPARATOR,
-          AS_COMMA: ;
-        else
-          Begin
-            Message(asmr_e_syn_operand);
-            Consume(actasmtoken);
-          end;
-        end; { end case }
-      end;
-
-
-    procedure ti386attreader.BuildOpCode(instr : t386instruction);
-      var
-        operandnum : longint;
-        PrefixOp,OverrideOp: tasmop;
-      Begin
-        PrefixOp:=A_None;
-        OverrideOp:=A_None;
-        { prefix seg opcode / prefix opcode }
-        repeat
-          if is_prefix(actopcode) then
-            begin
-              PrefixOp:=ActOpcode;
-              with instr do
-                begin
-                  opcode:=ActOpcode;
-                  condition:=ActCondition;
-                  opsize:=ActOpsize;
-                  ConcatInstruction(curlist);
-                end;
-              Consume(AS_OPCODE);
-            end
-          else
-            if is_override(actopcode) then
-              begin
-                OverrideOp:=ActOpcode;
-                with instr do
-                  begin
-                    opcode:=ActOpcode;
-                    condition:=ActCondition;
-                    opsize:=ActOpsize;
-                    ConcatInstruction(curlist);
-                  end;
-                Consume(AS_OPCODE);
-              end
-            else
-              break;
-          { allow for newline as in gas styled syntax }
-          while actasmtoken=AS_SEPARATOR do
-            Consume(AS_SEPARATOR);
-        until (actasmtoken<>AS_OPCODE);
-        { opcode }
-        if (actasmtoken<>AS_OPCODE) then
-         Begin
-           Message(asmr_e_invalid_or_missing_opcode);
-           RecoverConsume(true);
-           exit;
-         end;
-        { Fill the instr object with the current state }
-        with instr do
-          begin
-            Opcode:=ActOpcode;
-            condition:=ActCondition;
-            opsize:=ActOpsize;
-          end;
-
-        { Valid combination of prefix/override and instruction ?  }
-
-        if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
-           Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
-
-        if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
-          Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
-        { We are reading operands, so opcode will be an AS_ID }
-        operandnum:=1;
-        Consume(AS_OPCODE);
-        { Zero operand opcode ?  }
-        if actasmtoken in [AS_SEPARATOR,AS_END] then
-         begin
-           operandnum:=0;
-           exit;
-         end;
-        { Read the operands }
-        repeat
-          case actasmtoken of
-            AS_COMMA: { Operand delimiter }
-              Begin
-                if operandnum > Max_Operands then
-                  Message(asmr_e_too_many_operands)
-                else
-                  Inc(operandnum);
-                Consume(AS_COMMA);
-              end;
-            AS_SEPARATOR,
-            AS_END : { End of asm operands for this opcode  }
-              begin
-                break;
-              end;
-          else
-            BuildOperand(instr.Operands[operandnum] as t386operand);
-          end; { end case }
-        until false;
-        instr.Ops:=operandnum;
-      end;
-
-
-    function ti386attreader.is_asmopcode(const s: string):boolean;
-      const
-        { We need first to check the long prefixes, else we get probs
-          with things like movsbl }
-        att_sizesuffixstr : array[0..9] of string[2] = (
-          '','BW','BL','WL','B','W','L','S','Q','T'
-        );
-        att_sizesuffix : array[0..9] of topsize = (
-          S_NO,S_BW,S_BL,S_WL,S_B,S_W,S_L,S_FS,S_IQ,S_FX
-        );
-        att_sizefpusuffix : array[0..9] of topsize = (
-          S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_FL,S_FS,S_IQ,S_FX
-        );
-        att_sizefpuintsuffix : array[0..9] of topsize = (
-          S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
-        );
-      var
-        str2opentry: tstr2opentry;
-        cond : string[4];
-        cnd  : tasmcond;
-        len,
-        j,
-        sufidx : longint;
-      Begin
-        is_asmopcode:=FALSE;
-
-        actopcode:=A_None;
-        actcondition:=C_None;
-        actopsize:=S_NO;
-
-        { search for all possible suffixes }
-        for sufidx:=low(att_sizesuffixstr) to high(att_sizesuffixstr) do
-         begin
-           len:=length(s)-length(att_sizesuffixstr[sufidx]);
-           if copy(s,len+1,length(att_sizesuffixstr[sufidx]))=att_sizesuffixstr[sufidx] then
-            begin
-              { here we search the entire table... }
-              str2opentry:=nil;
-              if {(length(s)>0) and} (len>0) then
-                str2opentry:=tstr2opentry(iasmops.search(copy(s,1,len)));
-              if assigned(str2opentry) then
-                begin
-                  actopcode:=str2opentry.op;
-                  if gas_needsuffix[actopcode]=attsufFPU then
-                   actopsize:=att_sizefpusuffix[sufidx]
-                  else if gas_needsuffix[actopcode]=attsufFPUint then
-                   actopsize:=att_sizefpuintsuffix[sufidx]
-                  else
-                   actopsize:=att_sizesuffix[sufidx];
-                  actasmtoken:=AS_OPCODE;
-                  is_asmopcode:=TRUE;
-                  exit;
-                end;
-              { not found, check condition opcodes }
-              j:=0;
-              while (j<CondAsmOps) do
-               begin
-                 if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
-                  begin
-                    cond:=Copy(s,Length(CondAsmOpStr[j])+1,len-Length(CondAsmOpStr[j]));
-                    if cond<>'' then
-                     begin
-                       for cnd:=low(TasmCond) to high(TasmCond) do
-                        if Cond=Upper(cond2str[cnd]) then
-                         begin
-                           actopcode:=CondASmOp[j];
-                           if gas_needsuffix[actopcode]=attsufFPU then
-                            actopsize:=att_sizefpusuffix[sufidx]
-                           else if gas_needsuffix[actopcode]=attsufFPUint then
-                            actopsize:=att_sizefpuintsuffix[sufidx]
-                           else
-                            actopsize:=att_sizesuffix[sufidx];
-                           actcondition:=cnd;
-                           actasmtoken:=AS_OPCODE;
-                           is_asmopcode:=TRUE;
-                           exit;
-                         end;
-                     end;
-                  end;
-                 inc(j);
-               end;
-           end;
-         end;
-      end;
-
-
-    procedure ti386attreader.handleopcode;
-      var
-        instr : T386Instruction;
-      begin
-        instr:=T386Instruction.Create(T386Operand);
-        instr.OpOrder:=op_att;
-        BuildOpcode(instr);
-        instr.AddReferenceSizes;
-        instr.SetInstructionOpsize;
-        instr.CheckOperandSizes;
-        instr.ConcatInstruction(curlist);
-        instr.Free;
-      end;
-
-
-{*****************************************************************************
-                                     Initialize
-*****************************************************************************}
+    uses
+      rabase,systems;
 
 
 const
 const
   asmmode_i386_att_info : tasmmodeinfo =
   asmmode_i386_att_info : tasmmodeinfo =
@@ -806,191 +52,7 @@ initialization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.58  2003-11-12 16:05:39  florian
-    * assembler readers OOPed
-    + typed currency constants
-    + typed 128 bit float constants if the CPU supports it
-
-  Revision 1.57  2003/11/10 19:08:32  peter
-    * line numbering is now only done when #10, #10#13 is really parsed
-      instead of when it is the next character
-
-  Revision 1.56  2003/10/29 16:47:18  peter
-    * fix field offset in reference
-
-  Revision 1.55  2003/10/26 13:37:22  florian
-    * fixed web bug 2128
-
-  Revision 1.54  2003/10/24 17:39:03  peter
-    * more intel parser updates
-
-  Revision 1.53  2003/10/23 17:19:44  peter
-    * typecasting fixes
-    * reference building more delphi compatible
-
-  Revision 1.52  2003/10/20 19:29:35  peter
-    * fix check for register subscription of reference parameter
-
-  Revision 1.51  2003/10/16 21:29:24  peter
-    + __HIGH() to retrieve high value
-
-  Revision 1.50  2003/10/07 18:21:18  peter
-    * fix crash
-    * allow parameter subscription for register parameters
-
-  Revision 1.49  2003/10/01 20:34:49  peter
-    * procinfo unit contains tprocinfo
-    * cginfo renamed to cgbase
-    * moved cgmessage to verbose
-    * fixed ppc and sparc compiles
-
-  Revision 1.48  2003/09/23 20:37:53  peter
-    * fix global var+offset
-
-  Revision 1.47  2003/09/23 17:56:06  peter
-    * locals and paras are allocated in the code generation
-    * tvarsym.localloc contains the location of para/local when
-      generating code for the current procedure
-
-  Revision 1.46  2003/09/03 15:55:01  peter
-    * NEWRA branch merged
-
-  Revision 1.45.2.2  2003/08/31 15:46:26  peter
-    * more updates for tregister
-
-  Revision 1.45.2.1  2003/08/28 18:35:08  peter
-    * tregister changed to cardinal
-
-  Revision 1.45  2003/05/30 23:57:08  peter
-    * more sparc cleanup
-    * accumulator removed, splitted in function_return_reg (called) and
-      function_result_reg (caller)
-
-  Revision 1.44  2003/05/22 21:32:29  peter
-    * removed some unit dependencies
-
-  Revision 1.43  2003/04/30 15:45:35  florian
-    * merged more x86-64/i386 code
-
-  Revision 1.42  2003/04/25 12:04:31  florian
-    * merged agx64att and ag386att to x86/agx86att
-
-  Revision 1.41  2003/04/21 20:05:10  peter
-    * removed some ie checks
-
-  Revision 1.40  2003/03/18 18:15:53  peter
-    * changed reg2opsize to function
-
-  Revision 1.39  2003/02/20 15:52:58  pierre
-   * fix a range check error
-
-  Revision 1.38  2003/02/19 22:00:16  daniel
-    * Code generator converted to new register notation
-    - Horribily outdated todo.txt removed
-
-  Revision 1.37  2003/02/03 22:47:14  daniel
-    - Removed reg_2_opsize array
-
-  Revision 1.36  2003/01/08 18:43:57  daniel
-   * Tregister changed into a record
-
-  Revision 1.35  2002/12/14 15:02:03  carl
-    * maxoperands -> max_operands (for portability in rautils.pas)
-    * fix some range-check errors with loadconst
-    + add ncgadd unit to m68k
-    * some bugfix of a_param_reg with LOC_CREFERENCE
-
-  Revision 1.34  2002/12/01 22:08:34  carl
-    * some small cleanup (remove some specific operators which are not supported)
-
-  Revision 1.33  2002/11/30 23:16:39  carl
-    - removed unused message
-
-  Revision 1.32  2002/11/15 01:58:58  peter
-    * merged changes from 1.0.7 up to 04-11
-      - -V option for generating bug report tracing
-      - more tracing for option parsing
-      - errors for cdecl and high()
-      - win32 import stabs
-      - win32 records<=8 are returned in eax:edx (turned off by default)
-      - heaptrc update
-      - more info for temp management in .s file with EXTDEBUG
-
-  Revision 1.31  2002/09/03 16:26:28  daniel
-    * Make Tprocdef.defs protected
-
-  Revision 1.30  2002/08/13 18:01:52  carl
-    * rename swatoperands to swapoperands
-    + m68k first compilable version (still needs a lot of testing):
-        assembler generator, system information , inline
-        assembler reader.
-
-  Revision 1.29  2002/08/12 15:08:42  carl
-    + stab register indexes for powerpc (moved from gdb to cpubase)
-    + tprocessor enumeration moved to cpuinfo
-    + linker in target_info is now a class
-    * many many updates for m68k (will soon start to compile)
-    - removed some ifdef or correct them for correct cpu
-
-  Revision 1.28  2002/08/11 14:32:31  peter
-    * renamed current_library to objectlibrary
-
-  Revision 1.27  2002/08/11 13:24:17  peter
-    * saving of asmsymbols in ppu supported
-    * asmsymbollist global is removed and moved into a new class
-      tasmlibrarydata that will hold the info of a .a file which
-      corresponds with a single module. Added librarydata to tmodule
-      to keep the library info stored for the module. In the future the
-      objectfiles will also be stored to the tasmlibrarydata class
-    * all getlabel/newasmsymbol and friends are moved to the new class
-
-  Revision 1.26  2002/07/26 21:15:44  florian
-    * rewrote the system handling
-
-  Revision 1.25  2002/07/01 18:46:34  peter
-    * internal linker
-    * reorganized aasm layer
-
-  Revision 1.24  2002/05/18 13:34:25  peter
-    * readded missing revisions
-
-  Revision 1.23  2002/05/16 19:46:52  carl
-  + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
-  + try to fix temp allocation (still in ifdef)
-  + generic constructor calls
-  + start of tassembler / tmodulebase class cleanup
-
-  Revision 1.21  2002/04/15 19:12:09  carl
-  + target_info.size_of_pointer -> pointer_size
-  + some cleanup of unused types/variables
-  * move several constants from cpubase to their specific units
-    (where they are used)
-  + att_Reg2str -> gas_reg2str
-  + int_reg2str -> std_reg2str
-
-  Revision 1.20  2002/04/14 17:01:52  carl
-  + att_reg2str -> gas_reg2str
-
-  Revision 1.19  2002/04/04 19:06:13  peter
-    * removed unused units
-    * use tlocation.size in cg.a_*loc*() routines
-
-  Revision 1.18  2002/04/02 17:11:39  peter
-    * tlocation,treference update
-    * LOC_CONSTANT added for better constant handling
-    * secondadd splitted in multiple routines
-    * location_force_reg added for loading a location to a register
-      of a specified size
-    * secondassignment parses now first the right and then the left node
-      (this is compatible with Kylix). This saves a lot of push/pop especially
-      with string operations
-    * adapted some routines to use the new cg methods
-
-  Revision 1.17  2002/03/28 20:48:25  carl
-  - remove go32v1 support
-
-  Revision 1.16  2002/01/24 18:25:53  peter
-   * implicit result variable generation for assembler routines
-   * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
-
+  Revision 1.59  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
 }
 }

+ 18 - 14
compiler/i386/ra386int.pas

@@ -65,10 +65,10 @@ Unit Ra386int;
          procedure BuildConstSymbolExpression(needofs,isref:boolean;var value:longint;var asmsym:string);
          procedure BuildConstSymbolExpression(needofs,isref:boolean;var value:longint;var asmsym:string);
          function BuildConstExpression:longint;
          function BuildConstExpression:longint;
          function BuildRefConstExpression:longint;
          function BuildRefConstExpression:longint;
-         procedure BuildReference(oper : t386operand);
-         procedure BuildOperand(oper: t386operand);
-         procedure BuildConstantOperand(oper: t386operand);
-         procedure BuildOpCode(instr : t386instruction);
+         procedure BuildReference(oper : tx86operand);
+         procedure BuildOperand(oper: tx86operand);
+         procedure BuildConstantOperand(oper: tx86operand);
+         procedure BuildOpCode(instr : tx86instruction);
          procedure BuildConstant(maxvalue: longint);
          procedure BuildConstant(maxvalue: longint);
        end;
        end;
 
 
@@ -1028,7 +1028,7 @@ Unit Ra386int;
       end;
       end;
 
 
 
 
-    procedure ti386intreader.BuildReference(oper : t386operand);
+    procedure ti386intreader.BuildReference(oper : tx86operand);
       var
       var
         k,l,scale : longint;
         k,l,scale : longint;
         tempstr,hs : string;
         tempstr,hs : string;
@@ -1366,7 +1366,7 @@ Unit Ra386int;
       end;
       end;
 
 
 
 
-    Procedure ti386intreader.BuildConstantOperand(oper: t386operand);
+    Procedure ti386intreader.BuildConstantOperand(oper: tx86operand);
       var
       var
         l : longint;
         l : longint;
         tempstr : string;
         tempstr : string;
@@ -1393,7 +1393,7 @@ Unit Ra386int;
       end;
       end;
 
 
 
 
-    Procedure ti386intreader.BuildOperand(oper: t386operand);
+    Procedure ti386intreader.BuildOperand(oper: tx86operand);
 
 
         procedure AddLabelOperand(hl:tasmlabel);
         procedure AddLabelOperand(hl:tasmlabel);
         begin
         begin
@@ -1634,7 +1634,7 @@ Unit Ra386int;
       end;
       end;
 
 
 
 
-    Procedure ti386intreader.BuildOpCode(instr : t386instruction);
+    Procedure ti386intreader.BuildOpCode(instr : tx86instruction);
       var
       var
         PrefixOp,OverrideOp: tasmop;
         PrefixOp,OverrideOp: tasmop;
         size,
         size,
@@ -1751,7 +1751,7 @@ Unit Ra386int;
                    Consume(AS_PTR);
                    Consume(AS_PTR);
                    instr.Operands[operandnum].InitRef;
                    instr.Operands[operandnum].InitRef;
                  end;
                  end;
-                BuildOperand(instr.Operands[operandnum] as t386operand);
+                BuildOperand(instr.Operands[operandnum] as tx86operand);
                 { now set the size which was specified by the override }
                 { now set the size which was specified by the override }
                 instr.Operands[operandnum].setsize(size,true);
                 instr.Operands[operandnum].setsize(size,true);
               end;
               end;
@@ -1776,10 +1776,10 @@ Unit Ra386int;
                    Consume(AS_PTR);
                    Consume(AS_PTR);
                    instr.Operands[operandnum].InitRef;
                    instr.Operands[operandnum].InitRef;
                  end;
                  end;
-                BuildOperand(instr.Operands[operandnum] as t386operand);
+                BuildOperand(instr.Operands[operandnum] as tx86operand);
               end;
               end;
             else
             else
-              BuildOperand(instr.Operands[operandnum] as t386operand);
+              BuildOperand(instr.Operands[operandnum] as tx86operand);
           end; { end case }
           end; { end case }
         until false;
         until false;
         instr.Ops:=operandnum;
         instr.Ops:=operandnum;
@@ -1856,7 +1856,7 @@ Unit Ra386int;
   function ti386intreader.Assemble: tlinkedlist;
   function ti386intreader.Assemble: tlinkedlist;
     Var
     Var
       hl : tasmlabel;
       hl : tasmlabel;
-      instr : T386Instruction;
+      instr : Tx86Instruction;
     Begin
     Begin
       Message1(asmr_d_start_reading,'intel');
       Message1(asmr_d_start_reading,'intel');
       inexpression:=FALSE;
       inexpression:=FALSE;
@@ -1920,7 +1920,7 @@ Unit Ra386int;
 
 
           AS_OPCODE :
           AS_OPCODE :
             Begin
             Begin
-              instr:=T386Instruction.Create(T386Operand);
+              instr:=Tx86Instruction.Create(Tx86Operand);
               BuildOpcode(instr);
               BuildOpcode(instr);
               with instr do
               with instr do
                 begin
                 begin
@@ -1977,7 +1977,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.68  2003-11-29 20:13:25  florian
+  Revision 1.69  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+
+  Revision 1.68  2003/11/29 20:13:25  florian
     * fixed several pi_do_call problems
     * fixed several pi_do_call problems
 
 
   Revision 1.67  2003/11/29 15:53:06  florian
   Revision 1.67  2003/11/29 15:53:06  florian

+ 6 - 2
compiler/systems.pas

@@ -70,7 +70,7 @@ interface
             ,asmmode_ppc_motorola
             ,asmmode_ppc_motorola
             ,asmmode_arm_gas
             ,asmmode_arm_gas
             ,asmmode_sparc_gas
             ,asmmode_sparc_gas
-            ,asmmode_x8664_gas
+            ,asmmode_x86_64_gas
        );
        );
 
 
      (* IMPORTANT NOTE:
      (* IMPORTANT NOTE:
@@ -649,7 +649,11 @@ finalization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.78  2004-01-12 16:39:40  peter
+  Revision 1.79  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+
+  Revision 1.78  2004/01/12 16:39:40  peter
     * sparc updates, mostly float related
     * sparc updates, mostly float related
 
 
   Revision 1.77  2004/01/04 21:17:51  jonas
   Revision 1.77  2004/01/04 21:17:51  jonas

+ 24 - 52
compiler/x86/cgx86.pas

@@ -37,7 +37,6 @@ unit cgx86;
     type
     type
       tcgx86 = class(tcg)
       tcgx86 = class(tcg)
         rgfpu   : Trgx86fpu;
         rgfpu   : Trgx86fpu;
-        procedure init_register_allocators;override;
         procedure done_register_allocators;override;
         procedure done_register_allocators;override;
 
 
         function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
         function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
@@ -188,19 +187,6 @@ unit cgx86;
       end;
       end;
 
 
 
 
-    procedure Tcgx86.init_register_allocators;
-      begin
-        inherited init_register_allocators;
-        if cs_create_pic in aktmoduleswitches then
-          rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP,RS_EBX])
-        else
-          rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
-        rg[R_MMXREGISTER]:=trgcpu.create(R_MMXREGISTER,R_SUBNONE,[RS_MM0,RS_MM1,RS_MM2,RS_MM3,RS_MM4,RS_MM5,RS_MM6,RS_MM7],first_sse_imreg,[]);
-        rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,[RS_MM0,RS_MM1,RS_MM2,RS_MM3,RS_MM4,RS_MM5,RS_MM6,RS_MM7],first_sse_imreg,[]);
-        rgfpu:=Trgx86fpu.create;
-      end;
-
-
     procedure Tcgx86.done_register_allocators;
     procedure Tcgx86.done_register_allocators;
       begin
       begin
         rg[R_INTREGISTER].free;
         rg[R_INTREGISTER].free;
@@ -1806,63 +1792,45 @@ unit cgx86;
       var
       var
         href : treference;
         href : treference;
         size : longint;
         size : longint;
+        r : integer;
       begin
       begin
         { Get temp }
         { Get temp }
         size:=0;
         size:=0;
-        if RS_EBX in rg[R_INTREGISTER].used_in_proc then
-          inc(size,POINTER_SIZE);
-        if RS_ESI in rg[R_INTREGISTER].used_in_proc then
-          inc(size,POINTER_SIZE);
-        if RS_EDI in rg[R_INTREGISTER].used_in_proc then
-          inc(size,POINTER_SIZE);
+        for r:=low(saved_standard_registers) to high(saved_standard_registers) do
+          if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+            inc(size,POINTER_SIZE);
         if size>0 then
         if size>0 then
           begin
           begin
             tg.GetTemp(list,size,tt_noreuse,current_procinfo.save_regs_ref);
             tg.GetTemp(list,size,tt_noreuse,current_procinfo.save_regs_ref);
             { Copy registers to temp }
             { Copy registers to temp }
             href:=current_procinfo.save_regs_ref;
             href:=current_procinfo.save_regs_ref;
-            if RS_EBX in rg[R_INTREGISTER].used_in_proc then
-              begin
-                a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_EBX,href);
-                inc(href.offset,POINTER_SIZE);
-              end;
-            if RS_ESI in rg[R_INTREGISTER].used_in_proc then
-              begin
-                a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_ESI,href);
-                inc(href.offset,POINTER_SIZE);
-              end;
-            if RS_EDI in rg[R_INTREGISTER].used_in_proc then
+
+            for r:=low(saved_standard_registers) to high(saved_standard_registers) do
               begin
               begin
-                a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_EDI,href);
-                inc(href.offset,POINTER_SIZE);
+                if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+                  begin
+                    a_load_reg_ref(list,OS_ADDR,OS_ADDR,newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE),href);
+                    inc(href.offset,POINTER_SIZE);
+                  end;
+                include(rg[R_INTREGISTER].preserved_by_proc,saved_standard_registers[r]);
               end;
               end;
           end;
           end;
-        include(rg[R_INTREGISTER].preserved_by_proc,RS_EBX);
-        include(rg[R_INTREGISTER].preserved_by_proc,RS_ESI);
-        include(rg[R_INTREGISTER].preserved_by_proc,RS_EDI);
       end;
       end;
 
 
 
 
     procedure tcgx86.g_restore_standard_registers(list:Taasmoutput);
     procedure tcgx86.g_restore_standard_registers(list:Taasmoutput);
       var
       var
         href : treference;
         href : treference;
+        r : integer;
       begin
       begin
         { Copy registers from temp }
         { Copy registers from temp }
         href:=current_procinfo.save_regs_ref;
         href:=current_procinfo.save_regs_ref;
-        if RS_EBX in rg[R_INTREGISTER].used_in_proc then
-          begin
-            a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EBX);
-            inc(href.offset,POINTER_SIZE);
-          end;
-        if RS_ESI in rg[R_INTREGISTER].used_in_proc then
-          begin
-            a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_ESI);
-            inc(href.offset,POINTER_SIZE);
-          end;
-        if RS_EDI in rg[R_INTREGISTER].used_in_proc then
-          begin
-            a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EDI);
-            inc(href.offset,POINTER_SIZE);
-          end;
+        for r:=low(saved_standard_registers) to high(saved_standard_registers) do
+          if saved_standard_registers[r] in rg[R_INTREGISTER].used_in_proc then
+            begin
+              a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,newreg(R_INTREGISTER,saved_standard_registers[r],R_SUBWHOLE));
+              inc(href.offset,POINTER_SIZE);
+            end;
         tg.UnGetTemp(list,current_procinfo.save_regs_ref);
         tg.UnGetTemp(list,current_procinfo.save_regs_ref);
       end;
       end;
 
 
@@ -1927,7 +1895,11 @@ unit cgx86;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.101  2004-01-14 21:43:54  peter
+  Revision 1.102  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+
+  Revision 1.101  2004/01/14 21:43:54  peter
     * add release_openarrayvalue
     * add release_openarrayvalue
 
 
   Revision 1.100  2003/12/26 14:02:30  peter
   Revision 1.100  2003/12/26 14:02:30  peter

+ 21 - 17
compiler/x86/cpubase.pas

@@ -118,22 +118,22 @@ uses
       first_fpu_imreg     = $08;
       first_fpu_imreg     = $08;
 
 
       { MM Super registers }
       { MM Super registers }
-      RS_MM0        = $00;
-      RS_MM1        = $01;
-      RS_MM2        = $02;
-      RS_MM3        = $03;
-      RS_MM4        = $04;
-      RS_MM5        = $05;
-      RS_MM6        = $06;
-      RS_MM7        = $07;
-      RS_MM8        = $08;
-      RS_MM9        = $09;
-      RS_MM10       = $0a;
-      RS_MM11       = $0b;
-      RS_MM12       = $0c;
-      RS_MM13       = $0d;
-      RS_MM14       = $0e;
-      RS_MM15       = $0f;
+      RS_XMM0        = $00;
+      RS_XMM1        = $01;
+      RS_XMM2        = $02;
+      RS_XMM3        = $03;
+      RS_XMM4        = $04;
+      RS_XMM5        = $05;
+      RS_XMM6        = $06;
+      RS_XMM7        = $07;
+      RS_XMM8        = $08;
+      RS_XMM9        = $09;
+      RS_XMM10       = $0a;
+      RS_XMM11       = $0b;
+      RS_XMM12       = $0c;
+      RS_XMM13       = $0d;
+      RS_XMM14       = $0e;
+      RS_XMM15       = $0f;
 
 
       { Number of first imaginary register }
       { Number of first imaginary register }
 {$ifdef x86_64}
 {$ifdef x86_64}
@@ -535,7 +535,11 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.35  2004-01-12 16:37:59  peter
+  Revision 1.36  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+
+  Revision 1.35  2004/01/12 16:37:59  peter
     * moved spilling code from taicpu to rg
     * moved spilling code from taicpu to rg
 
 
   Revision 1.34  2003/12/26 13:19:16  florian
   Revision 1.34  2003/12/26 13:19:16  florian

+ 0 - 500
compiler/x86/radirect.pas

@@ -1,500 +0,0 @@
-{
-    $Id$
-    Copyright (c) 1998-2002 by Florian Klaempfl
-
-    Reads inline assembler and writes the lines direct to the output
-
-    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 radirect;
-
-{$i fpcdefs.inc}
-
-interface
-
-    uses
-      node;
-
-     function assemble : tnode;
-
-  implementation
-
-    uses
-       { common }
-       cutils,
-       { global }
-       globals,verbose,
-       systems,
-       { aasm }
-       aasmbase,aasmtai,aasmcpu,
-       { symtable }
-       symconst,symbase,symtype,symsym,symtable,defutil,paramgr,
-       { pass 1 }
-       nbas,
-       { parser }
-       scanner,
-       rax86,
-       { codegen }
-       cgbase,procinfo,
-       { constants }
-       itx86att,
-       cpubase
-       ;
-
-    function assemble : tnode;
-
-      var
-         uhs,
-         retstr,s,hs : string;
-         c : char;
-         ende : boolean;
-         srsym,sym : tsym;
-         srsymtable : tsymtable;
-         code : TAAsmoutput;
-         i,l : longint;
-
-       procedure writeasmline;
-         var
-           i : longint;
-         begin
-           i:=length(s);
-           while (i>0) and (s[i] in [' ',#9]) do
-            dec(i);
-           s[0]:=chr(i);
-           if s<>'' then
-            code.concat(Tai_direct.Create(strpnew(s)));
-           s:='';
-         end;
-
-     begin
-       ende:=false;
-       s:='';
-       if assigned(current_procinfo.procdef.funcretsym) and
-          is_fpu(current_procinfo.procdef.rettype.def) then
-         tvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_assigned;
-       c:=current_scanner.asmgetcharstart;
-       code:=TAAsmoutput.Create;
-       while not(ende) do
-         begin
-            { wrong placement
-            current_scanner.gettokenpos; }
-            case c of
-               'A'..'Z','a'..'z','_' : begin
-                    current_scanner.gettokenpos;
-                    i:=0;
-                    hs:='';
-                    while ((ord(c)>=ord('A')) and (ord(c)<=ord('Z')))
-                       or ((ord(c)>=ord('a')) and (ord(c)<=ord('z')))
-                       or ((ord(c)>=ord('0')) and (ord(c)<=ord('9')))
-                       or (c='_') do
-                      begin
-                         inc(i);
-                         hs[i]:=c;
-                         c:=current_scanner.asmgetchar;
-                      end;
-                    hs[0]:=chr(i);
-                    if upper(hs)='END' then
-                       ende:=true
-                    else
-                       begin
-                          if c=':' then
-                            begin
-                              searchsym(upper(hs),srsym,srsymtable);
-                              if srsym<>nil then
-                                if (srsym.typ = labelsym) then
-                                  Begin
-                                     hs:=tlabelsym(srsym).lab.name;
-                                     tlabelsym(srsym).lab.is_set:=true;
-                                  end
-                                else
-                                  Message(asmr_w_using_defined_as_local);
-                            end
-                          else if upper(hs)='FWAIT' then
-                           FwaitWarning
-                          else
-                          { access to local variables }
-                          if assigned(current_procinfo.procdef) then
-                            begin
-                               { is the last written character an special }
-                               { char ?                                   }
-                               if (s[length(s)]='%') and
-                                  (not paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption)) and
-                                  ((pos('AX',upper(hs))>0) or
-                                  (pos('AL',upper(hs))>0)) then
-                                 tvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_assigned;
-                               if (s[length(s)]<>'%') and
-                                 (s[length(s)]<>'$') and
-                                 (s[length(s)]<>'.') and
-                                 ((s[length(s)]<>'0') or (hs[1]<>'x')) then
-                                 begin
-                                    if assigned(current_procinfo.procdef.localst) and
-                                       (current_procinfo.procdef.localst.symtablelevel>=normal_function_level) then
-                                      sym:=tsym(current_procinfo.procdef.localst.search(upper(hs)))
-                                    else
-                                      sym:=nil;
-                                    if assigned(sym) then
-                                      begin
-                                         if (sym.typ = labelsym) then
-                                           Begin
-                                              hs:=tlabelsym(sym).lab.name;
-                                           end
-                                         else if sym.typ=varsym then
-                                           begin
-                                             {variables set are after a comma }
-                                             {like in movl %eax,I }
-                                             if pos(',',s) > 0 then
-                                               tvarsym(sym).varstate:=vs_used
-                                             else
-                                               if (pos('MOV',upper(s)) > 0) and (tvarsym(sym).varstate=vs_declared) then
-                                                 Message1(sym_n_uninitialized_local_variable,hs);
-                                             if (vo_is_external in tvarsym(sym).varoptions) then
-                                               hs:=tvarsym(sym).mangledname
-                                             else
-                                               hs:='%%'+tvarsym(sym).name;
-                                           end
-                                         else
-                                         { call to local function }
-                                         if (sym.typ=procsym) and ((pos('CALL',upper(s))>0) or
-                                            (pos('LEA',upper(s))>0)) then
-                                           begin
-                                              hs:=tprocsym(sym).first_procdef.mangledname;
-                                           end;
-                                      end
-                                    else
-                                      begin
-                                         if assigned(current_procinfo.procdef.parast) then
-                                           sym:=tsym(current_procinfo.procdef.parast.search(upper(hs)))
-                                         else
-                                           sym:=nil;
-                                         if assigned(sym) then
-                                           begin
-                                              if sym.typ=varsym then
-                                                begin
-                                                  hs:='%%'+tvarsym(sym).name;
-                                                  if pos(',',s) > 0 then
-                                                    tvarsym(sym).varstate:=vs_used;
-                                                end;
-                                           end
-                                    { I added that but it creates a problem in line.ppi
-                                    because there is a local label wbuffer and
-                                    a static variable WBUFFER ...
-                                    what would you decide, florian ?}
-                                    else
-
-                                      begin
-                                         uhs:=upper(hs);
-                                         if (uhs='__SELF') then
-                                           begin
-                                             if assigned(current_procinfo.procdef._class) then
-                                              uhs:='self'
-                                             else
-                                              begin
-                                                Message(asmr_e_cannot_use_SELF_outside_a_method);
-                                                uhs:='';
-                                              end;
-                                           end
-                                         else
-                                          if (uhs='__OLDEBP') then
-                                           begin
-                                             if current_procinfo.procdef.parast.symtablelevel>normal_function_level then
-                                              uhs:='parentframe'
-                                             else
-                                              begin
-                                                Message(asmr_e_cannot_use_OLDEBP_outside_nested_procedure);
-                                                uhs:='';
-                                              end;
-                                           end
-                                         else
-                                          if uhs='__RESULT' then
-                                           begin
-                                             if (not is_void(current_procinfo.procdef.rettype.def)) then
-                                              uhs:='result'
-                                             else
-                                              begin
-                                                Message(asmr_e_void_function);
-                                                uhs:='';
-                                              end;
-                                           end;
-
-                                         if uhs<>'' then
-                                           searchsym(uhs,sym,srsymtable)
-                                         else
-                                           sym:=nil;
-                                         if assigned(sym) then
-                                          begin
-                                            case sym.owner.symtabletype of
-                                              globalsymtable,
-                                              staticsymtable :
-                                                begin
-                                                  case sym.typ of
-                                                    varsym :
-                                                      begin
-                                                        Message2(asmr_h_direct_global_to_mangled,hs,tvarsym(sym).mangledname);
-                                                        hs:=tvarsym(sym).mangledname;
-                                                        inc(tvarsym(sym).refs);
-                                                      end;
-                                                    typedconstsym :
-                                                      begin
-                                                        Message2(asmr_h_direct_global_to_mangled,hs,ttypedconstsym(sym).mangledname);
-                                                        hs:=ttypedconstsym(sym).mangledname;
-                                                      end;
-                                                    procsym :
-                                                      begin
-                                                        { procs can be called or the address can be loaded }
-                                                        if ((pos('CALL',upper(s))>0) or (pos('LEA',upper(s))>0)) then
-                                                         begin
-                                                           if tprocsym(sym).procdef_count>1 then
-                                                             Message1(asmr_w_direct_global_is_overloaded_func,hs);
-                                                           Message2(asmr_h_direct_global_to_mangled,hs,tprocsym(sym).first_procdef.mangledname);
-                                                           hs:=tprocsym(sym).first_procdef.mangledname;
-                                                         end;
-                                                      end;
-                                                    else
-                                                      Message(asmr_e_wrong_sym_type);
-                                                  end;
-                                                end;
-                                              parasymtable,
-                                              localsymtable :
-                                                begin
-                                                  case sym.typ of
-                                                    varsym :
-                                                      begin
-                                                        hs:='%%'+tvarsym(sym).name;
-                                                        inc(tvarsym(sym).refs);
-                                                      end;
-                                                    typedconstsym :
-                                                      begin
-                                                        Message2(asmr_h_direct_global_to_mangled,hs,ttypedconstsym(sym).mangledname);
-                                                        hs:=ttypedconstsym(sym).mangledname;
-                                                      end;
-                                                    else
-                                                      Message(asmr_e_wrong_sym_type);
-                                                  end;
-                                                end;
-                                             end;
-                                           end
-                                         end;
-                                      end;
-                                 end;
-                            end;
-                          s:=s+hs;
-                       end;
-                end;
-              '{',';',#10,#13 :
-                begin
-                  writeasmline;
-                  c:=current_scanner.asmgetchar;
-                end;
-              #26 :
-                Message(scan_f_end_of_file);
-              else
-                begin
-                  current_scanner.gettokenpos;
-                  inc(byte(s[0]));
-                  s[length(s)]:=c;
-                  c:=current_scanner.asmgetchar;
-                end;
-            end;
-         end;
-       writeasmline;
-       assemble:=casmnode.create(code);
-     end;
-
-
-{*****************************************************************************
-                                     Initialize
-*****************************************************************************}
-
-const
-{$ifdef x86_64}
-  asmmode_x86_64_direct_info : tasmmodeinfo =
-          (
-            id    : asmmode_direct;
-            idtxt : 'DIRECT'
-          );
-{$else x86_64}
-  asmmode_i386_direct_info : tasmmodeinfo =
-          (
-            id    : asmmode_direct;
-            idtxt : 'DIRECT'
-          );
-{$endif x86_64}
-
-initialization
-{$ifdef x86_64}
-  RegisterAsmMode(asmmode_x86_64_direct_info);
-{$else x86_64}
-  RegisterAsmMode(asmmode_i386_direct_info);
-{$endif x86_64}
-end.
-{
-  $Log$
-  Revision 1.11  2003-11-10 19:08:32  peter
-    * line numbering is now only done when #10, #10#13 is really parsed
-      instead of when it is the next character
-
-  Revision 1.10  2003/10/01 20:34:51  peter
-    * procinfo unit contains tprocinfo
-    * cginfo renamed to cgbase
-    * moved cgmessage to verbose
-    * fixed ppc and sparc compiles
-
-  Revision 1.9  2003/09/23 17:56:06  peter
-    * locals and paras are allocated in the code generation
-    * tvarsym.localloc contains the location of para/local when
-      generating code for the current procedure
-
-  Revision 1.8  2003/09/03 15:55:02  peter
-    * NEWRA branch merged
-
-  Revision 1.7.2.1  2003/08/27 21:06:34  peter
-    * more updates
-
-  Revision 1.7  2003/06/13 21:19:33  peter
-    * current_procdef removed, use current_procinfo.procdef instead
-
-  Revision 1.6  2003/06/02 21:42:05  jonas
-    * function results can now also be regvars
-    - removed tprocinfo.return_offset, never use it again since it's invalid
-      if the result is a regvar
-
-  Revision 1.5  2003/05/22 21:33:31  peter
-    * removed some unit dependencies
-
-  Revision 1.4  2003/05/15 18:58:54  peter
-    * removed selfpointer_offset, vmtpointer_offset
-    * tvarsym.adjusted_address
-    * address in localsymtable is now in the real direction
-    * removed some obsolete globals
-
-  Revision 1.3  2003/05/13 19:15:28  peter
-    * removed radirect
-
-  Revision 1.2  2003/05/01 07:59:43  florian
-    * introduced defaultordconsttype to decribe the default size of ordinal constants
-      on 64 bit CPUs it's equal to cs64bitdef while on 32 bit CPUs it's equal to s32bitdef
-    + added defines CPU32 and CPU64 for 32 bit and 64 bit CPUs
-    * int64s/qwords are allowed as for loop counter on 64 bit CPUs
-
-  Revision 1.1  2003/04/30 15:45:35  florian
-    * merged more x86-64/i386 code
-
-  Revision 1.11  2003/04/27 11:21:36  peter
-    * aktprocdef renamed to current_procinfo.procdef
-    * procinfo renamed to current_procinfo
-    * procinfo will now be stored in current_module so it can be
-      cleaned up properly
-    * gen_main_procsym changed to create_main_proc and release_main_proc
-      to also generate a tprocinfo structure
-    * fixed unit implicit initfinal
-
-  Revision 1.10  2003/04/27 07:29:52  peter
-    * current_procinfo.procdef cleanup, current_procinfo.procdef is now always nil when parsing
-      a new procdef declaration
-    * aktprocsym removed
-    * lexlevel removed, use symtable.symtablelevel instead
-    * implicit init/final code uses the normal genentry/genexit
-    * funcret state checking updated for new funcret handling
-
-  Revision 1.9  2003/04/25 20:59:35  peter
-    * removed funcretn,funcretsym, function result is now in varsym
-      and aliases for result and function name are added using absolutesym
-    * vs_hidden parameter for funcret passed in parameter
-    * vs_hidden fixes
-    * writenode changed to printnode and released from extdebug
-    * -vp option added to generate a tree.log with the nodetree
-    * nicer printnode for statements, callnode
-
-  Revision 1.8  2003/04/25 12:04:31  florian
-    * merged agx64att and ag386att to x86/agx86att
-
-  Revision 1.7  2003/04/21 20:05:10  peter
-    * removed some ie checks
-
-  Revision 1.6  2003/01/08 18:43:57  daniel
-   * Tregister changed into a record
-
-  Revision 1.5  2002/11/25 17:43:27  peter
-    * splitted defbase in defutil,symutil,defcmp
-    * merged isconvertable and is_equal into compare_defs(_ext)
-    * made operator search faster by walking the list only once
-
-  Revision 1.4  2002/11/18 17:32:00  peter
-    * pass proccalloption to ret_in_xxx and push_xxx functions
-
-  Revision 1.3  2002/09/03 16:26:28  daniel
-    * Make Tprocdef.defs protected
-
-  Revision 1.2  2002/08/17 09:23:47  florian
-    * first part of procinfo rewrite
-
-  Revision 1.1  2002/08/10 14:47:50  carl
-    + moved target_cpu_string to cpuinfo
-    * renamed asmmode enum.
-    * assembler reader has now less ifdef's
-    * move from nppcmem.pas -> ncgmem.pas vec. node.
-
-  Revision 1.21  2002/07/20 11:58:05  florian
-    * types.pas renamed to defbase.pas because D6 contains a types
-      unit so this would conflicts if D6 programms are compiled
-    + Willamette/SSE2 instructions to assembler added
-
-  Revision 1.20  2002/07/11 14:41:34  florian
-    * start of the new generic parameter handling
-
-  Revision 1.19  2002/07/01 18:46:34  peter
-    * internal linker
-    * reorganized aasm layer
-
-  Revision 1.18  2002/05/18 13:34:26  peter
-    * readded missing revisions
-
-  Revision 1.17  2002/05/16 19:46:52  carl
-  + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
-  + try to fix temp allocation (still in ifdef)
-  + generic constructor calls
-  + start of tassembler / tmodulebase class cleanup
-
-  Revision 1.15  2002/05/12 16:53:18  peter
-    * moved entry and exitcode to ncgutil and cgobj
-    * foreach gets extra argument for passing local data to the
-      iterator function
-    * -CR checks also class typecasts at runtime by changing them
-      into as
-    * fixed compiler to cycle with the -CR option
-    * fixed stabs with elf writer, finally the global variables can
-      be watched
-    * removed a lot of routines from cga unit and replaced them by
-      calls to cgobj
-    * u32bit-s32bit updates for and,or,xor nodes. When one element is
-      u32bit then the other is typecasted also to u32bit without giving
-      a rangecheck warning/error.
-    * fixed pascal calling method with reversing also the high tree in
-      the parast, detected by tcalcst3 test
-
-  Revision 1.14  2002/04/15 19:12:09  carl
-  + target_info.size_of_pointer -> pointer_size
-  + some cleanup of unused types/variables
-  * move several constants from cpubase to their specific units
-    (where they are used)
-  + att_Reg2str -> gas_reg2str
-  + int_reg2str -> std_reg2str
-
-  Revision 1.13  2002/04/14 17:01:52  carl
-  + att_reg2str -> gas_reg2str
-
-}

+ 96 - 86
compiler/x86/rax86.pas

@@ -41,13 +41,13 @@ Function CheckOverride(overrideop,op:tasmop): Boolean;
 Procedure FWaitWarning;
 Procedure FWaitWarning;
 
 
 type
 type
-  T386Operand=class(TOperand)
+  Tx86Operand=class(TOperand)
     opsize  : topsize;
     opsize  : topsize;
     Procedure SetSize(_size:longint;force:boolean);override;
     Procedure SetSize(_size:longint;force:boolean);override;
     Procedure SetCorrectSize(opcode:tasmop);override;
     Procedure SetCorrectSize(opcode:tasmop);override;
   end;
   end;
 
 
-  T386Instruction=class(TInstruction)
+  Tx86Instruction=class(TInstruction)
     OpOrder : TOperandOrder;
     OpOrder : TOperandOrder;
     opsize  : topsize;
     opsize  : topsize;
     constructor Create(optype : tcoperand);override;
     constructor Create(optype : tcoperand);override;
@@ -193,10 +193,10 @@ begin
 end;
 end;
 
 
 {*****************************************************************************
 {*****************************************************************************
-                              T386Operand
+                              TX86Operand
 *****************************************************************************}
 *****************************************************************************}
 
 
-Procedure T386Operand.SetSize(_size:longint;force:boolean);
+Procedure Tx86Operand.SetSize(_size:longint;force:boolean);
 begin
 begin
   inherited SetSize(_size,force);
   inherited SetSize(_size,force);
   { OS_64 will be set to S_L and be fixed later
   { OS_64 will be set to S_L and be fixed later
@@ -205,7 +205,7 @@ begin
 end;
 end;
 
 
 
 
-Procedure T386Operand.SetCorrectSize(opcode:tasmop);
+Procedure Tx86Operand.SetCorrectSize(opcode:tasmop);
 begin
 begin
   if gas_needsuffix[opcode]=attsufFPU then
   if gas_needsuffix[opcode]=attsufFPU then
     begin
     begin
@@ -229,14 +229,14 @@ end;
                               T386Instruction
                               T386Instruction
 *****************************************************************************}
 *****************************************************************************}
 
 
-constructor T386Instruction.Create(optype : tcoperand);
+constructor Tx86Instruction.Create(optype : tcoperand);
 begin
 begin
   inherited Create(optype);
   inherited Create(optype);
   Opsize:=S_NO;
   Opsize:=S_NO;
 end;
 end;
 
 
 
 
-procedure T386Instruction.SwapOperands;
+procedure Tx86Instruction.SwapOperands;
 begin
 begin
   Inherited SwapOperands;
   Inherited SwapOperands;
   { mark the correct order }
   { mark the correct order }
@@ -247,7 +247,7 @@ begin
 end;
 end;
 
 
 
 
-procedure T386Instruction.AddReferenceSizes;
+procedure Tx86Instruction.AddReferenceSizes;
 { this will add the sizes for references like [esi] which do not
 { this will add the sizes for references like [esi] which do not
   have the size set yet, it will take only the size if the other
   have the size set yet, it will take only the size if the other
   operand is a register }
   operand is a register }
@@ -256,69 +256,73 @@ var
   s : tasmsymbol;
   s : tasmsymbol;
   so : longint;
   so : longint;
 begin
 begin
-  for i:=1to ops do
-   begin
-   operands[i].SetCorrectSize(opcode);
-   if t386operand(operands[i]).opsize=S_NO then
+  for i:=1 to ops do
     begin
     begin
-      case operands[i].Opr.Typ of
-        OPR_LOCAL,
-        OPR_REFERENCE :
-          begin
-            if i=2 then
-             operand2:=1
-            else
-             operand2:=2;
-            if operand2<ops then
-             begin
-               { Only allow register as operand to take the size from }
-               if operands[operand2].opr.typ=OPR_REGISTER then
+      operands[i].SetCorrectSize(opcode);
+      if tx86operand(operands[i]).opsize=S_NO then
+        begin
+          case operands[i].Opr.Typ of
+            OPR_LOCAL,
+            OPR_REFERENCE :
+              begin
+                if i=2 then
+                 operand2:=1
+                else
+                 operand2:=2;
+                if operand2<ops then
                  begin
                  begin
-                   if ((opcode<>A_MOVD) and
-                       (opcode<>A_CVTSI2SS)) then
-                     t386operand(operands[i]).opsize:=t386operand(operands[operand2]).opsize;
+                   { Only allow register as operand to take the size from }
+                   if operands[operand2].opr.typ=OPR_REGISTER then
+                     begin
+                       if ((opcode<>A_MOVD) and
+                           (opcode<>A_CVTSI2SS)) then
+                         tx86operand(operands[i]).opsize:=tx86operand(operands[operand2]).opsize;
+                     end
+                   else
+                    begin
+                      { if no register then take the opsize (which is available with ATT),
+                        if not availble then give an error }
+                      if opsize<>S_NO then
+                        tx86operand(operands[i]).opsize:=opsize
+                      else
+                       begin
+                         Message(asmr_e_unable_to_determine_reference_size);
+                         { recovery }
+                         tx86operand(operands[i]).opsize:=S_L;
+                       end;
+                    end;
                  end
                  end
-               else
-                begin
-                  { if no register then take the opsize (which is available with ATT),
-                    if not availble then give an error }
-                  if opsize<>S_NO then
-                    t386operand(operands[i]).opsize:=opsize
-                  else
-                   begin
-                     Message(asmr_e_unable_to_determine_reference_size);
-                     { recovery }
-                     t386operand(operands[i]).opsize:=S_L;
-                   end;
-                end;
-             end
-            else
-             begin
-               if opsize<>S_NO then
-                 t386operand(operands[i]).opsize:=opsize
-             end;
-          end;
-        OPR_SYMBOL :
-          begin
-            { Fix lea which need a reference }
-            if opcode=A_LEA then
-             begin
-               s:=operands[i].opr.symbol;
-               so:=operands[i].opr.symofs;
-               operands[i].opr.typ:=OPR_REFERENCE;
-               Fillchar(operands[i].opr.ref,sizeof(treference),0);
-               operands[i].opr.ref.symbol:=s;
-               operands[i].opr.ref.offset:=so;
-             end;
-            t386operand(operands[i]).opsize:=S_L;
+                else
+                 begin
+                   if opsize<>S_NO then
+                     tx86operand(operands[i]).opsize:=opsize
+                 end;
+              end;
+            OPR_SYMBOL :
+              begin
+                { Fix lea which need a reference }
+                if opcode=A_LEA then
+                 begin
+                   s:=operands[i].opr.symbol;
+                   so:=operands[i].opr.symofs;
+                   operands[i].opr.typ:=OPR_REFERENCE;
+                   Fillchar(operands[i].opr.ref,sizeof(treference),0);
+                   operands[i].opr.ref.symbol:=s;
+                   operands[i].opr.ref.offset:=so;
+                 end;
+{$ifdef x86_64}
+                tx86operand(operands[i]).opsize:=S_Q;
+{$else x86_64}
+                tx86operand(operands[i]).opsize:=S_L;
+{$endif x86_64}
+              end;
           end;
           end;
-      end;
+        end;
     end;
     end;
-   end;
 end;
 end;
 
 
 
 
-procedure T386Instruction.SetInstructionOpsize;
+procedure Tx86Instruction.SetInstructionOpsize;
 begin
 begin
   if opsize<>S_NO then
   if opsize<>S_NO then
    exit;
    exit;
@@ -335,21 +339,21 @@ begin
            is_segment_reg(operands[1].opr.reg) then
            is_segment_reg(operands[1].opr.reg) then
           opsize:=S_L
           opsize:=S_L
         else
         else
-          opsize:=t386operand(operands[1]).opsize;
+          opsize:=tx86operand(operands[1]).opsize;
       end;
       end;
     2 :
     2 :
       begin
       begin
         case opcode of
         case opcode of
           A_MOVZX,A_MOVSX :
           A_MOVZX,A_MOVSX :
             begin
             begin
-              case t386operand(operands[1]).opsize of
+              case tx86operand(operands[1]).opsize of
                 S_W :
                 S_W :
-                  case t386operand(operands[2]).opsize of
+                  case tx86operand(operands[2]).opsize of
                     S_L :
                     S_L :
                       opsize:=S_WL;
                       opsize:=S_WL;
                   end;
                   end;
                 S_B :
                 S_B :
-                  case t386operand(operands[2]).opsize of
+                  case tx86operand(operands[2]).opsize of
                     S_W :
                     S_W :
                       opsize:=S_BW;
                       opsize:=S_BW;
                     S_L :
                     S_L :
@@ -361,18 +365,18 @@ begin
                      32 bit register or memory, so no opsize is correct here PM }
                      32 bit register or memory, so no opsize is correct here PM }
             exit;
             exit;
           A_OUT :
           A_OUT :
-            opsize:=t386operand(operands[1]).opsize;
+            opsize:=tx86operand(operands[1]).opsize;
           else
           else
-            opsize:=t386operand(operands[2]).opsize;
+            opsize:=tx86operand(operands[2]).opsize;
         end;
         end;
       end;
       end;
     3 :
     3 :
-      opsize:=t386operand(operands[3]).opsize;
+      opsize:=tx86operand(operands[3]).opsize;
   end;
   end;
 end;
 end;
 
 
 
 
-procedure T386Instruction.CheckOperandSizes;
+procedure Tx86Instruction.CheckOperandSizes;
 var
 var
   sizeerr : boolean;
   sizeerr : boolean;
   i : longint;
   i : longint;
@@ -403,11 +407,11 @@ begin
       begin
       begin
         case opsize of
         case opsize of
           S_BW :
           S_BW :
-            sizeerr:=(t386operand(operands[1]).opsize<>S_B) or (t386operand(operands[2]).opsize<>S_W);
+            sizeerr:=(tx86operand(operands[1]).opsize<>S_B) or (tx86operand(operands[2]).opsize<>S_W);
           S_BL :
           S_BL :
-            sizeerr:=(t386operand(operands[1]).opsize<>S_B) or (t386operand(operands[2]).opsize<>S_L);
+            sizeerr:=(tx86operand(operands[1]).opsize<>S_B) or (tx86operand(operands[2]).opsize<>S_L);
           S_WL :
           S_WL :
-            sizeerr:=(t386operand(operands[1]).opsize<>S_W) or (t386operand(operands[2]).opsize<>S_L);
+            sizeerr:=(tx86operand(operands[1]).opsize<>S_W) or (tx86operand(operands[2]).opsize<>S_L);
         end;
         end;
       end;
       end;
    end
    end
@@ -416,8 +420,8 @@ begin
      for i:=1 to ops do
      for i:=1 to ops do
       begin
       begin
         if (operands[i].opr.typ<>OPR_CONSTANT) and
         if (operands[i].opr.typ<>OPR_CONSTANT) and
-           (t386operand(operands[i]).opsize in [S_B,S_W,S_L]) and
-           (t386operand(operands[i]).opsize<>opsize) then
+           (tx86operand(operands[i]).opsize in [S_B,S_W,S_L]) and
+           (tx86operand(operands[i]).opsize<>opsize) then
          sizeerr:=true;
          sizeerr:=true;
       end;
       end;
    end;
    end;
@@ -436,7 +440,7 @@ end;
 { This check must be done with the operand in ATT order
 { This check must be done with the operand in ATT order
   i.e.after swapping in the intel reader
   i.e.after swapping in the intel reader
   but before swapping in the NASM and TASM writers PM }
   but before swapping in the NASM and TASM writers PM }
-procedure T386Instruction.CheckNonCommutativeOpcodes;
+procedure Tx86Instruction.CheckNonCommutativeOpcodes;
 begin
 begin
   if (OpOrder=op_intel) then
   if (OpOrder=op_intel) then
     SwapOperands;
     SwapOperands;
@@ -487,7 +491,7 @@ end;
                               opcode Adding
                               opcode Adding
 *****************************************************************************}
 *****************************************************************************}
 
 
-function T386Instruction.ConcatInstruction(p : taasmoutput) : tai;
+function Tx86Instruction.ConcatInstruction(p : taasmoutput) : tai;
 var
 var
   siz  : topsize;
   siz  : topsize;
   i,asize : longint;
   i,asize : longint;
@@ -502,21 +506,21 @@ begin
   else
   else
    begin
    begin
      if (Ops=2) and (operands[1].opr.typ=OPR_REGISTER) then
      if (Ops=2) and (operands[1].opr.typ=OPR_REGISTER) then
-      siz:=t386operand(operands[1]).opsize
+      siz:=tx86operand(operands[1]).opsize
      else
      else
-      siz:=t386operand(operands[Ops]).opsize;
+      siz:=tx86operand(operands[Ops]).opsize;
      { MOVD should be of size S_LQ or S_QL, but these do not exist PM }
      { MOVD should be of size S_LQ or S_QL, but these do not exist PM }
      if (ops=2) and
      if (ops=2) and
-        (t386operand(operands[1]).opsize<>S_NO) and
-        (t386operand(operands[2]).opsize<>S_NO) and
-        (t386operand(operands[1]).opsize<>t386operand(operands[2]).opsize) then
+        (tx86operand(operands[1]).opsize<>S_NO) and
+        (tx86operand(operands[2]).opsize<>S_NO) and
+        (tx86operand(operands[1]).opsize<>tx86operand(operands[2]).opsize) then
        siz:=S_NO;
        siz:=S_NO;
    end;
    end;
 
 
    if ((opcode=A_MOVD)or
    if ((opcode=A_MOVD)or
        (opcode=A_CVTSI2SS)) and
        (opcode=A_CVTSI2SS)) and
-      ((t386operand(operands[1]).opsize=S_NO) or
-       (t386operand(operands[2]).opsize=S_NO)) then
+      ((tx86operand(operands[1]).opsize=S_NO) or
+       (tx86operand(operands[2]).opsize=S_NO)) then
      siz:=S_NO;
      siz:=S_NO;
    { NASM does not support FADD without args
    { NASM does not support FADD without args
      as alias of FADDP
      as alias of FADDP
@@ -721,7 +725,9 @@ begin
    begin
    begin
      { Check the instruction if it's valid }
      { Check the instruction if it's valid }
 {$ifndef NOAG386BIN}
 {$ifndef NOAG386BIN}
+{$ifndef x86_64}
      ai.CheckIfValid;
      ai.CheckIfValid;
+{$endif x86_64}
 {$endif NOAG386BIN}
 {$endif NOAG386BIN}
      p.concat(ai);
      p.concat(ai);
    end
    end
@@ -733,7 +739,11 @@ end;
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.15  2003-11-17 23:23:47  florian
+  Revision 1.16  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+
+  Revision 1.15  2003/11/17 23:23:47  florian
     + first part of arm assembler reader
     + first part of arm assembler reader
 
 
   Revision 1.14  2003/11/12 16:05:40  florian
   Revision 1.14  2003/11/12 16:05:40  florian

+ 986 - 0
compiler/x86/rax86att.pas

@@ -0,0 +1,986 @@
+{
+    $Id$
+    Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+    Does the parsing for the x86 GNU AS styled 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 rax86att;
+
+{$i fpcdefs.inc}
+
+Interface
+
+  uses
+    cpubase,
+    raatt,rax86;
+
+  type
+    tx86attreader = class(tattreader)
+      ActOpsize : topsize;
+      function is_asmopcode(const s: string):boolean;override;
+      procedure handleopcode;override;
+      procedure BuildReference(oper : tx86operand);
+      procedure BuildOperand(oper : tx86operand);
+      procedure BuildOpCode(instr : tx86instruction);
+      procedure handlepercent;override;
+    end;
+
+
+Implementation
+
+    uses
+      { helpers }
+      cutils,
+      { global }
+      globtype,globals,verbose,
+      systems,
+      { aasm }
+      cpuinfo,aasmbase,aasmtai,aasmcpu,
+      { symtable }
+      symconst,symbase,symtype,symsym,symtable,
+      { parser }
+      scanner,
+      procinfo,
+      itcpugas,
+      rabase,rautils,
+      cgbase,cgobj
+      ;
+
+    procedure tx86attreader.handlepercent;
+      var
+        len : longint;
+      begin
+        len:=1;
+        actasmpattern[len]:='%';
+        c:=current_scanner.asmgetchar;
+        { to be a register there must be a letter and not a number }
+        if c in ['0'..'9'] then
+         begin
+           actasmtoken:=AS_MOD;
+         end
+        else
+         begin
+           while c in ['a'..'z','A'..'Z','0'..'9'] do
+            Begin
+              inc(len);
+              actasmpattern[len]:=c;
+              c:=current_scanner.asmgetchar;
+            end;
+           actasmpattern[0]:=chr(len);
+           uppervar(actasmpattern);
+           if (actasmpattern = '%ST') and (c='(') then
+            Begin
+              actasmpattern:=actasmpattern+c;
+              c:=current_scanner.asmgetchar;
+              if c in ['0'..'9'] then
+               actasmpattern:=actasmpattern + c
+              else
+               Message(asmr_e_invalid_fpu_register);
+              c:=current_scanner.asmgetchar;
+              if c <> ')' then
+               Message(asmr_e_invalid_fpu_register)
+              else
+               Begin
+                 actasmpattern:=actasmpattern + c;
+                 c:=current_scanner.asmgetchar; { let us point to next character. }
+               end;
+            end;
+           if is_register(actasmpattern) then
+            exit;
+           Message(asmr_e_invalid_register);
+           actasmtoken:=raatt.AS_NONE;
+         end;
+      end;
+
+
+    Procedure tx86attreader.BuildReference(oper : tx86operand);
+
+      procedure Consume_RParen;
+        begin
+          if actasmtoken <> AS_RPAREN then
+           Begin
+             Message(asmr_e_invalid_reference_syntax);
+             RecoverConsume(true);
+           end
+          else
+           begin
+             Consume(AS_RPAREN);
+             if not (actasmtoken in [AS_COMMA,AS_SEPARATOR,AS_END]) then
+              Begin
+                Message(asmr_e_invalid_reference_syntax);
+                RecoverConsume(true);
+              end;
+           end;
+        end;
+
+
+      procedure Consume_Scale;
+        var
+          l : longint;
+        begin
+          { we have to process the scaling }
+          l:=BuildConstExpression(false,true);
+          if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) then
+           oper.opr.ref.scalefactor:=l
+          else
+           Begin
+             Message(asmr_e_wrong_scale_factor);
+             oper.opr.ref.scalefactor:=0;
+           end;
+        end;
+
+
+      begin
+        oper.InitRef;
+        Consume(AS_LPAREN);
+        Case actasmtoken of
+          AS_INTNUM,
+          AS_MINUS,
+          AS_PLUS: { absolute offset, such as fs:(0x046c) }
+            Begin
+              { offset(offset) is invalid }
+              If oper.opr.Ref.Offset <> 0 Then
+               Begin
+                 Message(asmr_e_invalid_reference_syntax);
+                 RecoverConsume(true);
+               End
+              Else
+               Begin
+                 oper.opr.Ref.Offset:=BuildConstExpression(false,true);
+                 Consume_RParen;
+               end;
+              exit;
+            End;
+          AS_REGISTER: { (reg ...  }
+            Begin
+              { Check if there is already a base (mostly ebp,esp) than this is
+                not allowed, because it will give crashing code }
+              if ((oper.opr.typ=OPR_REFERENCE) and (oper.opr.ref.base<>NR_NO)) or
+                 ((oper.opr.typ=OPR_LOCAL) and (oper.opr.localsym.localloc.loc<>LOC_REGISTER)) then
+                message(asmr_e_cannot_index_relative_var);
+              oper.opr.ref.base:=actasmregister;
+              Consume(AS_REGISTER);
+              { can either be a register or a right parenthesis }
+              { (reg)        }
+              if actasmtoken=AS_RPAREN then
+               Begin
+                 Consume_RParen;
+                 exit;
+               end;
+              { (reg,reg ..  }
+              Consume(AS_COMMA);
+              if actasmtoken=AS_REGISTER then
+               Begin
+                 oper.opr.ref.index:=actasmregister;
+                 Consume(AS_REGISTER);
+                 { check for scaling ... }
+                 case actasmtoken of
+                   AS_RPAREN:
+                     Begin
+                       Consume_RParen;
+                       exit;
+                     end;
+                   AS_COMMA:
+                     Begin
+                       Consume(AS_COMMA);
+                       Consume_Scale;
+                       Consume_RParen;
+                     end;
+                 else
+                   Begin
+                     Message(asmr_e_invalid_reference_syntax);
+                     RecoverConsume(false);
+                   end;
+                 end; { end case }
+               end
+              else
+               Begin
+                 Message(asmr_e_invalid_reference_syntax);
+                 RecoverConsume(false);
+               end;
+            end; {end case }
+          AS_COMMA: { (, ...  can either be scaling, or index }
+            Begin
+              Consume(AS_COMMA);
+              { Index }
+              if (actasmtoken=AS_REGISTER) then
+               Begin
+                 oper.opr.ref.index:=actasmregister;
+                 Consume(AS_REGISTER);
+                 { check for scaling ... }
+                 case actasmtoken of
+                   AS_RPAREN:
+                     Begin
+                       Consume_RParen;
+                       exit;
+                     end;
+                   AS_COMMA:
+                     Begin
+                       Consume(AS_COMMA);
+                       Consume_Scale;
+                       Consume_RParen;
+                     end;
+                 else
+                   Begin
+                     Message(asmr_e_invalid_reference_syntax);
+                     RecoverConsume(false);
+                   end;
+                 end; {end case }
+               end
+              { Scaling }
+              else
+               Begin
+                 Consume_Scale;
+                 Consume_RParen;
+                 exit;
+               end;
+            end;
+        else
+          Begin
+            Message(asmr_e_invalid_reference_syntax);
+            RecoverConsume(false);
+          end;
+        end;
+      end;
+
+
+    Procedure tx86attreader.BuildOperand(oper : tx86operand);
+      var
+        tempstr,
+        expr : string;
+        typesize,
+        l,k : longint;
+
+
+        procedure AddLabelOperand(hl:tasmlabel);
+          begin
+            if not(actasmtoken in [AS_PLUS,AS_MINUS,AS_LPAREN]) and
+               is_calljmp(actopcode) then
+             begin
+               oper.opr.typ:=OPR_SYMBOL;
+               oper.opr.symbol:=hl;
+             end
+            else
+             begin
+               oper.InitRef;
+               oper.opr.ref.symbol:=hl;
+             end;
+          end;
+
+
+        procedure MaybeRecordOffset;
+          var
+            hasdot  : boolean;
+            l,
+            toffset,
+            tsize   : longint;
+          begin
+            if not(actasmtoken in [AS_DOT,AS_PLUS,AS_MINUS]) then
+             exit;
+            l:=0;
+            hasdot:=(actasmtoken=AS_DOT);
+            if hasdot then
+             begin
+               if expr<>'' then
+                 begin
+                   BuildRecordOffsetSize(expr,toffset,tsize);
+                   inc(l,toffset);
+                   oper.SetSize(tsize,true);
+                 end;
+             end;
+            if actasmtoken in [AS_PLUS,AS_MINUS] then
+             inc(l,BuildConstExpression(true,false));
+            case oper.opr.typ of
+              OPR_LOCAL :
+                begin
+                  { don't allow direct access to fields of parameters, because that
+                    will generate buggy code. Allow it only for explicit typecasting }
+                  if hasdot and
+                     (not oper.hastype) and
+                     (tvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and
+                     (current_procinfo.procdef.proccalloption<>pocall_register) then
+                    Message(asmr_e_cannot_access_field_directly_for_parameters);
+                  inc(oper.opr.localsymofs,l)
+                end;
+              OPR_CONSTANT :
+                inc(oper.opr.val,l);
+              OPR_REFERENCE :
+                inc(oper.opr.ref.offset,l);
+              else
+                internalerror(200309221);
+            end;
+          end;
+
+
+        function MaybeBuildReference:boolean;
+          { Try to create a reference, if not a reference is found then false
+            is returned }
+          begin
+            MaybeBuildReference:=true;
+            case actasmtoken of
+              AS_INTNUM,
+              AS_MINUS,
+              AS_PLUS:
+                Begin
+                  oper.opr.ref.offset:=BuildConstExpression(True,False);
+                  if actasmtoken<>AS_LPAREN then
+                    Message(asmr_e_invalid_reference_syntax)
+                  else
+                    BuildReference(oper);
+                end;
+              AS_LPAREN:
+                BuildReference(oper);
+              AS_ID: { only a variable is allowed ... }
+                Begin
+                  tempstr:=actasmpattern;
+                  Consume(AS_ID);
+                  { typecasting? }
+                  if (actasmtoken=AS_LPAREN) and
+                     SearchType(tempstr,typesize) then
+                   begin
+                     oper.hastype:=true;
+                     Consume(AS_LPAREN);
+                     BuildOperand(oper);
+                     Consume(AS_RPAREN);
+                     if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+                       oper.SetSize(typesize,true);
+                   end
+                  else
+                   if not oper.SetupVar(tempstr,false) then
+                    Message1(sym_e_unknown_id,tempstr);
+                  { record.field ? }
+                  if actasmtoken=AS_DOT then
+                   begin
+                     BuildRecordOffsetSize(tempstr,l,k);
+                     inc(oper.opr.ref.offset,l);
+                   end;
+                  case actasmtoken of
+                    AS_END,
+                    AS_SEPARATOR,
+                    AS_COMMA: ;
+                    AS_LPAREN:
+                      BuildReference(oper);
+                  else
+                    Begin
+                      Message(asmr_e_invalid_reference_syntax);
+                      Consume(actasmtoken);
+                    end;
+                  end; {end case }
+                end;
+              else
+               MaybeBuildReference:=false;
+            end; { end case }
+          end;
+
+
+      const
+        regsize_2_size: array[S_B..S_L] of longint = (1,2,4);
+      var
+        tempreg : tregister;
+        hl      : tasmlabel;
+      Begin
+        expr:='';
+        case actasmtoken of
+          AS_LPAREN: { Memory reference or constant expression }
+            Begin
+              oper.InitRef;
+              BuildReference(oper);
+            end;
+
+          AS_DOLLAR: { Constant expression  }
+            Begin
+              Consume(AS_DOLLAR);
+              BuildConstantOperand(oper);
+            end;
+
+          AS_INTNUM,
+          AS_MINUS,
+          AS_PLUS:
+            Begin
+              { Constant memory offset }
+              { This must absolutely be followed by (  }
+              oper.InitRef;
+              oper.opr.ref.offset:=BuildConstExpression(True,False);
+              if actasmtoken<>AS_LPAREN then
+                Message(asmr_e_invalid_reference_syntax)
+              else
+                BuildReference(oper);
+            end;
+
+          AS_STAR: { Call from memory address }
+            Begin
+              Consume(AS_STAR);
+              if actasmtoken=AS_REGISTER then
+               begin
+                 oper.opr.typ:=OPR_REGISTER;
+                 oper.opr.reg:=actasmregister;
+                 oper.SetSize(regsize_2_size[reg2opsize(actasmregister)],true);
+                 Consume(AS_REGISTER);
+               end
+              else
+               begin
+                 oper.InitRef;
+                 if not MaybeBuildReference then
+                  Message(asmr_e_syn_operand);
+               end;
+              { this is only allowed for call's and jmp's }
+              if not is_calljmp(actopcode) then
+               Message(asmr_e_syn_operand);
+            end;
+
+          AS_ID: { A constant expression, or a Variable ref.  }
+            Begin
+              { Local Label ? }
+              if is_locallabel(actasmpattern) then
+               begin
+                 CreateLocalLabel(actasmpattern,hl,false);
+                 Consume(AS_ID);
+                 AddLabelOperand(hl);
+               end
+              else
+               { Check for label }
+               if SearchLabel(actasmpattern,hl,false) then
+                begin
+                  Consume(AS_ID);
+                  AddLabelOperand(hl);
+                end
+              else
+               { probably a variable or normal expression }
+               { or a procedure (such as in CALL ID)      }
+               Begin
+                 { is it a constant ? }
+                 if SearchIConstant(actasmpattern,l) then
+                  Begin
+                    if not (oper.opr.typ in [OPR_NONE,OPR_CONSTANT]) then
+                     Message(asmr_e_invalid_operand_type);
+                    BuildConstantOperand(oper);
+                  end
+                 else
+                  begin
+                    expr:=actasmpattern;
+                    Consume(AS_ID);
+                    { typecasting? }
+                    if (actasmtoken=AS_LPAREN) and
+                       SearchType(expr,typesize) then
+                     begin
+                       oper.hastype:=true;
+                       Consume(AS_LPAREN);
+                       BuildOperand(oper);
+                       Consume(AS_RPAREN);
+                       if oper.opr.typ in [OPR_REFERENCE,OPR_LOCAL] then
+                         oper.SetSize(typesize,true);
+                     end
+                    else
+                     begin
+                       if oper.SetupVar(expr,false) then
+                        begin
+                        end
+                       else
+                        Begin
+                          { look for special symbols ... }
+                          if expr= '__HIGH' then
+                            begin
+                              consume(AS_LPAREN);
+                              if not oper.setupvar('high'+actasmpattern,false) then
+                                Message1(sym_e_unknown_id,'high'+actasmpattern);
+                              consume(AS_ID);
+                              consume(AS_RPAREN);
+                            end
+                          else
+                           if expr = '__RESULT' then
+                            oper.SetUpResult
+                          else
+                           if expr = '__SELF' then
+                            oper.SetupSelf
+                          else
+                           if expr = '__OLDEBP' then
+                            oper.SetupOldEBP
+                          else
+                            { check for direct symbolic names   }
+                            { only if compiling the system unit }
+                            if (cs_compilesystem in aktmoduleswitches) then
+                             begin
+                               if not oper.SetupDirectVar(expr) then
+                                Begin
+                                  { not found, finally ... add it anyways ... }
+                                  Message1(asmr_w_id_supposed_external,expr);
+                                  oper.InitRef;
+                                  oper.opr.ref.symbol:=objectlibrary.newasmsymbol(expr);
+                                end;
+                             end
+                          else
+                            Message1(sym_e_unknown_id,expr);
+                        end;
+                     end;
+                  end;
+                  if actasmtoken=AS_DOT then
+                    MaybeRecordOffset;
+                  { add a constant expression? }
+                  if (actasmtoken=AS_PLUS) then
+                   begin
+                     l:=BuildConstExpression(true,false);
+                     case oper.opr.typ of
+                       OPR_CONSTANT :
+                         inc(oper.opr.val,l);
+                       OPR_LOCAL :
+                         inc(oper.opr.localsymofs,l);
+                       OPR_REFERENCE :
+                         inc(oper.opr.ref.offset,l);
+                       else
+                         internalerror(200309202);
+                     end;
+                   end
+               end;
+              { Do we have a indexing reference, then parse it also }
+              if actasmtoken=AS_LPAREN then
+                BuildReference(oper);
+            end;
+
+          AS_REGISTER: { Register, a variable reference or a constant reference  }
+            Begin
+              { save the type of register used. }
+              tempreg:=actasmregister;
+              Consume(AS_REGISTER);
+              if actasmtoken = AS_COLON then
+               Begin
+                 Consume(AS_COLON);
+                 oper.InitRef;
+                 oper.opr.ref.segment:=tempreg;
+                 { This must absolutely be followed by a reference }
+                 if not MaybeBuildReference then
+                  Begin
+                    Message(asmr_e_invalid_seg_override);
+                    Consume(actasmtoken);
+                  end;
+               end
+              { Simple register  }
+              else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
+                Begin
+                  if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
+                    Message(asmr_e_invalid_operand_type);
+                  oper.opr.typ:=OPR_REGISTER;
+                  oper.opr.reg:=tempreg;
+                  oper.SetSize(tcgsize2size[cg.reg_cgsize(oper.opr.reg)],true);
+                end
+              else
+                Message(asmr_e_syn_operand);
+            end;
+          AS_END,
+          AS_SEPARATOR,
+          AS_COMMA: ;
+        else
+          Begin
+            Message(asmr_e_syn_operand);
+            Consume(actasmtoken);
+          end;
+        end; { end case }
+      end;
+
+
+    procedure tx86attreader.BuildOpCode(instr : tx86instruction);
+      var
+        operandnum : longint;
+        PrefixOp,OverrideOp: tasmop;
+      Begin
+        PrefixOp:=A_None;
+        OverrideOp:=A_None;
+        { prefix seg opcode / prefix opcode }
+        repeat
+          if is_prefix(actopcode) then
+            begin
+              PrefixOp:=ActOpcode;
+              with instr do
+                begin
+                  opcode:=ActOpcode;
+                  condition:=ActCondition;
+                  opsize:=ActOpsize;
+                  ConcatInstruction(curlist);
+                end;
+              Consume(AS_OPCODE);
+            end
+          else
+            if is_override(actopcode) then
+              begin
+                OverrideOp:=ActOpcode;
+                with instr do
+                  begin
+                    opcode:=ActOpcode;
+                    condition:=ActCondition;
+                    opsize:=ActOpsize;
+                    ConcatInstruction(curlist);
+                  end;
+                Consume(AS_OPCODE);
+              end
+            else
+              break;
+          { allow for newline as in gas styled syntax }
+          while actasmtoken=AS_SEPARATOR do
+            Consume(AS_SEPARATOR);
+        until (actasmtoken<>AS_OPCODE);
+        { opcode }
+        if (actasmtoken<>AS_OPCODE) then
+         Begin
+           Message(asmr_e_invalid_or_missing_opcode);
+           RecoverConsume(true);
+           exit;
+         end;
+        { Fill the instr object with the current state }
+        with instr do
+          begin
+            Opcode:=ActOpcode;
+            condition:=ActCondition;
+            opsize:=ActOpsize;
+          end;
+
+        { Valid combination of prefix/override and instruction ?  }
+
+        if (prefixop<>A_NONE) and (NOT CheckPrefix(PrefixOp,actopcode)) then
+           Message1(asmr_e_invalid_prefix_and_opcode,actasmpattern);
+
+        if (overrideop<>A_NONE) and (NOT CheckOverride(OverrideOp,ActOpcode)) then
+          Message1(asmr_e_invalid_override_and_opcode,actasmpattern);
+        { We are reading operands, so opcode will be an AS_ID }
+        operandnum:=1;
+        Consume(AS_OPCODE);
+        { Zero operand opcode ?  }
+        if actasmtoken in [AS_SEPARATOR,AS_END] then
+         begin
+           operandnum:=0;
+           exit;
+         end;
+        { Read the operands }
+        repeat
+          case actasmtoken of
+            AS_COMMA: { Operand delimiter }
+              Begin
+                if operandnum > Max_Operands then
+                  Message(asmr_e_too_many_operands)
+                else
+                  Inc(operandnum);
+                Consume(AS_COMMA);
+              end;
+            AS_SEPARATOR,
+            AS_END : { End of asm operands for this opcode  }
+              begin
+                break;
+              end;
+          else
+            BuildOperand(instr.Operands[operandnum] as tx86operand);
+          end; { end case }
+        until false;
+        instr.Ops:=operandnum;
+      end;
+
+
+    function tx86attreader.is_asmopcode(const s: string):boolean;
+      const
+        { We need first to check the long prefixes, else we get probs
+          with things like movsbl }
+        att_sizesuffixstr : array[0..9] of string[2] = (
+          '','BW','BL','WL','B','W','L','S','Q','T'
+        );
+        att_sizesuffix : array[0..9] of topsize = (
+          S_NO,S_BW,S_BL,S_WL,S_B,S_W,S_L,S_FS,S_IQ,S_FX
+        );
+        att_sizefpusuffix : array[0..9] of topsize = (
+          S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_FL,S_FS,S_IQ,S_FX
+        );
+        att_sizefpuintsuffix : array[0..9] of topsize = (
+          S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
+        );
+      var
+        str2opentry: tstr2opentry;
+        cond : string[4];
+        cnd  : tasmcond;
+        len,
+        j,
+        sufidx : longint;
+      Begin
+        is_asmopcode:=FALSE;
+
+        actopcode:=A_None;
+        actcondition:=C_None;
+        actopsize:=S_NO;
+
+        { search for all possible suffixes }
+        for sufidx:=low(att_sizesuffixstr) to high(att_sizesuffixstr) do
+         begin
+           len:=length(s)-length(att_sizesuffixstr[sufidx]);
+           if copy(s,len+1,length(att_sizesuffixstr[sufidx]))=att_sizesuffixstr[sufidx] then
+            begin
+              { here we search the entire table... }
+              str2opentry:=nil;
+              if {(length(s)>0) and} (len>0) then
+                str2opentry:=tstr2opentry(iasmops.search(copy(s,1,len)));
+              if assigned(str2opentry) then
+                begin
+                  actopcode:=str2opentry.op;
+                  if gas_needsuffix[actopcode]=attsufFPU then
+                   actopsize:=att_sizefpusuffix[sufidx]
+                  else if gas_needsuffix[actopcode]=attsufFPUint then
+                   actopsize:=att_sizefpuintsuffix[sufidx]
+                  else
+                   actopsize:=att_sizesuffix[sufidx];
+                  actasmtoken:=AS_OPCODE;
+                  is_asmopcode:=TRUE;
+                  exit;
+                end;
+              { not found, check condition opcodes }
+              j:=0;
+              while (j<CondAsmOps) do
+               begin
+                 if Copy(s,1,Length(CondAsmOpStr[j]))=CondAsmOpStr[j] then
+                  begin
+                    cond:=Copy(s,Length(CondAsmOpStr[j])+1,len-Length(CondAsmOpStr[j]));
+                    if cond<>'' then
+                     begin
+                       for cnd:=low(TasmCond) to high(TasmCond) do
+                        if Cond=Upper(cond2str[cnd]) then
+                         begin
+                           actopcode:=CondASmOp[j];
+                           if gas_needsuffix[actopcode]=attsufFPU then
+                            actopsize:=att_sizefpusuffix[sufidx]
+                           else if gas_needsuffix[actopcode]=attsufFPUint then
+                            actopsize:=att_sizefpuintsuffix[sufidx]
+                           else
+                            actopsize:=att_sizesuffix[sufidx];
+                           actcondition:=cnd;
+                           actasmtoken:=AS_OPCODE;
+                           is_asmopcode:=TRUE;
+                           exit;
+                         end;
+                     end;
+                  end;
+                 inc(j);
+               end;
+           end;
+         end;
+      end;
+
+
+    procedure tx86attreader.handleopcode;
+      var
+        instr : Tx86Instruction;
+      begin
+        instr:=Tx86Instruction.Create(Tx86Operand);
+        instr.OpOrder:=op_att;
+        BuildOpcode(instr);
+        instr.AddReferenceSizes;
+        instr.SetInstructionOpsize;
+        instr.CheckOperandSizes;
+        instr.ConcatInstruction(curlist);
+        instr.Free;
+      end;
+
+
+end.
+{
+  $Log$
+  Revision 1.1  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+
+  Revision 1.58  2003/11/12 16:05:39  florian
+    * assembler readers OOPed
+    + typed currency constants
+    + typed 128 bit float constants if the CPU supports it
+
+  Revision 1.57  2003/11/10 19:08:32  peter
+    * line numbering is now only done when #10, #10#13 is really parsed
+      instead of when it is the next character
+
+  Revision 1.56  2003/10/29 16:47:18  peter
+    * fix field offset in reference
+
+  Revision 1.55  2003/10/26 13:37:22  florian
+    * fixed web bug 2128
+
+  Revision 1.54  2003/10/24 17:39:03  peter
+    * more intel parser updates
+
+  Revision 1.53  2003/10/23 17:19:44  peter
+    * typecasting fixes
+    * reference building more delphi compatible
+
+  Revision 1.52  2003/10/20 19:29:35  peter
+    * fix check for register subscription of reference parameter
+
+  Revision 1.51  2003/10/16 21:29:24  peter
+    + __HIGH() to retrieve high value
+
+  Revision 1.50  2003/10/07 18:21:18  peter
+    * fix crash
+    * allow parameter subscription for register parameters
+
+  Revision 1.49  2003/10/01 20:34:49  peter
+    * procinfo unit contains tprocinfo
+    * cginfo renamed to cgbase
+    * moved cgmessage to verbose
+    * fixed ppc and sparc compiles
+
+  Revision 1.48  2003/09/23 20:37:53  peter
+    * fix global var+offset
+
+  Revision 1.47  2003/09/23 17:56:06  peter
+    * locals and paras are allocated in the code generation
+    * tvarsym.localloc contains the location of para/local when
+      generating code for the current procedure
+
+  Revision 1.46  2003/09/03 15:55:01  peter
+    * NEWRA branch merged
+
+  Revision 1.45.2.2  2003/08/31 15:46:26  peter
+    * more updates for tregister
+
+  Revision 1.45.2.1  2003/08/28 18:35:08  peter
+    * tregister changed to cardinal
+
+  Revision 1.45  2003/05/30 23:57:08  peter
+    * more sparc cleanup
+    * accumulator removed, splitted in function_return_reg (called) and
+      function_result_reg (caller)
+
+  Revision 1.44  2003/05/22 21:32:29  peter
+    * removed some unit dependencies
+
+  Revision 1.43  2003/04/30 15:45:35  florian
+    * merged more x86-64/i386 code
+
+  Revision 1.42  2003/04/25 12:04:31  florian
+    * merged agx64att and ag386att to x86/agx86att
+
+  Revision 1.41  2003/04/21 20:05:10  peter
+    * removed some ie checks
+
+  Revision 1.40  2003/03/18 18:15:53  peter
+    * changed reg2opsize to function
+
+  Revision 1.39  2003/02/20 15:52:58  pierre
+   * fix a range check error
+
+  Revision 1.38  2003/02/19 22:00:16  daniel
+    * Code generator converted to new register notation
+    - Horribily outdated todo.txt removed
+
+  Revision 1.37  2003/02/03 22:47:14  daniel
+    - Removed reg_2_opsize array
+
+  Revision 1.36  2003/01/08 18:43:57  daniel
+   * Tregister changed into a record
+
+  Revision 1.35  2002/12/14 15:02:03  carl
+    * maxoperands -> max_operands (for portability in rautils.pas)
+    * fix some range-check errors with loadconst
+    + add ncgadd unit to m68k
+    * some bugfix of a_param_reg with LOC_CREFERENCE
+
+  Revision 1.34  2002/12/01 22:08:34  carl
+    * some small cleanup (remove some specific operators which are not supported)
+
+  Revision 1.33  2002/11/30 23:16:39  carl
+    - removed unused message
+
+  Revision 1.32  2002/11/15 01:58:58  peter
+    * merged changes from 1.0.7 up to 04-11
+      - -V option for generating bug report tracing
+      - more tracing for option parsing
+      - errors for cdecl and high()
+      - win32 import stabs
+      - win32 records<=8 are returned in eax:edx (turned off by default)
+      - heaptrc update
+      - more info for temp management in .s file with EXTDEBUG
+
+  Revision 1.31  2002/09/03 16:26:28  daniel
+    * Make Tprocdef.defs protected
+
+  Revision 1.30  2002/08/13 18:01:52  carl
+    * rename swatoperands to swapoperands
+    + m68k first compilable version (still needs a lot of testing):
+        assembler generator, system information , inline
+        assembler reader.
+
+  Revision 1.29  2002/08/12 15:08:42  carl
+    + stab register indexes for powerpc (moved from gdb to cpubase)
+    + tprocessor enumeration moved to cpuinfo
+    + linker in target_info is now a class
+    * many many updates for m68k (will soon start to compile)
+    - removed some ifdef or correct them for correct cpu
+
+  Revision 1.28  2002/08/11 14:32:31  peter
+    * renamed current_library to objectlibrary
+
+  Revision 1.27  2002/08/11 13:24:17  peter
+    * saving of asmsymbols in ppu supported
+    * asmsymbollist global is removed and moved into a new class
+      tasmlibrarydata that will hold the info of a .a file which
+      corresponds with a single module. Added librarydata to tmodule
+      to keep the library info stored for the module. In the future the
+      objectfiles will also be stored to the tasmlibrarydata class
+    * all getlabel/newasmsymbol and friends are moved to the new class
+
+  Revision 1.26  2002/07/26 21:15:44  florian
+    * rewrote the system handling
+
+  Revision 1.25  2002/07/01 18:46:34  peter
+    * internal linker
+    * reorganized aasm layer
+
+  Revision 1.24  2002/05/18 13:34:25  peter
+    * readded missing revisions
+
+  Revision 1.23  2002/05/16 19:46:52  carl
+  + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
+  + try to fix temp allocation (still in ifdef)
+  + generic constructor calls
+  + start of tassembler / tmodulebase class cleanup
+
+  Revision 1.21  2002/04/15 19:12:09  carl
+  + target_info.size_of_pointer -> pointer_size
+  + some cleanup of unused types/variables
+  * move several constants from cpubase to their specific units
+    (where they are used)
+  + att_Reg2str -> gas_reg2str
+  + int_reg2str -> std_reg2str
+
+  Revision 1.20  2002/04/14 17:01:52  carl
+  + att_reg2str -> gas_reg2str
+
+  Revision 1.19  2002/04/04 19:06:13  peter
+    * removed unused units
+    * use tlocation.size in cg.a_*loc*() routines
+
+  Revision 1.18  2002/04/02 17:11:39  peter
+    * tlocation,treference update
+    * LOC_CONSTANT added for better constant handling
+    * secondadd splitted in multiple routines
+    * location_force_reg added for loading a location to a register
+      of a specified size
+    * secondassignment parses now first the right and then the left node
+      (this is compatible with Kylix). This saves a lot of push/pop especially
+      with string operations
+    * adapted some routines to use the new cg methods
+
+  Revision 1.17  2002/03/28 20:48:25  carl
+  - remove go32v1 support
+
+  Revision 1.16  2002/01/24 18:25:53  peter
+   * implicit result variable generation for assembler routines
+   * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
+
+}

+ 20 - 2
compiler/x86_64/cgcpu.pas

@@ -32,10 +32,11 @@ unit cgcpu;
        cgbase,cgobj,cg64f64,cgx86,
        cgbase,cgobj,cg64f64,cgx86,
        aasmbase,aasmtai,aasmcpu,
        aasmbase,aasmtai,aasmcpu,
        cpubase,cpuinfo,cpupara,
        cpubase,cpuinfo,cpupara,
-       node,symconst;
+       node,symconst,rgx86;
 
 
     type
     type
       tcgx86_64 = class(tcgx86)
       tcgx86_64 = class(tcgx86)
+        procedure init_register_allocators;override;
         class function reg_cgsize(const reg: tregister): tcgsize; override;
         class function reg_cgsize(const reg: tregister): tcgsize; override;
         procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);override;
         procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);override;
       end;
       end;
@@ -48,6 +49,19 @@ unit cgcpu;
        rgobj,tgobj,rgcpu;
        rgobj,tgobj,rgcpu;
 
 
 
 
+    procedure Tcgx86_64.init_register_allocators;
+      begin
+        inherited init_register_allocators;
+        if cs_create_pic in aktmoduleswitches then
+          rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP,RS_EBX])
+        else
+          rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
+        rg[R_MMXREGISTER]:=trgcpu.create(R_MMXREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_sse_imreg,[]);
+        rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_sse_imreg,[]);
+        rgfpu:=Trgx86fpu.create;
+      end;
+
+
     class function tcgx86_64.reg_cgsize(const reg: tregister): tcgsize;
     class function tcgx86_64.reg_cgsize(const reg: tregister): tcgsize;
     const subreg2cgsize:array[Tsubregister] of Tcgsize =
     const subreg2cgsize:array[Tsubregister] of Tcgsize =
           (OS_NO,OS_8,OS_8,OS_16,OS_32,OS_64,OS_NO,OS_NO);
           (OS_NO,OS_8,OS_8,OS_16,OS_32,OS_64,OS_NO,OS_NO);
@@ -206,7 +220,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.8  2004-01-13 18:08:58  florian
+  Revision 1.9  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+
+  Revision 1.8  2004/01/13 18:08:58  florian
     * x86-64 compilation fixed
     * x86-64 compilation fixed
 
 
   Revision 1.7  2003/12/24 01:47:23  florian
   Revision 1.7  2003/12/24 01:47:23  florian

+ 6 - 2
compiler/x86_64/cpubase.inc

@@ -123,7 +123,7 @@ const
         This value can be deduced from the CALLED_USED_REGISTERS array in the
         This value can be deduced from the CALLED_USED_REGISTERS array in the
         GCC source.
         GCC source.
       }
       }
-      std_saved_registers = [RS_ESI,RS_EDI,RS_EBX];
+      saved_standard_registers : array[0..4] of tsuperregister = (RS_EBX,RS_R12,RS_R13,RS_R14,RS_R15);
       { Required parameter alignment when calling a routine declared as
       { Required parameter alignment when calling a routine declared as
         stdcall and cdecl. The alignment value should be the one defined
         stdcall and cdecl. The alignment value should be the one defined
         by GCC or the target ABI.
         by GCC or the target ABI.
@@ -135,7 +135,11 @@ const
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.9  2003-12-22 19:00:17  florian
+  Revision 1.10  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+
+  Revision 1.9  2003/12/22 19:00:17  florian
     * fixed some x86-64 issues
     * fixed some x86-64 issues
 
 
   Revision 1.8  2003/09/25 13:13:32  florian
   Revision 1.8  2003/09/25 13:13:32  florian

+ 87 - 9
compiler/x86_64/cpupara.pas

@@ -49,11 +49,12 @@ unit cpupara;
 
 
     uses
     uses
        verbose,
        verbose,
-       cpuinfo,cgbase,
+       cpuinfo,cgbase,systems,
        defutil;
        defutil;
 
 
     const
     const
-      intreg_nr2reg : array[1..6] of tsuperregister = (RS_RDI,RS_RSI,RS_RDX,RS_RCX,RS_R8,RS_R9);
+      paraintsupregs : array[0..5] of tsuperregister = (RS_RDI,RS_RSI,RS_RDX,RS_RCX,RS_R8,RS_R9);
+      parammsupregs : array[0..7] of tsuperregister = (RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7);
 
 
     function getparaloc(p : tdef) : tcgloc;
     function getparaloc(p : tdef) : tcgloc;
 
 
@@ -120,15 +121,17 @@ unit cpupara;
          end;
          end;
       end;
       end;
 
 
+
     function tx86_64paramanager.getintparaloc(calloption : tproccalloption; nr : longint): tparalocation;
     function tx86_64paramanager.getintparaloc(calloption : tproccalloption; nr : longint): tparalocation;
       begin
       begin
          fillchar(result,sizeof(tparalocation),0);
          fillchar(result,sizeof(tparalocation),0);
+         result.size:=OS_INT;
          if nr<1 then
          if nr<1 then
            internalerror(200304303)
            internalerror(200304303)
-         else if nr<=6 then
+         else if nr<=high(paraintsupregs)+1 then
            begin
            begin
               result.loc:=LOC_REGISTER;
               result.loc:=LOC_REGISTER;
-              result.register:=newreg(R_INTREGISTER,intreg_nr2reg[nr],R_SUBWHOLE);
+              result.register:=newreg(R_INTREGISTER,paraintsupregs[nr-1],R_SUBWHOLE);
            end
            end
          else
          else
            begin
            begin
@@ -140,11 +143,82 @@ unit cpupara;
 
 
 
 
     function tx86_64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
     function tx86_64paramanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+      var
+        hp : tparaitem;
+        paraloc : tparalocation;
+        subreg : tsubregister;
+        pushaddr : boolean;
+        l,intparareg,mmparareg,
+        varalign,
+        paraalign,
+        parasize : longint;
       begin
       begin
-         { set default para_alignment to target_info.stackalignment }
-         { if para_alignment=0 then
-           para_alignment:=aktalignment.paraalign;
-         }
+        intparareg:=0;
+        mmparareg:=0;
+        parasize:=0;
+        paraalign:=get_para_align(p.proccalloption);
+        { Register parameters are assigned from left to right }
+        hp:=tparaitem(p.para.first);
+        while assigned(hp) do
+          begin
+            pushaddr:=push_addr_param(hp.paratyp,hp.paratype.def,p.proccalloption);
+            if pushaddr then
+              paraloc.size:=OS_ADDR
+            else
+              paraloc.size:=def_cgsize(hp.paratype.def);
+            paraloc.alignment:=paraalign;
+            if (intparareg<=high(paraintsupregs)) and
+               not(
+                   ((hp.paratype.def.deftype in [floatdef,recorddef,arraydef]) and
+                    (not pushaddr))
+                  ) then
+              begin
+                paraloc.loc:=LOC_REGISTER;
+                if paraloc.size=OS_NO then
+                  subreg:=R_SUBWHOLE
+                else
+                  subreg:=cgsize2subreg(paraloc.size);
+                paraloc.alignment:=paraalign;
+                paraloc.register:=newreg(R_INTREGISTER,paraintsupregs[intparareg],subreg);
+                inc(intparareg);
+              end
+            else if (mmparareg<=high(parammsupregs)) then
+              begin
+              end
+            else
+              begin
+                paraloc.loc:=LOC_REFERENCE;
+                if side=callerside then
+                  paraloc.reference.index:=NR_STACK_POINTER_REG
+                else
+                  paraloc.reference.index:=NR_FRAME_POINTER_REG;
+                l:=push_size(hp.paratyp,hp.paratype.def,p.proccalloption);
+                // varalign:=size_2_align(l);
+                paraloc.reference.offset:=parasize;
+                // varalign:=used_align(varalign,paraalign,paraalign);
+                // parasize:=align(parasize+l,varalign);
+              end;
+            hp.paraloc[side]:=paraloc;
+            hp:=tparaitem(hp.next);
+          end;
+        { Register parameters are assigned from left-to-right, adapt offset
+          for calleeside to be reversed }
+        hp:=tparaitem(p.para.first);
+        while assigned(hp) do
+          begin
+            if (hp.paraloc[side].loc=LOC_REFERENCE) then
+              begin
+                l:=push_size(hp.paratyp,hp.paratype.def,p.proccalloption);
+                // varalign:=used_align(size_2_align(l),paraalign,paraalign);
+                // l:=align(l,varalign);
+                hp.paraloc[side].reference.offset:=parasize-hp.paraloc[side].reference.offset-l;
+                if side=calleeside then
+                  inc(hp.paraloc[side].reference.offset,target_info.first_parm_offset);
+              end;
+            hp:=tparaitem(hp.next);
+          end;
+        { We need to return the size allocated }
+        result:=parasize;
       end;
       end;
 
 
 
 
@@ -153,7 +227,11 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.5  2003-12-24 00:10:03  florian
+  Revision 1.6  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+
+  Revision 1.5  2003/12/24 00:10:03  florian
     - delete parameter in cg64 methods removed
     - delete parameter in cg64 methods removed
 
 
   Revision 1.4  2003/04/30 20:53:32  florian
   Revision 1.4  2003/04/30 20:53:32  florian

+ 76 - 0
compiler/x86_64/rax64att.pas

@@ -0,0 +1,76 @@
+{
+    $Id$
+    Copyright (c) 1998-2002 by Carl Eric Codere and Peter Vreman
+
+    Does the parsing for the i386 GNU AS styled 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 rax64att;
+
+{$i fpcdefs.inc}
+
+  interface
+
+    uses
+      rax86att;
+
+    type
+      tx8664attreader = class(tx86attreader)
+        procedure handleopcode;override;
+      end;
+
+
+  implementation
+
+    uses
+      rabase,systems,rax86,aasmcpu;
+
+    procedure tx8664attreader.handleopcode;
+      var
+        instr : Tx86Instruction;
+      begin
+        instr:=Tx86Instruction.Create(Tx86Operand);
+        instr.OpOrder:=op_att;
+        BuildOpcode(instr);
+        instr.AddReferenceSizes;
+        instr.SetInstructionOpsize;
+        {
+        instr.CheckOperandSizes;
+        }
+        instr.ConcatInstruction(curlist);
+        instr.Free;
+      end;
+
+
+const
+  asmmode_x86_64_gas_info : tasmmodeinfo =
+          (
+            id    : asmmode_x86_64_gas;
+            idtxt : 'GAS';
+            casmreader : tx8664attreader;
+          );
+
+initialization
+  RegisterAsmMode(asmmode_x86_64_gas_info);
+end.
+{
+  $Log$
+  Revision 1.1  2004-01-14 23:39:05  florian
+    * another bunch of x86-64 fixes mainly calling convention and
+      assembler reader related
+}