Browse Source

add loongarch64 linux rtl support

Jinyang He 2 years ago
parent
commit
92e60d2107

+ 1 - 1
compiler/systems.pas

@@ -383,7 +383,7 @@ interface
        { all systems that support indirect entry information }
        { all systems that support indirect entry information }
        systems_indirect_entry_information = systems_darwin+
        systems_indirect_entry_information = systems_darwin+
                                             [system_i386_win32,system_x86_64_win64,system_x86_64_linux,
                                             [system_i386_win32,system_x86_64_win64,system_x86_64_linux,
-                                            system_aarch64_win64];
+                                            system_aarch64_win64,system_loongarch64_linux];
 
 
        { all systems for which weak linking has been tested/is supported }
        { all systems for which weak linking has been tested/is supported }
        systems_weak_linking = systems_darwin + systems_solaris + systems_linux + systems_android + systems_bsd +
        systems_weak_linking = systems_darwin + systems_solaris + systems_linux + systems_android + systems_bsd +

+ 5 - 0
rtl/linux/Makefile.fpc

@@ -138,6 +138,11 @@ override LOADERS=
 SYSINIT_UNITS=si_prc si_dll si_c
 SYSINIT_UNITS=si_prc si_dll si_c
 endif
 endif
 
 
+ifeq ($(ARCH),loongarch64)
+override LOADERS=
+SYSINIT_UNITS=si_prc si_dll si_c si_g
+endif
+
 SYSTEMUNIT=system
 SYSTEMUNIT=system
 
 
 # Causes release PPU files not to be recompiled
 # Causes release PPU files not to be recompiled

+ 1 - 0
rtl/linux/loongarch64/bsyscall.inc

@@ -0,0 +1 @@
+{ nothing }

+ 167 - 0
rtl/linux/loongarch64/si_c.inc

