Procházet zdrojové kódy

+ inline support for the x86 'in' and 'out' instructions. Currently only enabled
in the i8086-msdos 'ports' unit, but will be enabled on other targets (e.g.
go32v2) in the future as well. 32-bit 'in' and 'out' not inlined on i8086, but
will be on i386 and x86_64.

git-svn-id: trunk@39362 -

nickysn před 7 roky
rodič
revize
fdc896ad0a

+ 1 - 0
.gitattributes

@@ -842,6 +842,7 @@ compiler/x86/aoptx86.pas svneol=native#text/pascal
 compiler/x86/cga.pas svneol=native#text/plain
 compiler/x86/cga.pas svneol=native#text/plain
 compiler/x86/cgx86.pas svneol=native#text/plain
 compiler/x86/cgx86.pas svneol=native#text/plain
 compiler/x86/cpubase.pas svneol=native#text/plain
 compiler/x86/cpubase.pas svneol=native#text/plain
+compiler/x86/cx86innr.inc svneol=native#text/plain
 compiler/x86/hlcgx86.pas svneol=native#text/plain
 compiler/x86/hlcgx86.pas svneol=native#text/plain
 compiler/x86/itcpugas.pas svneol=native#text/plain
 compiler/x86/itcpugas.pas svneol=native#text/plain
 compiler/x86/itx86int.pas svneol=native#text/plain
 compiler/x86/itx86int.pas svneol=native#text/plain

+ 4 - 0
compiler/compinnr.pas

@@ -164,6 +164,10 @@ type
 
 
      { SSE }
      { SSE }
 
 
+{$if defined(X86)}
+     ,
+     {$i x86/cx86innr.inc}
+{$endif }
 {$if defined(AVR)}
 {$if defined(AVR)}
      ,
      ,
      {$i ccpuinnr.inc}
      {$i ccpuinnr.inc}

+ 12 - 0
compiler/i8086/n8086inl.pas

@@ -34,6 +34,7 @@ interface
 
 
        ti8086inlinenode = class(tx86inlinenode)
        ti8086inlinenode = class(tx86inlinenode)
          function pass_typecheck_cpu: tnode; override;
          function pass_typecheck_cpu: tnode; override;
+         procedure pass_generate_code_cpu;override;
          function typecheck_faraddr: tnode;
          function typecheck_faraddr: tnode;
          function typecheck_seg: tnode; override;
          function typecheck_seg: tnode; override;
          function first_seg: tnode; override;
          function first_seg: tnode; override;
@@ -73,6 +74,17 @@ implementation
          end;
          end;
        end;
        end;
 
 
+     procedure ti8086inlinenode.pass_generate_code_cpu;
+       begin
+         case inlinenumber of
+           in_x86_inportl,
+           in_x86_outportl:
+             internalerror(2018070302);
+           else
+             inherited pass_generate_code_cpu;
+         end;
+       end;
+
      function ti8086inlinenode.typecheck_faraddr: tnode;
      function ti8086inlinenode.typecheck_faraddr: tnode;
        var
        var
          addr_node: tnode;
          addr_node: tnode;

+ 20 - 0
compiler/x86/cx86innr.inc

@@ -0,0 +1,20 @@
+{
+
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2018 by the Free Pascal development team.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    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.
+
+ **********************************************************************}
+
+  in_x86_inportb = fpc_in_cpu_first,
+  in_x86_inportw = fpc_in_cpu_first+1,
+  in_x86_inportl = fpc_in_cpu_first+2,
+  in_x86_outportb = fpc_in_cpu_first+3,
+  in_x86_outportw = fpc_in_cpu_first+4,
+  in_x86_outportl = fpc_in_cpu_first+5

+ 105 - 1
compiler/x86/nx86inl.pas

@@ -33,10 +33,13 @@ interface
          protected
          protected
           procedure maybe_remove_round_trunc_typeconv; virtual;
           procedure maybe_remove_round_trunc_typeconv; virtual;
          public
          public
+          function pass_typecheck_cpu:tnode;override;
+
           { first pass override
           { first pass override
             so that the code generator will actually generate
             so that the code generator will actually generate
             these nodes.
             these nodes.
           }
           }
