Pārlūkot izejas kodu

Merged revisions 9162-9164,9185,9211,9236-9238,9260,9262,9266,9269-9272,9276-9278,9295,9307-9308,9310,9322,9337,9340,9343-9344,9359,9373-9376,9387,9396,9399,9401-9402,9434,9450-9456,9459-9463,9466,9468-9469,9472-9473,9476-9477,9480,9482,9491-9492,9529,9536,9543,9550,9566-9568,9571,9573,9576-9577,9579,9582 via svnmerge from
http://svn.freepascal.org/svn/fpc/trunk

........
r9162 | florian | 2007-11-08 10:01:13 +0100 (Thu, 08 Nov 2007) | 1 line

* fixed breakage
........
r9163 | florian | 2007-11-08 22:03:14 +0100 (Thu, 08 Nov 2007) | 2 lines

* comment in eabi code fixed
........
r9164 | florian | 2007-11-08 22:03:46 +0100 (Thu, 08 Nov 2007) | 2 lines

* define for armel fixed
........
r9376 | sekelsenmat | 2007-12-02 09:27:18 +0100 (Sun, 02 Dec 2007) | 1 line

Small fix for symbian arm target.
........
r9482 | florian | 2007-12-16 18:36:46 +0100 (Sun, 16 Dec 2007) | 2 lines

+ gprof startup code
........
r9543 | daniel | 2007-12-27 18:59:45 +0100 (Thu, 27 Dec 2007) | 4 lines

+ Assembler implementation of mod/div.
Improves amount of divides from about 230000/s to about 2400000/s on
ARM920T, 200MHz.
........
r9582 | daniel | 2007-12-30 12:19:10 +0100 (Sun, 30 Dec 2007) | 6 lines

- Intergrate i386/strlen.inc and remove it.
+ int_str assembler implementations for i386
+ fpc_shortstr_to_shortstr assembler implementation for ARM
+ fpc_shortstr_assign assembler implementation for ARM
+ fpc_Pchar_length assembler implementation for ARM
........

git-svn-id: branches/fixes_2_2@9852 -

peter 17 gadi atpakaļ
vecāks
revīzija
5d31646493

+ 1 - 1
.gitattributes

@@ -4629,6 +4629,7 @@ rtl/amiga/timerd.inc svneol=native#text/plain
 rtl/amiga/tthread.inc svneol=native#text/plain
 rtl/amiga/varutils.pp svneol=native#text/plain
 rtl/arm/arm.inc svneol=native#text/plain
+rtl/arm/divide.inc svneol=native#text/plain
 rtl/arm/int64p.inc svneol=native#text/plain
 rtl/arm/makefile.cpu -text
 rtl/arm/math.inc svneol=native#text/plain
@@ -4863,7 +4864,6 @@ rtl/i386/setjump.inc svneol=native#text/plain
 rtl/i386/setjumph.inc svneol=native#text/plain
 rtl/i386/strings.inc svneol=native#text/plain
 rtl/i386/stringss.inc svneol=native#text/plain
-rtl/i386/strlen.inc svneol=native#text/plain
 rtl/i386/strpas.inc svneol=native#text/plain
 rtl/inc/aliases.inc svneol=native#text/plain
 rtl/inc/astrings.inc svneol=native#text/plain

+ 3 - 0
compiler/arm/cputarg.pas

@@ -53,6 +53,9 @@ implementation
     {$ifndef NOTARGETEMBEDDED}
       ,t_embedded
     {$endif}