@@ -0,0 +1,167 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (C) 2022 Loongson Technology Corporation Limited.
+
+    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.
+
+ **********************************************************************}
+
+{******************************************************************************
+                          Process start/halt
+ ******************************************************************************}
+
+{
+The entry point's job is to call __libc_start_main.  Per the ABI,
+a0 contains the address of a function to be passed to atexit.
+__libc_start_main wants this in a5.
+
+int __libc_start_main (
+  int (*main) (int, char **, char **),
+  int argc,
+  char **argv,
+  __typeof (main) init,
+  void (*fini) (void),
+  void (*rtld_fini) (void),
+  void *stack_end);
+}
+
+var
+  libc_environ: pchar; external name '__environ';
+  libc_fpu_control: word; external name '__fpu_control';
+  libc_init_proc: procedure; external name '_init';
+  libc_fini_proc: procedure; external name '_fini';
+  _etext: pointer; external name '_etext';
+
+  fpc_ret_ra,fpc_ret_sp : pointer;
+
+procedure libc_atexit; external name 'atexit';
+procedure libc_exit; external name '__libc_exit';
+procedure libc_init; external name '__libc_init';
+procedure libc_setfpucw; external name '__setfpucw';
+procedure libc_start_main; external name '__libc_start_main';
+
+procedure _FPC_libc_haltproc(e:longint); forward;
+
+procedure ___libc_csu_init; external name '__libc_csu_init';
+{$if FPC_FULLVERSION>30202}
+procedure __libc_csu_init; public name '__libc_csu_init'; assembler; nostackframe;
+  asm
+    .weak __libc_csu_init
+  end;
+{$endif}
+
+procedure ___libc_csu_fini; external name '__libc_csu_fini';
+{$if FPC_FULLVERSION>30202}
+procedure __libc_csu_fini; public name '__libc_csu_fini'; assembler; nostackframe;
+  asm
+    .weak __libc_csu_fini
+  end;
+{$endif}
+
+procedure main_stub; assembler; nostackframe;
+  asm
+    { let fp = sp in case of no fp value }
+    ori $fp, $sp, 0
+
+    { save ra and sp }
+    la.pcrel $t0, fpc_ret_ra
+    st.d $ra, $t0, 0
+    la.pcrel $t1, fpc_ret_sp
+    st.d $sp, $t1, 0
+
+{$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
+    la.got, $t0, SysInitEntryInformation
+    st.d $sp, $t0, TEntryInformation.OS.stkptr
+    la.got $t1, StackLength
+    st.d $t1, $t0, TEntryInformation.OS.stklen
+    la.got $t2, _FPC_libc_haltproc
+    st.d $t2, $t0, TEntryInformation.OS.haltproc
+    move $a0, $t0
+    bl %plt(SysEntry)
+{$else}
+    { save stack pointer }
+    la.got $t1, initialstkptr
+    st.d $sp, $t1, 0
+
+    { call PascalMain }
+    bl %plt(PASCALMAIN)
+{$endif}
+    break 1
+  end;
+
+procedure ini_dummy;
+  begin
+  end;
+
+{******************************************************************************
+                          C library start/halt
+ ******************************************************************************}
+
+procedure _FPC_libc_start; assembler; nostackframe; public name '_start';
+  asm
+    { clear frame pointer }
+    ori $fp, $zero, 0
+
+{$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
+    la.got $t1, SysInitEntryInformation
+
+    { argc = *(int *)sp }
+    ld.w $a1, $sp, 0
+    st.w $a1, $t1, TEntryInformation.OS.argc
+
+    { argv = (char **)(sp + 8) }
+    addi.d $a2, $sp, 8
+    st.d $a2, $t1, TEntryInformation.OS.argv
+
+    { save envp }
+    alsl.d $t0, $a1, $a2, 3
+    addi.d $t0, $t0, 8
+    st.d $t0, $t1, TEntryInformation.OS.envp
+{$else}
+    { argc = *(int *)sp }
+    ld.w $a1, $sp, 0
+
+    { save operatingsystem parameter argc }
+    la.got $t0, operatingsystem_parameter_argc
+    st.w $a1, $t0, 0
+
+    { argv = (char **)(sp + 8) }
+    addi.d $a2, $sp, 8
+
+    { save operatingsystem parameter argv }
+    la.got $t0, operatingsystem_parameter_argv
+    st.d $a2, $t0, 0
+
+    { save operatingsystem parameter envp }
+    la.got $t0, operatingsystem_parameter_envp
+    alsl.d $t1, $a1, $a2, 3
+    addi.d $t1, $t1, 8
+    st.d $t1, $t0, 0
+{$endif}
+
+    { adjust $sp for 16-aligned }
+    bstrins.d $sp, $zero, 3, 0
+
+    { call libc_start_main (&main_stub, argc, argv, init, fiit, rtld_fini, stkend ) }
+    la.got $a3, ___libc_csu_fini
+    la.got $a4, ___libc_csu_fini
+    ori $a5, $a0, 0
+    ori $a6, $sp, 0
+    la.pcrel $a0, main_stub
+    bl %plt(libc_start_main)
+    break 1
+  end;
+
+procedure _FPC_libc_haltproc(e:longint); assembler; nostackframe; public name '_haltproc';
+  asm
+    la.pcrel $t0, fpc_ret_sp
+    ld.d $sp, $t0, 0
+    la.pcrel $t1, fpc_ret_ra
+    ld.d $ra, $t1, 0
+    jr $ra
+  end;

+ 55 - 0
rtl/linux/loongarch64/si_dll.inc

@@ -0,0 +1,55 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (C) 2022 Loongson Technology Corporation Limited.
+
+    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.
+
+ **********************************************************************}
+
+{******************************************************************************
+                        Shared library start/halt
+ ******************************************************************************}
+
+procedure _FPC_shared_lib_haltproc(e:longint); cdecl; forward;
+
+procedure __FPC_shared_lib_start(argc : dword;argv,envp : pointer); cdecl;
+  begin
+{$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
+    SysInitEntryInformation.OS.argc:=argc;
+    SysInitEntryInformation.OS.argv:=argv;
+    SysInitEntryInformation.OS.envp:=envp;
+    SysInitEntryInformation.OS.stkptr:=get_frame;
+    SysInitEntryInformation.OS.stklen:=StackLength;
+    SysInitEntryInformation.OS.haltproc:=@_FPC_shared_lib_haltproc;
+    SysEntry(SysInitEntryInformation);
+{$else}
+    operatingsystem_parameter_argc:=argc;    { Copy the argument count      }
+    operatingsystem_parameter_argv:=argv;    { Copy the argument pointer    }
+    operatingsystem_parameter_envp:=envp;    { Copy the environment pointer }
+    initialstkptr:=get_frame;
+    PASCALMAIN;
+{$endif}
+  end;
+
+procedure _FPC_shared_lib_start; assembler; nostackframe; public name 'FPC_SHARED_LIB_START'; public name '_start';
+  asm
+    .L_FPC_shared_lib_start:
+    .section ".init_array","a"
+    .dc.a .L_FPC_shared_lib_start
+    .text
+    b __FPC_shared_lib_start
+  end;
+
+{ this routine is only called when the halt() routine of the RTL embedded in
+  the shared library is called }
+procedure _FPC_shared_lib_haltproc(e:longint); cdecl; assembler; nostackframe; public name '_haltproc';
+  asm
+    ori $a7, $zero, 94
+    syscall 0
+    b _FPC_shared_lib_haltproc
+  end;

+ 166 - 0
rtl/linux/loongarch64/si_g.inc

@@ -0,0 +1,166 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (C) 2022 Loongson Technology Corporation Limited.
+
+    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.
+
+ **********************************************************************}
+
+{******************************************************************************
+                          Process start/halt
+ ******************************************************************************}
+
+{
+The entry point's job is to call __libc_start_main.  Per the ABI,
+a0 contains the address of a function to be passed to atexit.
+__libc_start_main wants this in a5.
+
+int __libc_start_main (
+  int (*main) (int, char **, char **),
+  int argc,
+  char **argv,
+  __typeof (main) init,
+  void (*fini) (void),
+  void (*rtld_fini) (void),
+  void *stack_end);
+}
+
+var
+  libc_environ: pchar; external name '__environ';
+  libc_fpu_control: word; external name '__fpu_control';
+  libc_init_proc: procedure; external name '_init';
+  libc_fini_proc: procedure; external name '_fini';
+  _etext: pointer; external name '_etext';
+
+  fpc_ret_ra,fpc_ret_sp : pointer;
+
+procedure libc_atexit; external name 'atexit';
+procedure libc_exit; external name '__libc_exit';
+procedure libc_init; external name '__libc_init';
+procedure libc_setfpucw; external name '__setfpucw';
+procedure libc_start_main; external name '__libc_start_main';
+
+procedure gmon_monstartup; external name 'monstartup';
+procedure gmon_mcleanup; external name '_mcleanup';
+
+procedure _FPC_libc_start; forward;
+procedure _FPC_libc_haltproc(e:longint); forward;
+
+procedure main_stub; assembler; nostackframe;
+  asm
+    { let fp = sp in case of no fp value }
+    ori $fp, $sp, 0
+
+    { save ra and sp }
+    la.pcrel $t0, fpc_ret_ra
+    st.d $ra, $t0, 0
+    la.pcrel $t1, fpc_ret_sp
+    st.d $sp, $t1, 0
+
+    { call gmon_monstartup(&_FPC_libc_start, &_etext) }
+    la.got $a0, _FPC_libc_start
+    la.got $a1, _etext
+    la.got $ra, gmon_monstartup
+    jirl $ra, $ra, 0
+
+    { call libc_atexit(&gmon_mcleanup) }
+    la.got $a0, gmon_mcleanup
+    la.got $ra, libc_atexit
+    jirl $ra, $ra, 0
+
+{$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
+    la.got, $t0, SysInitEntryInformation
+    st.d $sp, $t0, TEntryInformation.OS.stkptr
+    la.got $t1, StackLength
+    st.d $t1, $t0, TEntryInformation.OS.stklen
+    la.got $t2, _FPC_libc_haltproc
+    st.d $t2, $t0, TEntryInformation.OS.haltproc
+    move $a0, $t0
+    bl %plt(SysEntry)
+{$else}
+    { save stack pointer }
+    la.got $t1, initialstkptr
+    st.d $sp, $t1, 0
+
+    { call PascalMain }
+    bl %plt(PASCALMAIN)
+{$endif}
+    break 1
+  end;
+
+procedure ini_dummy;
+  begin
+  end;
+
+{******************************************************************************
+                          C library start/halt
+ ******************************************************************************}
+
+procedure _FPC_libc_start; assembler; nostackframe; public name '_start';
+  asm
+    { clear frame pointer }
+    ori $fp, $zero, 0
+
+{$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
+    la.got $t1, SysInitEntryInformation
+
+    { argc = *(int *)sp }
+    ld.w $a1, $sp, 0
+    st.w $a1, $t1, TEntryInformation.OS.argc
+
+    { argv = (char **)(sp + 8) }
+    addi.d $a2, $sp, 8
+    st.d $a2, $t1, TEntryInformation.OS.argv
+
+    { save envp }
+    alsl.d $t0, $a1, $a2, 3
+    addi.d $t0, $t0, 8
+    st.d $t0, $t1, TEntryInformation.OS.envp
+{$else}
+    { argc = *(int *)sp }
+    ld.w $a1, $sp, 0
+
+    { save operatingsystem parameter argc }
+    la.got $t0, operatingsystem_parameter_argc
+    st.w $a1, $t0, 0
+
+    { argv = (char **)(sp + 8) }
+    addi.d $a2, $sp, 8
+
+    { save operatingsystem parameter argv }
+    la.got $t0, operatingsystem_parameter_argv
+    st.d $a2, $t0, 0
+
+    { save operatingsystem parameter envp }
+    la.got $t0, operatingsystem_parameter_envp
+    alsl.d $t1, $a1, $a2, 3
+    addi.d $t1, $t1, 8
+    st.d $t1, $t0, 0
+{$endif}
+
+    { adjust $sp for 16-aligned }
+    bstrins.d $sp, $zero, 3, 0
+
+    { call libc_start_main (&main_stub, argc, argv, dummy, dummy, rtld_fini, stkend ) }
+    la.got $a3, ini_dummy
+    la.got $a4, ini_dummy
+    ori $a5, $a0, 0
+    ori $a6, $sp, 0
+    la.pcrel $a0, main_stub
+    bl %plt(libc_start_main)
+    break 1
+  end;
+
+procedure _FPC_libc_haltproc(e:longint); assembler; nostackframe; public name '_haltproc';
+  asm
+    la.pcrel $t0, fpc_ret_sp
+    ld.d $sp, $t0, 0
+    la.pcrel $t1, fpc_ret_ra
+    ld.d $ra, $t1, 0
+    jr $ra
+  end;

+ 120 - 0
rtl/linux/loongarch64/si_prc.inc

@@ -0,0 +1,120 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (C) 2022 Loongson Technology Corporation Limited.
+
+    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.
+
+ **********************************************************************}
+
+{******************************************************************************
+                          Process start/halt
+ ******************************************************************************}
+
+{$ifndef FPC_USE_LIBC}
+procedure InitTLS; [external name 'FPC_INITTLS'];
+{$endif}
+
+var
+  dlexitproc : pointer;
+
+procedure _FPC_proc_haltproc(e: longint); cdecl; forward;
+
+procedure _FPC_proc_start; assembler; nostackframe; public name '_start';
+  asm
+    { clear frame pointer }
+    ori $fp, $zero, 0
+
+{$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
+    la.got $t1, SysInitEntryInformation
+
+    { argc = *(int *)sp }
+    ld.w $a1, $sp, 0
+    st.w $a1, $t1, TEntryInformation.OS.argc
+
+    { argv = (char **)(sp + 8) }
+    addi.d $a2, $sp, 8
+    st.d $a2, $t1, TEntryInformation.OS.argv
+
+    { save envp }
+    alsl.d $t0, $a1, $a2, 3
+    addi.d $t0, $t0, 8
+    st.d $t0, $t1, TEntryInformation.OS.envp
+
+    { adjust $sp for 16-aligned }
+    bstrins.d $sp, $zero, 3, 0
+
+    st.d $sp, $t1, TEntryInformation.OS.stkptr
+    la.got $t0, StackLength
+    st.d $t0, $t1, TEntryInformation.OS.stklen
+    la.got $t2, _FPC_proc_haltproc
+    st.d $t2, $t1, TEntryInformation.OS.haltproc
+    move $a0, $t1
+
+{$if defined(FPC_USE_LIBC)}
+    { call PascalMain }
+    bl SysEntry
+{$else}
+    bl SysEntry_InitTLS
+{$endif}
+{$else}
+    { save operatingsystem parameter argc }
+    ld.w $a1, $sp, 0
+    la.got $t0, operatingsystem_parameter_argc
+    st.w $a1, $t0, 0
+
+    { save operatingsystem parameter argv }
+    addi.d $a2, $sp, 8
+    la.got $t0, operatingsystem_parameter_argv
+    st.d $a2, $t0, 0
+
+    { save operatingsystem parameter envp }
+    la.got $t0, operatingsystem_parameter_envp
+    alsl.d $t1, $a1, $a2, 3
+    addi.d $t1, $t1, 8
+    st.d $t1, $t0, 0
+
+    { adjust $sp for 16-aligned }
+    bstrins.d $sp, $zero, 3, 0
+
+    { save stack pointer }
+    la.got $t0, initialstkptr
+    st.d $sp, $t0, 0
+
+{$if defined(FPC_USE_LIBC)}
+    { call PascalMain }
+    bl PASCALMAIN
+{$else}
+    bl InitTLS
+{$endif}
+{$endif}
+    break 1
+  end;
+
+
+procedure _FPC_dynamic_proc_start; assembler; nostackframe; public name '_dynamic_start';
+  asm
+    la.got $t0, dlexitproc
+    st.d $a0, $t0, 0
+    b _FPC_proc_start
+  end;
+
+
+procedure _FPC_loongarch_exit(e:longint); assembler; nostackframe;
+  asm
+    ori $a7, $zero, 94
+    syscall 0
+    b _FPC_loongarch_exit
+  end;
+
+
+procedure _FPC_proc_haltproc(e:longint); cdecl; public name '_haltproc';
+  begin
+    if assigned(dlexitproc) then
+      TProcedure(dlexitproc);
+    _FPC_loongarch_exit(e);
+  end;

+ 97 - 0
rtl/linux/loongarch64/sighnd.inc

@@ -0,0 +1,97 @@
+{
+    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.
+
+    Signal handler is arch dependant due to processor to language
+    exception conversion.
+
+    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.
+
+ **********************************************************************}
+
+{ $define SYSTEM_DEBUG}
+
+procedure SignalToRunerror(Sig: longint; SigInfo: PSigInfo; UContext: PUContext); public name '_FPC_DEFAULTSIGHANDLER'; cdecl;
+
+const
+  fpu_ctx_magic = $46505501;
+  lsx_ctx_magic = $53580001;
+  lasx_ctx_magic = $41535801;
+  used_fp = 1 shl 0;
+  adrerr_rd = 1 shl 30;
+  adrerr_wr = 1 shl 31;
+  fcsr_bits_clear_exceptions = $e0ffffff;
+
+var
+  PCtxInfo : PContext_Info;
+  PFPU_Ctx : PFPU_Context;
+  PLSX_Ctx : PLSX_Context;
+  PLASX_Ctx : PLASX_Context;
+  PX_Context : pointer;
+  res : word;
+  ferr: cUint;
+
+begin
+  res:=0;
+  case sig of
+    SIGFPE:
+      begin
+        res:=207;
+        if (used_fp and uContext^.uc_mcontext.flags)<>0 then
+          begin
+            ferr:=0;
+            PCtxInfo:=PContext_Info(uContext+1);
+            PX_Context:=PCtxInfo+1;
+            case (PCtxInfo^.magic) of
+              fpu_ctx_magic: begin
+                  PFPU_Ctx:=PX_Context;
+                  ferr:=PFPU_Ctx^.fcsr;
+                  PFPU_Ctx^.fcsr:=PFPU_Ctx^.fcsr and fcsr_bits_clear_exceptions;
+                end;
+              lsx_ctx_magic: begin
+                  PLSX_Ctx:=PX_Context;
+                  ferr:=PLSX_Ctx^.fcsr;
+                  PLSX_Ctx^.fcsr:=PLSX_Ctx^.fcsr and fcsr_bits_clear_exceptions;
+                end;
+              lasx_ctx_magic: begin
+                  PLASX_Ctx:=PX_Context;
+                  ferr:=PLASX_Ctx^.fcsr;
+                  PLASX_Ctx^.fcsr:=PLASX_Ctx^.fcsr and fcsr_bits_clear_exceptions;
+                end;
+            end;
+            ferr:=ferr shr 24;
+            case ferr of
+              1: res:=207;
+              2: res:=206;
+              4: res:=205;
+              8: res:=208;
+              16: res:=207;
+            else
+              ;
+            end;
+        end;
+      end;
+    SIGILL:
+        res:=216;
+    SIGSEGV :
+        res:=216;
+    SIGBUS:
+        res:=214;
+    SIGINT:
+        res:=217;
+    SIGQUIT:
+        res:=233;
+  end;
+  reenable_signal(sig);
+  { give runtime error at the position where the signal was raised }
+  if res<>0 then
+    HandleErrorAddrFrame(res,
+      pointer(uContext^.uc_mcontext.pc),
+      pointer(uContext^.uc_mcontext.regs[3]));
+end;

+ 81 - 0
rtl/linux/loongarch64/sighndh.inc

@@ -0,0 +1,81 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2000 by Jonas Maebe,
+    member of the Free Pascal development team.
+
+    TSigContext and associated structures.
+
+    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.
+
+ **********************************************************************}
+
+{$packrecords C}
+
+type
+  PContext_Info = ^TContext_Info;
+  TContext_Info = record
+    magic,
+    size : DWord;
+    __padding : cULong;
+  end;
+
+  PFPU_Context = ^TFPU_Context;
+  TFPU_Context = record
+    regs : array[0..31] of cULong;
+    fcc : cULong;
+    fcsr : cUInt;
+  end;
+
+  PLSX_Context = ^TLSX_Context;
+  TLSX_Context = record
+    regs : array[0..31] of array[0..15] of Byte;
+    fcc : cULong;
+    fcsr : cUInt;
+  end;
+
+  PLASX_Context = ^TLASX_Context;
+  TLASX_Context = record
+    regs : array[0..31] of array[0..31] of Byte;
+    fcc : cULong;
+    fcsr : cUInt;
+  end;
+
+  PSigContext = ^TSigContext;
+  TSigContext = record
+    pc : cULong;
+    regs : array[0..31] of cULong;
+    flags : cUInt;
+    { __pad : cULong; }
+    { The following fields should be 16-byte-aligned. Currently the
+      directive for specifying alignment is buggy, so the preceding
+      field was added so that the record has the right size.
+      It is noted by aarch64 and we drop here at present. }
+  end;
+
+  stack_t = record
+    ss_sp : pointer;
+    ss_flags : cInt;
+    ss_size : size_t;
+  end;
+
+  PUContext = ^TUContext;
+  TUContext = record
+    uc_flags : cULong;
+    uc_link : PUContext;
+    uc_stack : stack_t;
+    uc_sigmask : sigset_t;
+    {$if sizeof(sigset_t) < 128 }
+    __padding : array[1..128 - sizeof(sigset_t)] of byte;
+    {$endif}
+    __pad : cULong;
+    { The following field should be 16-byte-aligned. Currently the
+      directive for specifying alignment is buggy, so the preceding
+      field was added so that the record has the right size.
+      It is noted by aarch64 and we keep here at present. }
+    uc_mcontext : TSigContext;
+  end;

+ 47 - 0
rtl/linux/loongarch64/stat.inc

@@ -0,0 +1,47 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1999-2000 by Jonas Maebe, (c) 2005 Thomas Schatzl,
+    members of the Free Pascal development team.
+
+    Contains the definition of the stat type for the PowerPC64 platform.
+
+    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.
+
+ **********************************************************************}
+
+{ This structure was adapted from
+
+    include/uapi/asm-generic/stat.h
+
+  in Linux 4.0. Note that the stat record is the same for direct
+  syscalls as for when linking to libc.
+}
+
+{$PACKRECORDS C}
+  stat = record
+      st_dev        : cULong;
+      st_ino        : cULong;
+      st_mode       : cUInt;
+      st_nlink      : cUInt;
+      st_uid        : cUInt;
+      st_gid        : cUInt;
+      st_rdev       : cULong;
+      __pad1a       : cULong;
+      st_size       : cLong;
+      st_blksize    : cInt;
+      __pad2a       : cInt;
+      st_blocks     : cLong;
+      st_atime      : cLong;
+      st_atime_nsec : cULong;
+      st_mtime      : cLong;
+      st_mtime_nsec : cULong;
+      st_ctime      : cLong;
+      st_ctime_nsec : cULong;
+      __unused4a    : cUInt;
+      __unused5a    : cUInt;
+  end;

+ 141 - 0
rtl/linux/loongarch64/syscall.inc

@@ -0,0 +1,141 @@
+{
+  This file is part of the Free Pascal run time library.
+
+  Perform syscall with 0..6 arguments.
+  If syscall return value is negative, negate it, set errno, and return -1.
+
+  Written by Edmund Grimley Evans in 2015 and released into the public domain.
+}
+
+function FpSysCall(sysnr:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL0'];
+asm
+  ori $a7, $a0, 0
+  syscall 0
+  bge $a0, $zero, .Ldone
+  addi.d $sp, $sp, -16
+  st.d $ra, $sp, 8
+  sub.d $a0, $zero, $a0
+  bl seterrno
+  addi.d $a0, $zero, -1
+  ld.d $ra, $sp, 8
+  addi.d $sp, $sp, 16
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL1'];
+asm
+  ori $a7, $a0, 0
+  ori $a0, $a1, 0
+  syscall 0
+  bge $a0, $zero, .Ldone
+  addi.d $sp, $sp, -16
+  st.d $ra, $sp, 8
+  sub.d $a0, $zero, $a0
+  bl seterrno
+  addi.d $a0, $zero, -1
+  ld.d $ra, $sp, 8
+  addi.d $sp, $sp, 16
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL2'];
+asm
+  ori $a7, $a0, 0
+  ori $a0, $a1, 0
+  ori $a1, $a2, 0
+  syscall 0
+  bge $a0, $zero, .Ldone
+  addi.d $sp, $sp, -16
+  st.d $ra, $sp, 8
+  sub.d $a0, $zero, $a0
+  bl seterrno
+  addi.d $a0, $zero, -1
+  ld.d $ra, $sp, 8
+  addi.d $sp, $sp, 16
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL3'];
+asm
+  ori $a7, $a0, 0
+  ori $a0, $a1, 0
+  ori $a1, $a2, 0
+  ori $a2, $a3, 0
+  syscall 0
+  bge $a0, $zero, .Ldone
+  addi.d $sp, $sp, -16
+  st.d $ra, $sp, 8
+  sub.d $a0, $zero, $a0
+  bl seterrno
+  addi.d $a0, $zero, -1
+  ld.d $ra, $sp, 8
+  addi.d $sp, $sp, 16
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL4'];
+asm
+  ori $a7, $a0, 0
+  ori $a0, $a1, 0
+  ori $a1, $a2, 0
+  ori $a2, $a3, 0
+  ori $a3, $a4, 0
+  syscall 0
+  bge $a0, $zero, .Ldone
+  addi.d $sp, $sp, -16
+  st.d $ra, $sp, 8
+  sub.d $a0, $zero, $a0
+  bl seterrno
+  addi.d $a0, $zero, -1
+  ld.d $ra, $sp, 8
+  addi.d $sp, $sp, 16
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL5'];
+asm
+  ori $a7, $a0, 0
+  ori $a0, $a1, 0
+  ori $a1, $a2, 0
+  ori $a2, $a3, 0
+  ori $a3, $a4, 0
+  ori $a4, $a5, 0
+  syscall 0
+  bge $a0, $zero, .Ldone
+  addi.d $sp, $sp, -16
+  st.d $ra, $sp, 8
+  sub.d $a0, $zero, $a0
+  bl seterrno
+  addi.d $a0, $zero, -1
+  ld.d $ra, $sp, 8
+  addi.d $sp, $sp, 16
+.Ldone:
+end;
+
+function FpSysCall(sysnr,param1,param2,param3,param4,param5,param6:TSysParam):TSysResult;
+assembler; nostackframe; [public,alias:'FPC_SYSCALL6'];
+asm
+  ori $a7, $a0, 0
+  ori $a0, $a1, 0
+  ori $a1, $a2, 0
+  ori $a2, $a3, 0
+  ori $a3, $a4, 0
+  ori $a4, $a5, 0
+  ori $a5, $a6, 0
+  syscall 0
+  bge $a0, $zero, .Ldone
+  addi.d $sp, $sp, -16
+  st.d $ra, $sp, 8
+  sub.d $a0, $zero, $a0
+  bl seterrno
+  addi.d $a0, $zero, -1
+  ld.d $ra, $sp, 8
+  addi.d $sp, $sp, 16
+.Ldone:
+end;

+ 27 - 0
rtl/linux/loongarch64/syscallh.inc

@@ -0,0 +1,27 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2002 Marco van de Voort
+    member of the Free Pascal development team.
+
+    LoongArch syscall headers for Linux
+
+    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.
+
+ **********************************************************************}
+
+Type
+  TSysResult = Int64;
+  TSysParam  = Int64;
+
+function Do_SysCall(sysnr:TSysParam):TSysResult; external name 'FPC_SYSCALL0';
+function Do_SysCall(sysnr,param1:TSysParam):TSysResult; external name 'FPC_SYSCALL1';
+function Do_SysCall(sysnr,param1,param2:TSysParam):TSysResult; external name 'FPC_SYSCALL2';
+function Do_SysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; external name 'FPC_SYSCALL3';
+function Do_SysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; external name 'FPC_SYSCALL4';
+function Do_SysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResult; external name 'FPC_SYSCALL5';
+function Do_SysCall(sysnr,param1,param2,param3,param4,param5,param6:TSysParam):TSysResult; external name 'FPC_SYSCALL6';

+ 1 - 0
rtl/linux/loongarch64/sysnr.inc

@@ -0,0 +1 @@
+{$i ../sysnr-gen.inc}

+ 5 - 0
rtl/linux/osdefs.inc

@@ -122,3 +122,8 @@
     {$define MMAP2}
     {$define MMAP2}
   {$endif}
   {$endif}
 {$endif android}
 {$endif android}
+
+{$ifdef cpuloongarch64}
+  {$define generic_linux_syscalls}
+  {$undef usestime}
+{$endif cpuloongarch64}

+ 1 - 1
rtl/linux/ostypes.inc

@@ -320,7 +320,7 @@ CONST
 {$if defined(cpupowerpc)}
 {$if defined(cpupowerpc)}
     O_LARGEFILE =   $10000;
     O_LARGEFILE =   $10000;
 {$endif}
 {$endif}
-{$if defined(cpui386) or defined(cpux86_64) or defined(cpuia64) or defined(cpuxtensa) or defined(cpuriscv32)}
+{$if defined(cpui386) or defined(cpux86_64) or defined(cpuia64) or defined(cpuxtensa) or defined(cpuriscv32) or defined(loongarch64)}
     O_LARGEFILE =    $8000;
     O_LARGEFILE =    $8000;
 {$endif}
 {$endif}
 {$if defined(cpumips) or defined(cpumipsel)}
 {$if defined(cpumips) or defined(cpumipsel)}

+ 11 - 0
rtl/linux/system.pp

@@ -188,6 +188,14 @@ begin
 end;
 end;
 {$endif defined(CPUX86_64)}
 {$endif defined(CPUX86_64)}
 
 
+{$ifdef CPULOONGARCH64}
+{$define INITTLS}
+Function fpset_tls(p : pointer;size : SizeUInt):cint; assembler;
+asm
+  move $tp, p
+end;
+{$endif CPULOONGARCH64}
+
 {$endif not FPC_USE_LIBC}
 {$endif not FPC_USE_LIBC}
 
 
 
 
@@ -660,6 +668,9 @@ function FpUGetRLimit(resource : cInt; rlim : PRLimit) : cInt; cdecl; external c
 const
 const
   page_size = $10000;
   page_size = $10000;
   {$define LAST_PAGE_GENERATES_SIGNAL}
   {$define LAST_PAGE_GENERATES_SIGNAL}
+{$elseif defined(CPULOONGARCH)}
+const
+  page_size = $4000;
 {$else}
 {$else}
 const
 const
   page_size = $1000;
   page_size = $1000;

+ 266 - 0
rtl/linux/termios.inc

@@ -2768,6 +2768,272 @@ const
 
 
 {$endif cpuxtensa}
 {$endif cpuxtensa}
 
 
+{$ifdef cpuloongarch64}
+
+{ from Linux 4.0, include/uapi/asm-generic/ioctls.h }
+
+  { For Terminal handling }
+  TCGETS          = $5401;
+  TCSETS          = $5402;
+  TCSETSW         = $5403;
+  TCSETSF         = $5404;
+  TCGETA          = $5405;
+  TCSETA          = $5406;
+  TCSETAW         = $5407;
+  TCSETAF         = $5408;
+  TCSBRK          = $5409;
+  TCXONC          = $540A;
+  TCFLSH          = $540B;
+  TIOCEXCL        = $540C;
+  TIOCNXCL        = $540D;
+  TIOCSCTTY       = $540E;
+  TIOCGPGRP       = $540F;
+  TIOCSPGRP       = $5410;
+  TIOCOUTQ        = $5411;
+  TIOCSTI         = $5412;
+  TIOCGWINSZ      = $5413;
+  TIOCSWINSZ      = $5414;
+  TIOCMGET        = $5415;
+  TIOCMBIS        = $5416;
+  TIOCMBIC        = $5417;
+  TIOCMSET        = $5418;
+  TIOCGSOFTCAR    = $5419;
+  TIOCSSOFTCAR    = $541A;
+  FIONREAD        = $541B;
+  TIOCINQ         = FIONREAD;
+  TIOCLINUX       = $541C;
+  TIOCCONS        = $541D;
+  TIOCGSERIAL     = $541E;
+  TIOCSSERIAL     = $541F;
+  TIOCPKT         = $5420;
+  FIONBIO         = $5421;
+  TIOCNOTTY       = $5422;
+  TIOCSETD        = $5423;
+  TIOCGETD        = $5424;
+  TCSBRKP         = $5425;
+
+  TIOCSBRK        = $5427;
+  TIOCCBRK        = $5428;
+  TIOCGSID        = $5429;
+
+  TIOCGRS485      = $542E;
+  TIOCSRS485      = $542F;
+
+  TCGETX          = $5432;
+  TCSETX          = $5433;
+  TCSETXF         = $5434;
+  TCSETXW         = $5435;
+  TIOCVHANGUP     = $5437;
+
+  FIONCLEX        = $5450;
+  FIOCLEX         = $5451;
+  FIOASYNC        = $5452;
+  TIOCSERCONFIG   = $5453;
+  TIOCSERGWILD    = $5454;
+  TIOCSERSWILD    = $5455;
+  TIOCGLCKTRMIOS  = $5456;
+  TIOCSLCKTRMIOS  = $5457;
+  TIOCSERGSTRUCT  = $5458;
+  TIOCSERGETLSR   = $5459;
+  TIOCSERGETMULTI = $545A;
+  TIOCSERSETMULTI = $545B;
+  TIOCMIWAIT      = $545C;
+  TIOCGICOUNT     = $545D;
+
+  FIOQSIZE        = $5460;
+
+  TIOCPKT_DATA       = 0;
+  TIOCPKT_FLUSHREAD  = 1;
+  TIOCPKT_FLUSHWRITE = 2;
+  TIOCPKT_STOP       = 4;
+  TIOCPKT_START      = 8;
+  TIOCPKT_NOSTOP     = 16;
+  TIOCPKT_DOSTOP     = 32;
+  TIOCPKT_IOCTL      = 64;
+
+  TIOCSER_TEMT       = $01;
+
+{ from Linux 4.0, include/uapi/asm-generic/termbits.h }
+
+  { c_cc characters }
+  VINTR    = 0;
+  VQUIT    = 1;
+  VERASE   = 2;
+  VKILL    = 3;
+  VEOF     = 4;
+  VTIME    = 5;
+  VMIN     = 6;
+  VSWTC    = 7;
+  VSTART   = 8;
+  VSTOP    = 9;
+  VSUSP    = 10;
+  VEOL     = 11;
+  VREPRINT = 12;
+  VDISCARD = 13;
+  VWERASE  = 14;
+  VLNEXT   = 15;
+  VEOL2    = 16;
+
+  { c_iflag bits }
+  IGNBRK  = &0000001;
+  BRKINT  = &0000002;
+  IGNPAR  = &0000004;
+  PARMRK  = &0000010;
+  INPCK   = &0000020;
+  ISTRIP  = &0000040;
+  INLCR   = &0000100;
+  IGNCR   = &0000200;
+  ICRNL   = &0000400;
+  IUCLC   = &0001000;
+  IXON    = &0002000;
+  IXANY   = &0004000;
+  IXOFF   = &0010000;
+  IMAXBEL = &0020000;
+  IUTF8   = &0040000;
+
+  { c_oflag bits }
+  OPOST  = &0000001;
+  OLCUC  = &0000002;
+  ONLCR  = &0000004;
+  OCRNL  = &0000010;
+  ONOCR  = &0000020;
+  ONLRET = &0000040;
+  OFILL  = &0000100;
+  OFDEL  = &0000200;
+  NLDLY  = &0000400;
+  NL0    = &0000000;
+  NL1    = &0000400;
+  CRDLY  = &0003000;
+  CR0    = &0000000;
+  CR1    = &0001000;
+  CR2    = &0002000;
+  CR3    = &0003000;
+  TABDLY = &0014000;
+  TAB0   = &0000000;
+  TAB1   = &0004000;
+  TAB2   = &0010000;
+  TAB3   = &0014000;
+  XTABS  = &0014000;
+  BSDLY  = &0020000;
+  BS0    = &0000000;
+  BS1    = &0020000;
+  VTDLY  = &0040000;
+  VT0    = &0000000;
+  VT1    = &0040000;
+  FFDLY  = &0100000;
+  FF0    = &0000000;
+  FF1    = &0100000;
+
+  { c_cflag bits }
+  CBAUD    = &0010017;
+  B0       = &0000000;
+  B50      = &0000001;
+  B75      = &0000002;
+  B110     = &0000003;
+  B134     = &0000004;
+  B150     = &0000005;
+  B200     = &0000006;
+  B300     = &0000007;
+  B600     = &0000010;
+  B1200    = &0000011;
+  B1800    = &0000012;
+  B2400    = &0000013;
+  B4800    = &0000014;
+  B9600    = &0000015;
+  B19200   = &0000016;
+  B38400   = &0000017;
+  EXTA     = B19200;
+  EXTB     = B38400;
+  CSIZE    = &0000060;
+  CS5      = &0000000;
+  CS6      = &0000020;
+  CS7      = &0000040;
+  CS8      = &0000060;
+  CSTOPB   = &0000100;
+  CREAD    = &0000200;
+  PARENB   = &0000400;
+  PARODD   = &0001000;
+  HUPCL    = &0002000;
+  CLOCAL   = &0004000;
+  CBAUDEX  = &0010000;
+  BOTHER   = &0010000;
+  B57600   = &0010001;
+  B115200  = &0010002;
+  B230400  = &0010003;
+  B460800  = &0010004;
+  B500000  = &0010005;
+  B576000  = &0010006;
+  B921600  = &0010007;
+  B1000000 = &0010010;
+  B1152000 = &0010011;
+  B1500000 = &0010012;
+  B2000000 = &0010013;
+  B2500000 = &0010014;
+  B3000000 = &0010015;
+  B3500000 = &0010016;
+  B4000000 = &0010017;
+  __MAX_BAUD =  B4000000;
+
+  CIBAUD   = &002003600000;
+  CMSPAR   = &010000000000;
+  CRTSCTS  = &020000000000;
+
+  IBSHIFT  = 16;
+
+  { c_lflag bits }
+  ISIG    = &0000001;
+  ICANON  = &0000002;
+  XCASE   = &0000004;
+  ECHO    = &0000010;
+  ECHOE   = &0000020;
+  ECHOK   = &0000040;
+  ECHONL  = &0000100;
+  NOFLSH  = &0000200;
+  TOSTOP  = &0000400;
+  ECHOCTL = &0001000;
+  ECHOPRT = &0002000;
+  ECHOKE  = &0004000;
+  FLUSHO  = &0010000;
+  PENDIN  = &0040000;
+  IEXTEN  = &0100000;
+  EXTPROC = &0200000;
+
+  { TCFlow }
+  TCOOFF = 0;
+  TCOON  = 1;
+  TCIOFF = 2;
+  TCION  = 3;
+
+  { TCFlush }
+  TCIFLUSH  = 0;
+  TCOFLUSH  = 1;
+  TCIOFLUSH = 2;
+
+  { TCSetAttr }
+  TCSANOW   = 0;
+  TCSADRAIN = 1;
+  TCSAFLUSH = 2;
+
+{ from Linux 4.0, include/uapi/asm-generic/termios.h }
+
+  { c_line bits }
+  TIOCM_LE   = $001;
+  TIOCM_DTR  = $002;
+  TIOCM_RTS  = $004;
+  TIOCM_ST   = $008;
+  TIOCM_SR   = $010;
+  TIOCM_CTS  = $020;
+  TIOCM_CAR  = $040;
+  TIOCM_RNG  = $080;
+  TIOCM_DSR  = $100;
+  TIOCM_CD   = TIOCM_CAR;
+  TIOCM_RI   = TIOCM_RNG;
+  TIOCM_OUT1 = $2000;
+  TIOCM_OUT2 = $4000;
+  TIOCM_LOOP = $8000;
+
+{$endif cpuloongarch64}
+
 Type
 Type
   winsize = record
   winsize = record
     ws_row,
     ws_row,

+ 5 - 0
rtl/unix/cthreads.pp

@@ -179,6 +179,11 @@ Type  PINTRTLEvent = ^TINTRTLEvent;
         threadvarblocksize:=align(threadvarblocksize,16);
         threadvarblocksize:=align(threadvarblocksize,16);
         {$endif cpuxtensa}
         {$endif cpuxtensa}
 
 
+        {$ifdef cpuloongarch64}
+        {$define threadvarblocksize_set}
+        threadvarblocksize:=align(threadvarblocksize,16);
+        {$endif cpuloongarch64}
+
         {$ifndef threadvarblocksize_set}
         {$ifndef threadvarblocksize_set}
         {$error threadvarblocksize must be set! }
         {$error threadvarblocksize must be set! }
         {$endif threadvarblocksize_set}
         {$endif threadvarblocksize_set}