+          function first_cpu: tnode;override;
           function first_pi: tnode ; override;
           function first_pi: tnode ; override;
           function first_arctan_real: tnode; override;
           function first_arctan_real: tnode; override;
           function first_abs_real: tnode; override;
           function first_abs_real: tnode; override;
@@ -55,6 +58,7 @@ interface
           function simplify(forinline : boolean) : tnode; override;
           function simplify(forinline : boolean) : tnode; override;
 
 
           { second pass override to generate these nodes }
           { second pass override to generate these nodes }
+          procedure pass_generate_code_cpu;override;
           procedure second_IncludeExclude;override;
           procedure second_IncludeExclude;override;
           procedure second_pi; override;
           procedure second_pi; override;
           procedure second_arctan_real; override;
           procedure second_arctan_real; override;
@@ -88,9 +92,10 @@ implementation
       aasmbase,aasmdata,aasmcpu,
       aasmbase,aasmdata,aasmcpu,
       symconst,symtype,symdef,symcpu,
       symconst,symtype,symdef,symcpu,
       ncnv,
       ncnv,
+      htypechk,
       cgbase,pass_1,pass_2,
       cgbase,pass_1,pass_2,
       cpuinfo,cpubase,nutils,
       cpuinfo,cpubase,nutils,
-      ncal,ncgutil,
+      ncal,ncgutil,nld,
       tgobj,
       tgobj,
       cga,cgutils,cgx86,cgobj,hlcgobj;
       cga,cgutils,cgx86,cgobj,hlcgobj;
 
 
@@ -105,6 +110,56 @@ implementation
        end;
        end;
 
 
 
 
+     function tx86inlinenode.pass_typecheck_cpu: tnode;
+       begin
+         Result:=nil;
+         case inlinenumber of
+           in_x86_inportb:
+             begin
+               CheckParameters(1);
+               resultdef:=u8inttype;
+             end;
+           in_x86_inportw:
+             begin
+               CheckParameters(1);
+               resultdef:=u16inttype;
+             end;
+           in_x86_inportl:
+             begin
+               CheckParameters(1);
+               resultdef:=s32inttype;
+             end;
+           in_x86_outportb,
+           in_x86_outportw,
+           in_x86_outportl:
+             begin
+               CheckParameters(2);
+               resultdef:=voidtype;
+             end;
+           else
+             Result:=inherited pass_typecheck_cpu;
+         end;
+       end;
+
+
+     function tx86inlinenode.first_cpu: tnode;
+       begin
+         Result:=nil;
+         case inlinenumber of
+           in_x86_inportb,
+           in_x86_inportw,
+           in_x86_inportl:
+             expectloc:=LOC_REGISTER;
+           in_x86_outportb,
+           in_x86_outportw,
+           in_x86_outportl:
+             expectloc:=LOC_VOID;
+           else
+             Result:=inherited first_cpu;
+         end;
+       end;
+
+
      function tx86inlinenode.first_pi : tnode;
      function tx86inlinenode.first_pi : tnode;
       begin
       begin
         if (tfloatdef(pbestrealtype^).floattype=s80real) then
         if (tfloatdef(pbestrealtype^).floattype=s80real) then
@@ -331,6 +386,55 @@ implementation
        end;
        end;
 
 
 
 