+    {$ifndef NOTARGETSYMBIAN}
+      ,t_symbian
+    {$endif}
 
 {**************************************
              Assemblers

+ 0 - 1
compiler/options.pas

@@ -2468,7 +2468,6 @@ begin
 {$endif cpufpemu}
     end;
 
-
   { now we can defined cpu and cpu type }
   def_system_macro('CPU'+Cputypestr[init_settings.cputype]);
 

+ 63 - 1
compiler/systems/i_linux.pas

@@ -54,7 +54,7 @@ unit i_linux;
             system       : system_i386_LINUX;
             name         : 'Linux for i386';
             shortname    : 'Linux';
-            flags        : [tf_needs_symbol_size,tf_pic_uses_got{,tf_smartlink_sections},
+            flags        : [tf_needs_symbol_size,tf_pic_uses_got{,tf_smartlink_sections}{,tf_winlikewidestring},
 {$ifdef segment_threadvars}
                             tf_section_threadvars,
 {$endif segment_threadvars}
@@ -532,6 +532,67 @@ unit i_linux;
             abi : abi_default
           );
 
+{$ifdef FPC_ARMEL}
+       system_arm_linux_info : tsysteminfo =
+          (
+            system       : system_arm_Linux;
+            name         : 'Linux for ARMEL';
+            shortname    : 'Linux';
+            flags        : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
+                            tf_use_function_relative_addresses,tf_requires_proper_alignment,tf_smartlink_sections,tf_smartlink_library];
+            cpu          : cpu_arm;
+            unit_env     : 'LINUXUNITS';
+            extradefines : 'UNIX;HASUNIX';
+            exeext       : '';
+            defext       : '.def';
+            scriptext    : '.sh';
+            smartext     : '.sl';
+            unitext      : '.ppu';
+            unitlibext   : '.ppl';
+            asmext       : '.s';
+            objext       : '.o';
+            resext       : '.res';
+            resobjext    : '.or';
+            sharedlibext : '.so';
+            staticlibext : '.a';
+            staticlibprefix : 'libp';
+            sharedlibprefix : 'lib';
+            sharedClibext : '.so';
+            staticClibext : '.a';
+            staticClibprefix : 'lib';
+            sharedClibprefix : 'lib';
+            Cprefix      : '';
+            newline      : #10;
+            dirsep       : '/';
+            assem        : as_gas;
+            assemextern  : as_gas;
+            link         : nil;
+            linkextern   : nil;
+            ar           : ar_gnu_ar;
+            res          : res_none;
+            dbg          : dbg_stabs;
+            script       : script_unix;
+            endian       : endian_little;
+            alignment    :
+              (
+                procalign       : 4;
+                loopalign       : 4;
+                jumpalign       : 0;
+                constalignmin   : 0;
+                constalignmax   : 8;
+                varalignmin     : 0;
+                varalignmax     : 8;
+                localalignmin   : 4;
+                localalignmax   : 8;
+                recordalignmin  : 0;
+                recordalignmax  : 8;
+                maxCrecordalign : 8
+              );
+            first_parm_offset : 8;
+            stacksize    : 262144;
+            abi : abi_eabi
+          );
+{$else FPC_ARMEL}
        system_arm_linux_info : tsysteminfo =
           (
             system       : system_arm_Linux;
@@ -591,6 +652,7 @@ unit i_linux;
             stacksize    : 262144;
             abi : abi_default
           );
+{$endif FPC_ARMEL}
 
   implementation
 

+ 166 - 0
rtl/arm/arm.inc

@@ -307,6 +307,168 @@ end;
 
 {$endif FPC_SYSTEM_HAS_MOVE}
 
+{****************************************************************************
+                                 String
+****************************************************************************}
+
+{$ifndef FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
+{$define FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
+
+{$ifndef FPC_STRTOSHORTSTRINGPROC}
+function fpc_shortstr_to_shortstr(len:longint;const sstr:shortstring):shortstring;assembler;nostackframe;[public,alias: 'FPC_SHORTSTR_TO_SHORTSTR'];compilerproc;
+{$else}
+procedure fpc_shortstr_to_shortstr(out res:shortstring;const sstr:shortstring);assembler;nostackframe;[public,alias: 'FPC_SHORTSTR_TO_SHORTSTR'];compilerproc;
+{$endif}
+{r0: __RESULT
+ r1: len
+ r2: sstr}
+
+asm
+    ldrb r12,[r2],#1
+    cmp  r12,r1
+    movgt r1,r12
+    strb r12,[r0],#1
+    cmp  r12,#6 (* 6 seems to be the break even point. *)
+    blt  .LStartTailCopy
+    (* Align destination on 32bits. This is the only place where unrolling
+       really seems to help, since in the common case, sstr is aligned on
+       32 bits, therefore in the common case we need to copy 3 bytes to
+       align, i.e. in the case of a loop, you wouldn't branch out early.*)
+    rsb  r3,r0,#0
+    ands  r3,r3,#3
+    sub  r12,r12,r3
+    ldrneb r1,[r2],#1
+    strneb r1,[r0],#1
+    subnes  r3,r3,#1
+    ldrneb r1,[r2],#1
+    strneb r1,[r0],#1
+    subnes  r3,r3,#1
+    ldrneb r1,[r2],#1
+    strneb r1,[r0],#1
+    subnes  r3,r3,#1
+.LDoneAlign:
+    (* Destination should be aligned now, but source might not be aligned,
+       if this is the case, do a byte-per-byte copy. *)
+    tst r2,#3
+    bne .LStartTailCopy
+    (* Start the main copy, 32 bit at a time. *)
+    movs r3,r12,lsr #2
+    and r12,r12,#3
+    beq  .LStartTailCopy
+.LNext4bytes:
+    (* Unrolling this loop would save a little bit of time for long strings
+       (>20 chars), but alas, it hurts for short strings and they are the
+       common case.*)
+    ldrne r1,[r2],#4
+    strne r1,[r0],#4
+    subnes  r3,r3,#1
+    bne .LNext4bytes
+.LStartTailCopy:
+    (* Do remaining bytes. *)
+    cmp r12,#0
+    beq .LDoneTail
+.LNextChar3:
+    ldrb r1,[r2],#1
+    strb r1,[r0],#1
+    subs  r12,r12,#1
+    bne .LNextChar3
+.LDoneTail:
+end;
+
+procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer);assembler;nostackframe;[public,alias:'FPC_SHORTSTR_ASSIGN'];compilerproc;
+
+{r0: len
+ r1: sstr
+ r2: dstr}
+
+asm
+    ldrb r12,[r1],#1
+    cmp  r12,r0
+    movgt r0,r12
+    strb r12,[r2],#1
+    cmp  r12,#6 (* 6 seems to be the break even point. *)
+    blt  .LStartTailCopy
+    (* Align destination on 32bits. This is the only place where unrolling
+       really seems to help, since in the common case, sstr is aligned on
+       32 bits, therefore in the common case we need to copy 3 bytes to
+       align, i.e. in the case of a loop, you wouldn't branch out early.*)
+    rsb  r3,r2,#0
+    ands  r3,r3,#3
+    sub  r12,r12,r3
+    ldrneb r0,[r1],#1
+    strneb r0,[r2],#1
+    subnes  r3,r3,#1
+    ldrneb r0,[r1],#1
+    strneb r0,[r2],#1
+    subnes  r3,r3,#1
+    ldrneb r0,[r1],#1
+    strneb r0,[r2],#1
+    subnes  r3,r3,#1
+.LDoneAlign:
+    (* Destination should be aligned now, but source might not be aligned,
+       if this is the case, do a byte-per-byte copy. *)
+    tst r1,#3
+    bne .LStartTailCopy
+    (* Start the main copy, 32 bit at a time. *)
+    movs r3,r12,lsr #2
+    and r12,r12,#3
+    beq  .LStartTailCopy
+.LNext4bytes:
+    (* Unrolling this loop would save a little bit of time for long strings
+       (>20 chars), but alas, it hurts for short strings and they are the
+       common case.*)
+    ldrne r0,[r1],#4
+    strne r0,[r2],#4
+    subnes  r3,r3,#1
+    bne .LNext4bytes
+.LStartTailCopy:
+    (* Do remaining bytes. *)
+    cmp r12,#0
+    beq .LDoneTail
+.LNextChar3:
+    ldrb r0,[r1],#1
+    strb r0,[r2],#1
+    subs  r12,r12,#1
+    bne .LNextChar3
+.LDoneTail:
+end;
+{$endif FPC_SYSTEM_HAS_FPC_SHORTSTR_ASSIGN}
+
+{$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
+{$define FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
+function fpc_Pchar_length(p:Pchar):longint;assembler;nostackframe;[public,alias:'FPC_PCHAR_LENGTH'];compilerproc;
+
+asm
+    mov r1,r0
+.Lnextchar:
+    (*Are we aligned?*)
+    tst r1,#3
+    bne .Ltest_unaligned    (*No, do byte per byte.*)
+    ldr r3,.L01010101
+.Ltest_aligned:
+    (*Aligned, load 4 bytes at a time.*)
+    ldr r12,[r1],#4
+    (*Check wether r12 contains a 0 byte.*)
+    sub r2,r12,r3
+    mvn r12,r12
+    and r2,r2,r12
+    ands r2,r2,r3,lsl #7    (*r3 lsl 7 = $80808080*)
+    beq .Ltest_aligned      (*No 0 byte, repeat.*)
+    sub r1,r1,#4
+.Ltest_unaligned:
+    ldrb r12,[r1],#1
+    cmp r12,#1              (*r12<1 same as r12=0, but result in carry flag*)
+    bcs .Lnextchar
+    (*Dirty trick: we need to subtract 1 extra because we have counted the
+      terminating 0, due to the known carry flag sbc can do this.*)
+    sbc r0,r1,r0
+    mov pc,lr
+.L01010101:
+    .long 0x01010101
+end;
+{$endif}
+
+
 var
   fpc_system_lock: longint; export name 'fpc_system_lock';
 
@@ -436,3 +598,7 @@ begin
     moveproc:=@move_blended;
 {$endif FPC_SYSTEM_FPC_MOVE}
 end;
+
+{include hand-optimized assembler division code}
+{$i divide.inc}
+

+ 157 - 0
rtl/arm/divide.inc

@@ -0,0 +1,157 @@
+{
+ Divide/modulo for Acorn RISC Machine
+
+ ... taken from a GP2X Ogg Tremor port by Dzz and converted to
+ Pascal.
+
+ Copyright (c) 2007, Daniel Mantione
+ Copyright (c) 2006, Dzz
+ Copyright (c) 2002, Xiph.org Foundation
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in the
+  documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Xiph.org Foundation nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION
+  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+}
+
+{$ifndef FPC_SYSTEM_HAS_DIV_DWORD}
+{$define FPC_SYSTEM_HAS_DIV_DWORD}
+function fpc_div_dword(n,z:dword):dword;[public,alias: 'FPC_DIV_DWORD'];assembler;nostackframe;
+
+asm
+	mov r3, #0
+	rsbs r2, r0, r1, LSR#3
+	bcc .Ldiv_3bits
+	rsbs r2, r0, r1, LSR#8
+	bcc .Ldiv_8bits
+	mov r0, r0, LSL#8
+	orr r3, r3, #0xFF000000
+	rsbs r2, r0, r1, LSR#4
+	bcc .Ldiv_4bits
+	rsbs r2, r0, r1, LSR#8
+	bcc .Ldiv_8bits
+	mov r0, r0, LSL#8
+	orr r3, r3, #0x00FF0000
+	rsbs r2, r0, r1, LSR#8
+	movcs r0, r0, LSL#8
+	orrcs r3, r3, #0x0000FF00
+	rsbs r2, r0, r1, LSR#4
+	bcc .Ldiv_4bits
+	rsbs r2, r0, #0
+	bcs .Ldiv_by_0
+.Ldiv_loop:
+	movcs r0, r0, LSR#8
+.Ldiv_8bits:
+	rsbs r2, r0, r1, LSR#7
+	subcs r1, r1, r0, LSL#7
+	adc r3, r3, r3
+	rsbs r2, r0, r1, LSR#6
+	subcs r1, r1, r0, LSL#6
+	adc r3, r3, r3
+	rsbs r2, r0, r1, LSR#5
+	subcs r1, r1, r0, LSL#5
+	adc r3, r3, r3
+	rsbs r2, r0, r1, LSR#4
+	subcs r1, r1, r0, LSL#4
+	adc r3, r3, r3
+.Ldiv_4bits:
+	rsbs r2, r0, r1, LSR#3
+	subcs r1, r1, r0, LSL#3
+	adc r3, r3, r3
+.Ldiv_3bits:
+	rsbs r2, r0, r1, LSR#2
+	subcs r1, r1, r0, LSL#2
+	adc r3, r3, r3
+	rsbs r2, r0, r1, LSR#1
+	subcs r1, r1, r0, LSL#1
+	adc r3, r3, r3
+	rsbs r2, r0, r1
+	subcs r1, r1, r0
+	adcs r3, r3, r3
+.Ldiv_next:
+	bcs .Ldiv_loop
+	mov r0, r3
+	mov pc, lr
+.Ldiv_by_0:
+    mov r0, #200
+    mov r1, r11
+    bl handleerrorframe
+	mov pc, lr
+end;
+
+{It is a compilerproc (systemh.inc), make an alias for internal use.}
+function fpc_div_dword(n,z:dword):dword;external name 'FPC_DIV_DWORD';
+{$endif}
+
+{$ifndef FPC_SYSTEM_HAS_DIV_LONGINT}
+{$define FPC_SYSTEM_HAS_DIV_LONGINT}
+function fpc_div_longint(n,z:longint):longint;[public,alias: 'FPC_DIV_LONGINT'];assembler;nostackframe;
+
+asm
+	stmfd sp!, {lr}
+	ands r12, r0, #1<<31       (* r12:=r0 and $80000000 *)
+	rsbmi r0, r0, #0           (* if signed(r0) then r0:=0-r0 *)
+	eors r12, r12, r1, ASR#32  (* r12:=r12 xor (r1 asr 32) *)
+	rsbcs r1, r1, #0           (* if signed(r12) then r1:=0-r1 *)
+	bl fpc_div_dword
+	movs r12, r12, LSL#1       (* carry:=sign(r12) *)
+	rsbcs r0, r0, #0
+	rsbmi r1, r1, #0
+	ldmfd sp!, {pc}
+end;
+
+{It is a compilerproc (systemh.inc), make an alias for internal use.}
+function fpc_div_longint(n,z:longint):longint;external name 'FPC_DIV_LONGINT';
+{$endif}
+
+{$ifndef FPC_SYSTEM_HAS_MOD_DWORD}
+{$define FPC_SYSTEM_HAS_MOD_DWORD}
+function fpc_mod_dword(n,z:dword):dword;[public,alias: 'FPC_MOD_DWORD'];assembler;nostackframe;
+
+asm
+	stmfd sp!, {lr}
+	bl fpc_div_dword
+	mov r0, r1
+	ldmfd sp!, {pc}
+end;
+
+{It is a compilerproc (systemh.inc), make an alias for internal use.}
+function fpc_mod_dword(n,z:dword):dword;external name 'FPC_MOD_DWORD';
+{$endif}
+
+{$ifndef FPC_SYSTEM_HAS_MOD_LONGINT}
+{$define FPC_SYSTEM_HAS_MOD_LONGINT}
+function fpc_mod_longint(n,z:longint):longint;[public,alias: 'FPC_MOD_LONGINT'];assembler;nostackframe;
+
+asm
+	stmfd sp!, {lr}
+	bl fpc_div_longint
+	mov r0, r1
+	ldmfd sp!, {pc}
+end;
+
+{It is a compilerproc (systemh.inc), make an alias for internal use.}
+function fpc_mod_longint(n,z:longint):longint;external name 'FPC_MOD_LONGINT';
+{$endif}

+ 91 - 1
rtl/i386/i386.inc

@@ -1013,7 +1013,25 @@ end;
 {$ifndef FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
 {$define FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
 function fpc_pchar_length(p:pchar):longint;assembler;[public,alias:'FPC_PCHAR_LENGTH']; compilerproc;
-{$include strlen.inc}
+
+var
+  saveedi : longint;
+asm
+        movl    %edi,saveedi
+{$ifdef REGCALL}
+        movl    %eax,%edi
+{$else}
+        movl    p,%edi
+{$endif}
+        movl    $0xffffffff,%ecx
+        xorl    %eax,%eax
+        cld
+        repne
+        scasb
+        movl    $0xfffffffe,%eax
+        subl    %ecx,%eax
+        movl    saveedi,%edi
+end;
 {$endif FPC_SYSTEM_HAS_FPC_PCHAR_LENGTH}
 
 {$IFNDEF INTERNAL_BACKTRACE}
@@ -1085,7 +1103,79 @@ Function Sptr : Pointer;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$end
 asm
         movl    %esp,%eax
 end;
+{****************************************************************************
+                                 Str()
+****************************************************************************}
+
+{$define FPC_SYSTEM_HAS_INT_STR_LONGWORD}
+{$define FPC_SYSTEM_HAS_INT_STR_LONGINT}
+
+label str_int_shortcut;
+
+{$asmmode intel}
+
+procedure int_str(l:longword;var s:string);assembler;nostackframe;
+
+asm
+  push edi
+  push ebx
+  mov edi,edx
+  xor edx,edx
+  jmp str_int_shortcut
+end;
+
+procedure int_str(l:longint;var s:string);assembler;nostackframe;
+
+{Optimized for speed, but balanced with size.}
+
+const digits:array[0..9] of cardinal=(0,10,100,1000,10000,
+                                      100000,1000000,10000000,
+                                      100000000,1000000000);
+
+asm
+  push edi
+  push ebx
+  mov edi,edx
+
+  { Calculate absolute value and put sign in edx}
+  cdq
+  xor eax,edx
+  sub eax,edx
+  neg edx
+str_int_shortcut:
+  {Calculate amount of digits in ecx.}
+  bsr ecx,eax
+  inc ecx
+  imul ecx,1233
+  shr ecx,12
+  cmp eax,[digits+4*ecx]
+  cmc
+  adc ecx,0 {Nr. digits ready in ecx.}
+
+  {Write length & sign.}
+  lea ebx,[edx+ecx]
+  mov bh,'-'
+  mov [edi],bx
+  add edi,edx
+
+  {Write out digits.}
+  mov edx,eax
+@loop:
+  mov eax,$cccccccd    {Divide by 10 using mul+shr}
+  lea ebx,[edx+'0']    {Pre-add '0'}
+  mul edx
+  shr edx,3
+  lea eax,[8*edx+edx]  {x mod 10 = x-10*(x div 10)}
+  sub ebx,edx
+  sub ebx,eax
+  mov [edi+ecx],bl
+  dec ecx
+  jnz @loop
+  pop ebx
+  pop edi
+end;
 
+{$asmmode att}
 
 {****************************************************************************
                                Bounds Check

+ 0 - 35
rtl/i386/strlen.inc

@@ -1,35 +0,0 @@
-{
-    This file is part of the Free Pascal run time library.
-    Copyright (c) 1999-2000 by the Free Pascal development team
-
-    Processor specific implementation of strlen
-
-    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.
-
- **********************************************************************}
-
-var
-  saveedi : longint;
-asm
-        movl    %edi,saveedi
-{$ifdef REGCALL}
-        movl    %eax,%edi
-{$else}
-        movl    p,%edi
-{$endif}
-        movl    $0xffffffff,%ecx
-        xorl    %eax,%eax
-        cld
-        repne
-        scasb
-        movl    $0xfffffffe,%eax
-        subl    %ecx,%eax
-        movl    saveedi,%edi
-end;
-
-

+ 92 - 0
rtl/linux/arm/gprt0.as

@@ -0,0 +1,92 @@
+/*
+                At this entry point, most registers' values are unspecified, except:
+
+   a1		Contains a function pointer to be registered with `atexit'.
+		This is how the dynamic linker arranges to have DT_FINI
+		functions called for shared libraries that have been loaded
+		before this code runs.
+
+   sp		The stack contains the arguments and environment:
+		0(sp)			argc
+		4(sp)			argv[0]
+		...
+		(4*argc)(sp)		NULL
+		(4*(argc+1))(sp)	envp[0]
+		...
+					NULL
+*/
+
+	.text
+	.globl _start
+	.type _start,#function
+_start:
+	/* Clear the frame pointer since this is the outermost frame.  */
+	mov fp, #0
+	ldmia   sp!, {a2}
+
+	/* Pop argc off the stack and save a pointer to argv */
+	ldr ip,=operatingsystem_parameter_argc
+	ldr a3,=operatingsystem_parameter_argv
+	str a2,[ip]
+
+	/* calc envp */
+	add a2,a2,#1
+	add a2,sp,a2,LSL #2
+	ldr ip,=operatingsystem_parameter_envp
+
+	str sp,[a3]
+   	str a2,[ip]
+
+        ldr     r1,=_etext                 /* Initialize gmon */
+        ldr     r0,=_start
+        bl      monstartup
+        ldr     r0,=_mcleanup
+        bl      atexit
+
+        /* Save initial stackpointer */
+	ldr ip,=__stkptr
+	str sp,[ip]
+
+	/* Let the libc call main and exit with its return code.  */
+	bl PASCALMAIN
+
+	.globl  _haltproc
+    .type   _haltproc,#function
+_haltproc:
+        /* r0 contains exitcode */
+	swi 0x900001
+	b _haltproc
+
+	/* Define a symbol for the first piece of initialized data.  */
+	.data
+	.globl __data_start
+__data_start:
+	.long 0
+	.weak data_start
+	data_start = __data_start
+
+.bss
+        .comm __stkptr,4
+
+        .comm operatingsystem_parameter_envp,4
+        .comm operatingsystem_parameter_argc,4
+        .comm operatingsystem_parameter_argv,4
+
+	.section ".comment"
+	.byte 0
+	.ascii "generated by FPC http://www.freepascal.org\0"
+
+/* We need this stuff to make gdb behave itself, otherwise
+   gdb will chokes with SIGILL when trying to debug apps.
+*/
+        .section ".note.ABI-tag", "a"
+        .align 4
+        .long 1f - 0f
+        .long 3f - 2f
+        .long  1
+0:      .asciz "GNU"
+1:      .align 4
+2:      .long 0
+        .long 2,0,0
+3:      .align 4
+

+ 25 - 0
rtl/linux/arm/syscall.inc

@@ -22,6 +22,30 @@
                      --- Main:The System Call Self ---
 *****************************************************************************}
 
+{$ifdef FPC_ABI_EABI}
+function FpSysCall(sysnr:TSysParam):TSysResult; assembler; nostackframe; [public,alias:'FPC_SYSCALL0'];
+{
+  Perform syscall and set errno variable if needed.
+}
+asm
+  // for now we are lazy
+  mov   r7,r0
+  mov   r0,r1
+  mov   r1,r2
+  mov   r2,r3
+  mov   r3,r4
+  mov   r4,r5
+  mov   r5,r6
+  swi   #0x0
+  cmn   r0,#126
+  movls pc,lr
+  stmfd sp!,{lr}
+  rsb   r0,r0,#0
+  bl    seterrno
+  mvn   r0,#0
+  ldmfd sp!,{pc}
+end;
+{$else FPC_ABI_EABI}
 function FpSysCall(sysnr:TSysParam):TSysResult; assembler; nostackframe; [public,alias:'FPC_SYSCALL0'];
 {
   Perform syscall and set errno variable if needed.
@@ -36,6 +60,7 @@ asm
   mvn   r0,#0
   ldmfd sp!,{pc}
 end;
+{$endif FPC_ABI_EABI}
 
 
 procedure FPC_SYSCALL; external name 'FPC_SYSCALL0';

+ 13 - 8
rtl/linux/ossysc.inc

@@ -46,10 +46,12 @@ begin
 {$if defined(cpu64)}
   result:=do_syscall(syscall_nr_lseek,tsysparam(fd),tsysparam(offset),tsysparam(whence));
 {$else}
-  if do_syscall(syscall_nr__llseek,tsysparam(fd),tsysparam(hi(offset)),tsysparam(lo(offset)),
+  if do_syscall(syscall_nr__llseek,tsysparam(fd),
+      {$ifdef FPC_ABI_EABI}      0,  { align parameters as required with dummy } {$endif FPC_ABI_EABI}
+      tsysparam(hi(offset)),tsysparam(lo(offset)),
       tsysparam(@result), tsysparam(whence)) = -1 then
     result:=off_t(-1);
-{$endif}    
+{$endif}
 end;
 
 function Fpread(fd: cint; buf: pchar; nbytes : size_t): ssize_t; [public, alias : 'FPC_SYSC_READ'];
@@ -65,13 +67,13 @@ begin
 end;
 {
 function Fppread(fd: cint; buf: pchar; nbytes : size_t; offset:Toff): ssize_t; [public, alias : 'FPC_SYSC_PREAD'];
-   !! check 64 bit off_t sycall 
+   !! check 64 bit off_t sycall
 begin
   Fpread:=do_syscall(syscall_nr_pread,Fd,TSysParam(buf),nbytes,offset);
 end;
 
 function Fppwrite(fd: cint;buf:pchar; nbytes : size_t; offset:Toff): ssize_t; [public, alias : 'FPC_SYSC_PWRITE'];
-   !! check 64 bit off_t sycall 
+   !! check 64 bit off_t sycall
 begin
  Fpwrite:=do_syscall(syscall_nr_pwrite,Fd,TSysParam(buf),nbytes,offset);
 end;
@@ -95,7 +97,7 @@ begin
   Fpstat:=do_syscall(syscall_nr_stat,TSysParam(path),TSysParam(@buf));
 {$else}
   Fpstat:=do_syscall(syscall_nr_stat64,TSysParam(path),TSysParam(@buf));
-{$endif}  
+{$endif}
 end;
 
 {*****************************************************************************
@@ -302,9 +304,12 @@ begin
 {$if defined(cpu64)}
  Fpftruncate:=Do_syscall(syscall_nr_ftruncate,TSysParam(fd),TSysParam(flength));
 {$else}
- Fpftruncate:=Do_syscall(syscall_nr_ftruncate64,TSysParam(fd),TSysParam(lo(flength)),
-  TSysParam(hi(flength)));
-{$endif} 
+ Fpftruncate:=Do_syscall(syscall_nr_ftruncate64,TSysParam(fd),
+   {$ifdef FPC_ABI_EABI}      0,  { align parameters as required with dummy } {$endif FPC_ABI_EABI}
+   {$ifdef FPC_BIG_ENDIAN}    tsysparam(hi(flength)),tsysparam(lo(flength)){$endif}
+   {$ifdef FPC_LITTLE_ENDIAN} tsysparam(lo(flength)),tsysparam(hi(flength)){$endif}
+   );
+{$endif}
 end;
 
 function Fpfstat(fd : cint; var sb : stat): cint;  [public, alias : 'FPC_SYSC_FSTAT'];