+ 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 -
This commit is contained in:
nickysn 2018-07-03 17:01:42 +00:00
parent b8ae9f5d6d
commit fdc896ad0a
6 changed files with 169 additions and 19 deletions

1
.gitattributes vendored
View File

@ -842,6 +842,7 @@ compiler/x86/aoptx86.pas svneol=native#text/pascal
compiler/x86/cga.pas svneol=native#text/plain
compiler/x86/cgx86.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/itcpugas.pas svneol=native#text/plain
compiler/x86/itx86int.pas svneol=native#text/plain

View File

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

View File

@ -34,6 +34,7 @@ interface
ti8086inlinenode = class(tx86inlinenode)
function pass_typecheck_cpu: tnode; override;
procedure pass_generate_code_cpu;override;
function typecheck_faraddr: tnode;
function typecheck_seg: tnode; override;
function first_seg: tnode; override;
@ -73,6 +74,17 @@ implementation
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;
var
addr_node: tnode;

20
compiler/x86/cx86innr.inc Normal file
View File

@ -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

View File

@ -33,10 +33,13 @@ interface
protected
procedure maybe_remove_round_trunc_typeconv; virtual;
public
function pass_typecheck_cpu:tnode;override;
{ first pass override
so that the code generator will actually generate
these nodes.
}
function first_cpu: tnode;override;
function first_pi: tnode ; override;
function first_arctan_real: tnode; override;
function first_abs_real: tnode; override;
@ -55,6 +58,7 @@ interface
function simplify(forinline : boolean) : tnode; override;
{ second pass override to generate these nodes }
procedure pass_generate_code_cpu;override;
procedure second_IncludeExclude;override;
procedure second_pi; override;
procedure second_arctan_real; override;
@ -88,9 +92,10 @@ implementation
aasmbase,aasmdata,aasmcpu,
symconst,symtype,symdef,symcpu,
ncnv,
htypechk,
cgbase,pass_1,pass_2,
cpuinfo,cpubase,nutils,
ncal,ncgutil,
ncal,ncgutil,nld,
tgobj,
cga,cgutils,cgx86,cgobj,hlcgobj;
@ -105,6 +110,56 @@ implementation
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;
begin
if (tfloatdef(pbestrealtype^).floattype=s80real) then
@ -331,6 +386,55 @@ implementation
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;
begin
location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));

View File

@ -45,37 +45,46 @@ var
portw : tportw;
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
{ 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;
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;
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;
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;