mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2026-01-07 13:00:39 +01:00
+ 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:
parent
b8ae9f5d6d
commit
fdc896ad0a
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
||||
@ -164,6 +164,10 @@ type
|
||||
|
||||
{ SSE }
|
||||
|
||||
{$if defined(X86)}
|
||||
,
|
||||
{$i x86/cx86innr.inc}
|
||||
{$endif }
|
||||
{$if defined(AVR)}
|
||||
,
|
||||
{$i ccpuinnr.inc}
|
||||
|
||||
@ -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
20
compiler/x86/cx86innr.inc
Normal 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
|
||||
@ -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));
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user