fpc/rtl/linux/i386/syscall.inc
2010-08-15 09:11:06 +00:00

510 lines
12 KiB
PHP

{
This file is part of the Free Pascal run time library.
Copyright (c) 1999-2000 by Michael Van Canneyt,
member of the Free Pascal development team.
The syscalls for the new RTL, moved to platform dependant dir.
Old linux calling convention is still kept.
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.
**********************************************************************}
{$ASMMODE ATT}
{*************************SYSENTER CODE********************************}
{ included by system.pp in linux rtl }
const
AT_NULL = 0;
{* Pointer to the global system page used for system calls and other
nice things. *}
AT_SYSINFO = 32;
AT_SYSINFO_EHDR = 33;
type
TAuxiliaryValue = cuInt32;
TInternalUnion = record
a_val: cuint32; //* Integer value */
{* We use to have pointer elements added here. We cannot do that,
though, since it does not work when using 32-bit definitions
on 64-bit platforms and vice versa. *}
end;
Elf32_auxv_t = record
a_type: cuint32; //* Entry type */
a_un: TInternalUnion;
end;
TElf32AuxiliaryVector = Elf32_auxv_t;
PElf32AuxiliaryVector = ^TElf32AuxiliaryVector;
var
psysinfo: LongWord = 0;
procedure InitSyscallIntf;
var
ep: PPChar;
auxv: PElf32AuxiliaryVector;
begin
psysinfo := 0;
ep := envp;
while ep^ <> nil do
Inc(ep);
Inc(ep);
auxv := PElf32AuxiliaryVector(ep);
repeat
if auxv^.a_type = AT_SYSINFO then begin
psysinfo := auxv^.a_un.a_val;
if psysinfo <> 0 then
sysenter_supported := 1; // descision factor in asm syscall routines
Break;
end;
Inc(auxv);
until auxv^.a_type = AT_NULL;
end;
{***********************SYSENTER CODE END******************************}
Procedure fpc_geteipasebx;[external name 'fpc_geteipasebx'];
{$ifdef FPC_PROFILE}
procedure mcount; external name 'mcount';
{$endif FPC_PROFILE}
function FpSysCall(sysnr:TSysParam):TSysResult; assembler; register; [public,alias:'FPC_SYSCALL0'];
{ Var sysnr located in register eax }
asm
{$ifdef FPC_PROFILE}
push %eax
call mcount
pop %eax
{$endif FPC_PROFILE}
push %ebx
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
{$endif FPC_PIC}
jne .LSysEnter
int $0x80
jmp .LTail
.LSysEnter:
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl (%ecx),%ecx
call *%ecx
{$else FPC_PIC}
call psysinfo
{$endif FPC_PIC}
.LTail:
pop %ecx
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax
call seterrno
movl $-1,%eax
.LSyscOK:
end;
function FpSysCall(sysnr,param1 : TSysParam):TSysResult; assembler; register; [public,alias:'FPC_SYSCALL1'];
{ Var sysnr located in register eax
Var param1 located in register edx }
asm
{$ifdef FPC_PROFILE}
push %eax
push %edx
call mcount
pop %edx
pop %eax
{$endif FPC_PROFILE}
push %ebx
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
{$endif FPC_PIC}
jne .LSysEnter
movl %edx,%ebx // param1
int $0x80
jmp .LTail
.LSysEnter:
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl (%ecx),%ecx
movl %edx,%ebx // param1
call *%ecx
{$else FPC_PIC}
movl %edx,%ebx // param1
call psysinfo
{$endif FPC_PIC}
.LTail:
pop %ecx
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax
call seterrno
movl $-1,%eax
.LSyscOK:
end;
function FpSysCall(sysnr,param1,param2 : TSysParam):TSysResult; assembler; register; [public,alias:'FPC_SYSCALL2'];
{ Var sysnr located in register eax
Var param1 located in register edx
Var param2 located in register ecx }
asm
{$ifdef FPC_PROFILE}
push %eax
push %edx
push %ecx
call mcount
pop %ecx
pop %edx
pop %eax
{$endif FPC_PROFILE}
push %ebx
push %edx
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
{$endif FPC_PIC}
jne .LSysEnter
movl %edx,%ebx // param1
pop %ecx // param2
int $0x80
jmp .LTail
.LSysEnter:
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl %edx,%ebx // param1
movl (%ecx),%edx
pop %ecx // param2
call *%edx
{$else FPC_PIC}
movl %edx,%ebx // param1
pop %ecx // param2
call psysinfo
{$endif FPC_PIC}
.LTail:
pop %edx
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax
call seterrno
movl $-1,%eax
.LSyscOK:
end;
function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; assembler; register; [public,alias:'FPC_SYSCALL3'];
{ Var sysnr located in register eax
Var param1 located in register edx
Var param2 located in register ecx
Var param3 located at ebp+20 }
var
_psysinfo: LongWord;
asm
{$ifdef FPC_PROFILE}
push %eax
push %edx
push %ecx
call mcount
pop %ecx
pop %edx
pop %eax
{$endif FPC_PROFILE}
push %ebx
push %edx
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
{$endif FPC_PIC}
jne .LSysEnter
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
int $0x80
jmp .LTail
.LSysEnter:
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl (%ecx),%ecx
movl %ecx,_psysinfo
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
call _psysinfo
{$else FPC_PIC}
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
call psysinfo
{$endif FPC_PIC}
.LTail:
pop %edx
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax
call seterrno
movl $-1,%eax
.LSyscOK:
end;
function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; assembler; register; [public,alias:'FPC_SYSCALL4'];
{ Var sysnr located in register eax
Var param1 located in register edx
Var param2 located in register ecx
Var param3 located at ebp+20
Var param4 located at ebp+16 }
var
_psysinfo: LongWord;
asm
{$ifdef FPC_PROFILE}
push %eax
push %edx
push %ecx
call mcount
pop %ecx
pop %edx
pop %eax
{$endif FPC_PROFILE}
push %ebx
push %esi
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
{$endif FPC_PIC}
jne .LSysEnter
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
int $0x80
jmp .LTail
.LSysEnter:
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl (%ecx),%ecx
movl %ecx,_psysinfo
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
call _psysinfo
{$else FPC_PIC}
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
call psysinfo
{$endif FPC_PIC}
.LTail:
pop %esi
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax
call seterrno
movl $-1,%eax
.LSyscOK:
end;
function FpSysCall(sysnr,param1,param2,param3,param4,param5 : TSysParam):TSysResult; assembler; register; [public,alias:'FPC_SYSCALL5'];
{ Var sysnr located in register eax
Var param1 located in register edx
Var param2 located in register ecx
Var param3 located at ebp+20
Var param4 located at ebp+16
Var param5 located at ebp+12 }
var
_psysinfo: LongWord;
asm
{$ifdef FPC_PROFILE}
push %eax
push %edx
push %ecx
call mcount
pop %ecx
pop %edx
pop %eax
{$endif FPC_PROFILE}
push %ebx
push %edx
push %esi
push %edi
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
{$endif FPC_PIC}
jne .LSysEnter
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
movl param5,%edi // param5
int $0x80
jmp .LTail
.LSysEnter:
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl (%ecx),%ecx
movl %ecx,_psysinfo
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
movl param5,%edi // param5
call _psysinfo
{$else FPC_PIC}
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
movl param5,%edi // param5
call psysinfo
{$endif FPC_PIC}
.LTail:
pop %edi
pop %esi
pop %edx
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax
call seterrno
movl $-1,%eax
.LSyscOK:
end;
function FpSysCall(sysnr,param1,param2,param3,param4,param5,param6: TSysParam):TSysResult; assembler; register; [public,alias:'FPC_SYSCALL6'];
{ Var sysnr located in register eax
Var param1 located in register edx
Var param2 located in register ecx
Var param3 located at ebp+20
Var param4 located at ebp+16
Var param5 located at ebp+12
Var param6 located at ebp+8 }
var
_psysinfo: LongWord;
asm
{$ifdef FPC_PROFILE}
push %eax
push %edx
push %ecx
call mcount
pop %ecx
pop %edx
pop %eax
{$endif FPC_PROFILE}
push %ebx
push %edx
push %esi
push %edi
push %ebp
push %ecx
{$ifdef FPC_PIC}
call fpc_geteipasebx
addl $_GLOBAL_OFFSET_TABLE_,%ebx
movl sysenter_supported@GOT(%ebx),%ecx
movl (%ecx),%ecx
cmp $0, %ecx
{$else FPC_PIC}
cmp $0, sysenter_supported
{$endif FPC_PIC}
jne .LSysEnter
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
movl param5,%edi // param5
movl param6,%ebp // param6
int $0x80
jmp .LTail
.LSysEnter:
{$ifdef FPC_PIC}
movl psysinfo@GOT(%ebx),%ecx
movl (%ecx),%ecx
movl %ecx,_psysinfo
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
movl param5,%edi // param5
movl param6,%ebp // param6
call _psysinfo
{$else FPC_PIC}
movl %edx,%ebx // param1
pop %ecx // param2
movl param3,%edx // param3
movl param4,%esi // param4
movl param5,%edi // param5
movl param6,%ebp // param6
call psysinfo
{$endif FPC_PIC}
.LTail:
pop %ebp
pop %edi
pop %esi
pop %edx
pop %ebx
cmpl $-4095,%eax
jb .LSyscOK
negl %eax
call seterrno
movl $-1,%eax
.LSyscOK:
end;
{No debugging for syslinux include !}
{$IFDEF SYS_LINUX}
{$UNDEF SYSCALL_DEBUG}
{$ENDIF SYS_LINUX}