+     procedure tx86inlinenode.pass_generate_code_cpu;
+
+       procedure inport(dreg:TRegister;dsize:topsize;dtype:tdef);
+         begin
+           secondpass(left);
+           hlcg.getcpuregister(current_asmdata.CurrAsmList,NR_DX);
+           hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,left.resultdef,u16inttype,left.location,NR_DX);
+           hlcg.getcpuregister(current_asmdata.CurrAsmList,dreg);
+           current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_IN,dsize,NR_DX,dreg));
+           hlcg.ungetcpuregister(current_asmdata.CurrAsmList,NR_DX);
+           location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+           location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
+           hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,dtype,resultdef,dreg,location.register);
+           hlcg.ungetcpuregister(current_asmdata.CurrAsmList,dreg);
+         end;
+
+       procedure outport(dreg:TRegister;dsize:topsize;dtype:tdef);
+         begin
+           secondpass(tcallparanode(left).left);
+           secondpass(tcallparanode(tcallparanode(left).right).left);
+           hlcg.getcpuregister(current_asmdata.CurrAsmList,dreg);
+           hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,tcallparanode(left).left.resultdef,dtype,tcallparanode(left).left.location,dreg);
+           hlcg.getcpuregister(current_asmdata.CurrAsmList,NR_DX);
+           hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,tcallparanode(tcallparanode(left).right).left.resultdef,u16inttype,tcallparanode(tcallparanode(left).right).left.location,NR_DX);
+           current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_OUT,dsize,dreg,NR_DX));
+           hlcg.ungetcpuregister(current_asmdata.CurrAsmList,NR_DX);
+           hlcg.ungetcpuregister(current_asmdata.CurrAsmList,dreg);
+         end;
+
+       begin
+         case inlinenumber of
+           in_x86_inportb:
+             inport(NR_AL,S_B,u8inttype);
+           in_x86_inportw:
+             inport(NR_AX,S_W,u16inttype);
+           in_x86_inportl:
+             inport(NR_EAX,S_L,s32inttype);
+           in_x86_outportb:
+             outport(NR_AL,S_B,u8inttype);
+           in_x86_outportw:
+             outport(NR_AX,S_W,u16inttype);
+           in_x86_outportl:
+             outport(NR_EAX,S_L,s32inttype);
+           else
+             inherited pass_generate_code_cpu;
+         end;
+       end;
+
+
      procedure tx86inlinenode.second_pi;
      procedure tx86inlinenode.second_pi;
        begin
        begin
          location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
          location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));

+ 27 - 18
rtl/msdos/ports.pp

@@ -45,37 +45,46 @@ var
    portw : tportw;
    portw : tportw;
    portl : tportl;
    portl : tportl;
 
 
+const
+  fpc_in_x86_inportb = fpc_in_cpu_first;
+  fpc_in_x86_inportw = fpc_in_cpu_first+1;
+//  fpc_in_x86_inportl = fpc_in_cpu_first+2;
+  fpc_in_x86_outportb = fpc_in_cpu_first+3;
+  fpc_in_x86_outportw = fpc_in_cpu_first+4;
+//  fpc_in_x86_outportl = fpc_in_cpu_first+5;
+
+function inportb(port : word) : byte;[internproc:fpc_in_x86_inportb];
+function inportw(port : word) : word;[internproc:fpc_in_x86_inportw];
+//function inportl(port : word) : longint;[internproc:fpc_in_x86_inportl];
+procedure outportb(port : word;data : byte);[internproc:fpc_in_x86_outportb];
+procedure outportw(port : word;data : word);[internproc:fpc_in_x86_outportw];
+//procedure outportl(port : word;data : longint);[internproc:fpc_in_x86_outportl];
+
   implementation
   implementation
 
 
 { to give easy port access like tp with port[] }
 { to give easy port access like tp with port[] }
 
 
-procedure tport.writeport(p : word;data : byte);assembler;
-asm
-  mov dx, p
-  mov al, data
-  out dx, al
+procedure tport.writeport(p : word;data : byte);inline;
+begin
+  outportb(p,data);
 end;
 end;
 
 
 
 
-function tport.readport(p : word) : byte;assembler;
-asm
-  mov dx, p
-  in al, dx
+function tport.readport(p : word) : byte;inline;
+begin
+  readport:=inportb(p);
 end;
 end;
 
 
 
 
-procedure tportw.writeport(p : word;data : word);assembler;
-asm
-  mov dx, p
-  mov ax, data
-  out dx, ax
+procedure tportw.writeport(p : word;data : word);inline;
+begin
+  outportw(p,data);
 end;
 end;
 
 
 
 
-function tportw.readport(p : word) : word;assembler;
-asm
-  mov dx, p
-  in ax, dx
+function tportw.readport(p : word) : word;inline;
+begin
+  readport:=inportw(p);
 end;
 end;