fpc/rtl/unix/x86.pp
2023-07-27 19:04:03 +02:00

461 lines
8.8 KiB
ObjectPascal

{
This file is part of the Free Pascal run time library.
Copyright (c) 1997-2004 by the Free Pascal development team
Some x86 specific stuff. Has to be fixed still for *BSD
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.
**********************************************************************}
{$IFNDEF FPC_DOTTEDUNITS}
unit x86;
{$ENDIF FPC_DOTTEDUNITS}
interface
{$inline on}
{$IFDEF FPC_DOTTEDUNITS}
Uses UnixApi.Base;
{$ELSE FPC_DOTTEDUNITS}
Uses BaseUnix;
{$ENDIF FPC_DOTTEDUNITS}
function ReadPortB (Port : Longint): Byte;inline;
function ReadPortW (Port : Longint): Word;inline;
function ReadPortL (Port : Longint): Longint;inline;
Procedure ReadPort (Port : Longint; Var Value : Byte);inline;
Procedure ReadPort (Port : Longint; Var Value : Longint);inline;
Procedure ReadPort (Port : Longint; Var Value : Word);inline;
Procedure ReadPortB (Port : Longint; Var Buf; Count: longint);
Procedure ReadPortL (Port : Longint; Var Buf; Count: longint);
Procedure ReadPortW (Port : Longint; Var Buf; Count: longint);
Procedure WritePort (Port : Longint; Value : Byte);inline;
Procedure WritePort (Port : Longint; Value : Longint);inline;
Procedure WritePort (Port : Longint; Value : Word);inline;
Procedure WritePortB (Port : Longint; Value : Byte);inline;
Procedure WritePortB (Port : Longint; Var Buf; Count: longint);
Procedure WritePortL (Port : Longint; Value : Longint);inline;
Procedure WritePortW (Port : Longint; Value : Word);inline;
Procedure WritePortW (Port : Longint; Var Buf; Count: longint);
Procedure WritePortl (Port : Longint; Var Buf; Count: longint);
Function fpIOperm (From,Num : Cardinal; Value : cint) : cint;
Function fpIoPL(Level : cint) : cint;
implementation
{$ASMMODE ATT}
{$IFDEF FPC_DOTTEDUNITS}
Uses UnixApi.SysCall;
{$ELSE FPC_DOTTEDUNITS}
Uses Syscall;
{$ENDIF FPC_DOTTEDUNITS}
{$IFDEF cpullvm}
procedure fpc_x86_outportb(p:longint;v:byte);
begin
asm
movl %edx, p
movb v, %al
outb %al, %dx
end ['eax','edx'];
end;
procedure fpc_x86_outportw(p:longint;v:word);
begin
asm
movl %edx, p
movw v, %ax
outw %ax, %dx
end ['eax','edx'];
end;
procedure fpc_x86_outportl(p:longint;v:longint);
begin
asm
movl %edx, p
movl v, %eax
outl %eax, %dx
end ['eax','edx'];
end;
function fpc_x86_inportb(p:word):byte; assembler; nostackframe;
asm
xorl %eax, %eax
movw %dx, p
inb %dx, %al
end;
function fpc_x86_inportw(p:word):word; assembler; nostackframe;
asm
xorl %eax, %eax
movw %dx, p
inw %dx, %ax
end;
function fpc_x86_inportl(p:word):longint; assembler; nostackframe;
asm
movw %dx, p
inl %dx, %eax
end;
{$ENDIF ndef cpullvm}
Procedure WritePort (Port : Longint; Value : Byte);inline;
{
Writes 'Value' to port 'Port'
}
begin
fpc_x86_outportb(Port,Value);
end;
Procedure WritePort (Port : Longint; Value : Word);inline;
{
Writes 'Value' to port 'Port'
}
begin
fpc_x86_outportw(Port,Value);
end;
Procedure WritePort (Port : Longint; Value : Longint);inline;
{
Writes 'Value' to port 'Port'
}
begin
fpc_x86_outportl(Port,Value);
end;
Procedure WritePortB (Port : Longint; Value : Byte);inline;
{
Writes 'Value' to port 'Port'
}
begin
fpc_x86_outportb(Port,Value);
end;
Procedure WritePortW (Port : Longint; Value : Word);inline;
{
Writes 'Value' to port 'Port'
}
begin
fpc_x86_outportw(Port,Value);
end;
Procedure WritePortL (Port : Longint; Value : Longint);inline;
{
Writes 'Value' to port 'Port'
}
begin
fpc_x86_outportl(Port,Value);
end;
Procedure WritePortl (Port : Longint; Var Buf; Count: longint);
{
Writes 'Count' longints from 'Buf' to Port
}
begin
asm
{$ifdef CPU386}
movl count,%ecx
movl buf,%esi
movl port,%edx
cld
rep
outsl
{$endif CPU386}
{$ifdef CPUX86_64}
movl count,%ecx
movq buf,%rsi
movl port,%edx
cld
rep
outsl
{$endif CPUX86_64}
end;
end;
Procedure WritePortW (Port : Longint; Var Buf; Count: longint);
{
Writes 'Count' words from 'Buf' to Port
}
begin
asm
{$ifdef CPU386}
movl count,%ecx
movl buf,%esi
movl port,%edx
cld
rep
outsw
{$endif CPU386}
{$ifdef CPUX86_64}
movl count,%ecx
movq buf,%rsi
movl port,%edx
cld
rep
outsw
{$endif CPUX86_64}
end;
end;
Procedure WritePortB (Port : Longint; Var Buf; Count: longint);
{
Writes 'Count' bytes from 'Buf' to Port
}
begin
asm
{$ifdef CPU386}
movl count,%ecx
movl buf,%esi
movl port,%edx
cld
rep
outsb
{$endif CPU386}
{$ifdef CPUX86_64}
movl count,%ecx
movq buf,%rsi
movl port,%edx
cld
rep
outsb
{$endif CPUX86_64}
end;
end;
Procedure ReadPort (Port : Longint; Var Value : Byte);inline;
{
Reads 'Value' from port 'Port'
}
begin
Value:=fpc_x86_inportb(Port);
end;
Procedure ReadPort (Port : Longint; Var Value : Word);inline;
{
Reads 'Value' from port 'Port'
}
begin
Value:=fpc_x86_inportw(Port);
end;
Procedure ReadPort (Port : Longint; Var Value : Longint);inline;
{
Reads 'Value' from port 'Port'
}
begin
Value:=fpc_x86_inportl(Port);
end;
function ReadPortB (Port : Longint): Byte;inline;
{
Reads a byte from port 'Port'
}
begin
ReadPortB:=fpc_x86_inportb(Port);
end;
function ReadPortW (Port : Longint): Word;inline;
{
Reads a word from port 'Port'
}
begin
ReadPortW:=fpc_x86_inportw(Port);
end;
function ReadPortL (Port : Longint): LongInt;inline;
{
Reads a LongInt from port 'Port'
}
begin
ReadPortL:=fpc_x86_inportl(Port);
end;
Procedure ReadPortL (Port : Longint; Var Buf; Count: longint);
{
Reads 'Count' longints from port 'Port' to 'Buf'.
}
begin
asm
{$ifdef CPU386}
movl count,%ecx
movl buf,%edi
movl port,%edx
cld
rep
insl
{$endif CPU386}
{$ifdef CPUX86_64}
movl count,%ecx
movq buf,%rdi
movl port,%edx
cld
rep
insl
{$endif CPUX86_64}
end;
end;
Procedure ReadPortW (Port : Longint; Var Buf; Count: longint);
{
Reads 'Count' words from port 'Port' to 'Buf'.
}
begin
asm
{$ifdef CPU386}
movl count,%ecx
movl buf,%edi
movl port,%edx
cld
rep
insw
{$endif CPU386}
{$ifdef CPUX86_64}
movl count,%ecx
movq buf,%rdi
movl port,%edx
cld
rep
insw
{$endif CPUX86_64}
end;
end;
Procedure ReadPortB (Port : Longint; Var Buf; Count: longint);
{
Reads 'Count' bytes from port 'Port' to 'Buf'.
}
begin
asm
{$ifdef CPU386}
movl count,%ecx
movl buf,%edi
movl port,%edx
cld
rep
insb
{$endif CPU386}
{$ifdef CPUX86_64}
movl count,%ecx
movq buf,%rdi
movl port,%edx
cld
rep
insb
{$endif CPUX86_64}
end;
end;
{$if defined(linux) or defined(android)}
Function fpIOperm (From,Num : Cardinal; Value : cint) : cint;
{
Set permissions on NUM ports starting with port FROM to VALUE
this works ONLY as root.
}
begin
fpIOPerm:=do_Syscall(Syscall_nr_ioperm,TSysParam(From),TSysParam(Num),TSysParam(Value));
end;
{$else}
{$packrecords C}
TYPE uint=CARDINAL;
CONST
I386_GET_LDT =0;
I386_SET_LDT =1;
{ I386_IOPL }
I386_GET_IOPERM =3;
I386_SET_IOPERM =4;
{ xxxxx }
I386_VM86 =6;
type
{ i386_ldt_args = record
int start : longint;
union descriptor *descs;
int num;
end;
}
i386_ioperm_args = record
start : cuint;
length : cuint;
enable : cint;
end;
i386_vm86_args = record
sub_op : cint; { sub-operation to perform }
sub_args : PAnsiChar; { args }
end;
sysarch_args = record
op : longint;
parms : PAnsiChar;
end;
Function fpIOPerm(From,Num:CARDINAL;Value:cint):cint;
var sg : i386_ioperm_args;
sa : sysarch_args;
begin
sg.start:=From;
sg.length:=Num;
sg.enable:=value;
sa.op:=i386_SET_IOPERM;
sa.parms:=@sg;
fpIOPerm:=do_syscall(syscall_nr_sysarch,TSysParam(@sa));
end;
{$endif}
Function fpIoPL(Level : cint) : cint;
begin
{$ifdef Linux}
fpIOPL:=do_Syscall(Syscall_nr_iopl,TSysParam(Level));
{$else}
fpIOPL:=-1;
FpSetErrNo(ESysENoSys);
{$endif}
end;
end.