mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-12 23:29:31 +02:00
337 lines
6.9 KiB
PHP
337 lines
6.9 KiB
PHP
{
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 2001 by Free Pascal development team
|
|
|
|
This file implements all the base types and limits required
|
|
for a minimal POSIX compliant subset required to port the compiler
|
|
to a new OS.
|
|
|
|
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.
|
|
|
|
**********************************************************************}
|
|
|
|
const
|
|
carryflag = 1;
|
|
|
|
type
|
|
tseginfo=packed record
|
|
offset : pointer;
|
|
segment : word;
|
|
end;
|
|
|
|
var
|
|
old_int00 : tseginfo;cvar;
|
|
old_int75 : tseginfo;cvar;
|
|
|
|
{$asmmode ATT}
|
|
|
|
{*****************************************************************************
|
|
Go32 Helpers
|
|
*****************************************************************************}
|
|
|
|
function far_strlen(selector : word;linear_address : longint) : longint;assembler;
|
|
asm
|
|
movl linear_address,%edx
|
|
movl %edx,%ecx
|
|
pushl %gs
|
|
movw selector,%gs
|
|
.Larg19:
|
|
movb %gs:(%edx),%al
|
|
testb %al,%al
|
|
je .Larg20
|
|
incl %edx
|
|
jmp .Larg19
|
|
.Larg20:
|
|
popl %gs
|
|
movl %edx,%eax
|
|
subl %ecx,%eax
|
|
end;
|
|
|
|
|
|
function tb : longint;
|
|
begin
|
|
tb:=go32_info_block.linear_address_of_transfer_buffer;
|
|
end;
|
|
|
|
|
|
function tb_segment : longint;
|
|
begin
|
|
tb_segment:=go32_info_block.linear_address_of_transfer_buffer shr 4;
|
|
end;
|
|
|
|
|
|
function tb_offset : longint;
|
|
begin
|
|
tb_offset:=go32_info_block.linear_address_of_transfer_buffer and $f;
|
|
end;
|
|
|
|
|
|
function tb_size : longint;
|
|
begin
|
|
tb_size:=go32_info_block.size_of_transfer_buffer;
|
|
end;
|
|
|
|
|
|
function dos_selector : word;
|
|
begin
|
|
dos_selector:=go32_info_block.selector_for_linear_memory;
|
|
end;
|
|
|
|
|
|
function get_ds : word;assembler;
|
|
asm
|
|
movw %ds,%ax
|
|
end;
|
|
|
|
|
|
function get_cs : word;assembler;
|
|
asm
|
|
movw %cs,%ax
|
|
end;
|
|
|
|
|
|
procedure sysseg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
|
|
begin
|
|
if count=0 then
|
|
exit;
|
|
if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
|
|
asm
|
|
pushl %esi
|
|
pushl %edi
|
|
pushw %es
|
|
pushw %ds
|
|
cld
|
|
movl count,%ecx
|
|
movl source,%esi
|
|
movl dest,%edi
|
|
movw dseg,%ax
|
|
movw %ax,%es
|
|
movw sseg,%ax
|
|
movw %ax,%ds
|
|
movl %ecx,%eax
|
|
shrl $2,%ecx
|
|
rep
|
|
movsl
|
|
movl %eax,%ecx
|
|
andl $3,%ecx
|
|
rep
|
|
movsb
|
|
popw %ds
|
|
popw %es
|
|
popl %edi
|
|
popl %esi
|
|
end
|
|
else if (source<dest) then
|
|
{ copy backward for overlapping }
|
|
asm
|
|
pushl %esi
|
|
pushl %edi
|
|
pushw %es
|
|
pushw %ds
|
|
std
|
|
movl count,%ecx
|
|
movl source,%esi
|
|
movl dest,%edi
|
|
movw dseg,%ax
|
|
movw %ax,%es
|
|
movw sseg,%ax
|
|
movw %ax,%ds
|
|
addl %ecx,%esi
|
|
addl %ecx,%edi
|
|
movl %ecx,%eax
|
|
andl $3,%ecx
|
|
orl %ecx,%ecx
|
|
jz .LSEG_MOVE1
|
|
|
|
{ calculate esi and edi}
|
|
decl %esi
|
|
decl %edi
|
|
rep
|
|
movsb
|
|
incl %esi
|
|
incl %edi
|
|
.LSEG_MOVE1:
|
|
subl $4,%esi
|
|
subl $4,%edi
|
|
movl %eax,%ecx
|
|
shrl $2,%ecx
|
|
rep
|
|
movsl
|
|
cld
|
|
popw %ds
|
|
popw %es
|
|
popl %edi
|
|
popl %esi
|
|
end;
|
|
end;
|
|
|
|
|
|
function strcopy(dest,source : PAnsiChar) : PAnsiChar;assembler;
|
|
var
|
|
saveeax,saveesi,saveedi : longint;
|
|
asm
|
|
movl %edi,saveedi
|
|
movl %esi,saveesi
|
|
{$ifdef REGCALL}
|
|
movl %eax,saveeax
|
|
movl %edx,%edi
|
|
{$else}
|
|
movl source,%edi
|
|
{$endif}
|
|
testl %edi,%edi
|
|
jz .LStrCopyDone
|
|
leal 3(%edi),%ecx
|
|
andl $-4,%ecx
|
|
movl %edi,%esi
|
|
subl %edi,%ecx
|
|
{$ifdef REGCALL}
|
|
movl %eax,%edi
|
|
{$else}
|
|
movl dest,%edi
|
|
{$endif}
|
|
jz .LStrCopyAligned
|
|
.LStrCopyAlignLoop:
|
|
movb (%esi),%al
|
|
incl %edi
|
|
incl %esi
|
|
testb %al,%al
|
|
movb %al,-1(%edi)
|
|
jz .LStrCopyDone
|
|
decl %ecx
|
|
jnz .LStrCopyAlignLoop
|
|
.balign 16
|
|
.LStrCopyAligned:
|
|
movl (%esi),%eax
|
|
movl %eax,%edx
|
|
leal 0x0fefefeff(%eax),%ecx
|
|
notl %edx
|
|
addl $4,%esi
|
|
andl %edx,%ecx
|
|
andl $0x080808080,%ecx
|
|
jnz .LStrCopyEndFound
|
|
movl %eax,(%edi)
|
|
addl $4,%edi
|
|
jmp .LStrCopyAligned
|
|
.LStrCopyEndFound:
|
|
testl $0x0ff,%eax
|
|
jz .LStrCopyByte
|
|
testl $0x0ff00,%eax
|
|
jz .LStrCopyWord
|
|
testl $0x0ff0000,%eax
|
|
jz .LStrCopy3Bytes
|
|
movl %eax,(%edi)
|
|
jmp .LStrCopyDone
|
|
.LStrCopy3Bytes:
|
|
xorb %dl,%dl
|
|
movw %ax,(%edi)
|
|
movb %dl,2(%edi)
|
|
jmp .LStrCopyDone
|
|
.LStrCopyWord:
|
|
movw %ax,(%edi)
|
|
jmp .LStrCopyDone
|
|
.LStrCopyByte:
|
|
movb %al,(%edi)
|
|
.LStrCopyDone:
|
|
{$ifdef REGCALL}
|
|
movl saveeax,%eax
|
|
{$else}
|
|
movl dest,%eax
|
|
{$endif}
|
|
movl saveedi,%edi
|
|
movl saveesi,%esi
|
|
end;
|
|
|
|
|
|
procedure syscopytodos(addr : longint; len : longint);
|
|
begin
|
|
if len > tb_size then
|
|
HandleError(217);
|
|
sysseg_move(get_ds,addr,dos_selector,tb,len);
|
|
end;
|
|
|
|
|
|
procedure syscopyfromdos(addr : longint; len : longint);
|
|
begin
|
|
if len > tb_size then
|
|
HandleError(217);
|
|
sysseg_move(dos_selector,tb,get_ds,addr,len);
|
|
end;
|
|
|
|
|
|
procedure sysrealintr(intnr : word;var regs : trealregs);
|
|
begin
|
|
regs.realsp:=0;
|
|
regs.realss:=0;
|
|
regs.realres:=0; { spec says so, play it safe }
|
|
asm
|
|
pushl %ebx
|
|
pushl %edi
|
|
pushl %fs // Go32.RealIntr does it too (NTVDM bug),
|
|
// "pushl" to avoid size prefix
|
|
movw intnr,%bx
|
|
xorl %ecx,%ecx
|
|
movl regs,%edi
|
|
movw $0x300,%ax
|
|
int $0x31
|
|
popl %fs
|
|
popl %edi
|
|
popl %ebx
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure set_pm_interrupt(vector : byte;const intaddr : tseginfo);
|
|
begin
|
|
asm
|
|
pushl %ebx
|
|
movl intaddr,%eax
|
|
movl (%eax),%edx
|
|
movw 4(%eax),%cx
|
|
movl $0x205,%eax
|
|
movb vector,%bl
|
|
int $0x31
|
|
popl %ebx
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure get_pm_interrupt(vector : byte;var intaddr : tseginfo);
|
|
begin
|
|
asm
|
|
pushl %ebx
|
|
movb vector,%bl
|
|
movl $0x204,%eax
|
|
int $0x31
|
|
movl intaddr,%eax
|
|
movl %edx,(%eax)
|
|
movw %cx,4(%eax)
|
|
popl %ebx
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure getinoutres(def : word);
|
|
var
|
|
regs : trealregs;
|
|
begin
|
|
regs.realeax:=$5900;
|
|
regs.realebx:=$0;
|
|
sysrealintr($21,regs);
|
|
InOutRes:=lo(regs.realeax);
|
|
case InOutRes of
|
|
19 : InOutRes:=150;
|
|
21 : InOutRes:=152;
|
|
32 : InOutRes:=5;
|
|
end;
|
|
if InOutRes=0 then
|
|
InOutRes:=Def;
|
|
end;
|
|
|
|
|
|
|