From 657aa063608bbb6640493cab21df66bcc30dae94 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?K=C3=A1roly=20Balogh?= <karoly@freepascal.org>
Date: Sun, 6 Nov 2016 14:31:42 +0000
Subject: [PATCH] arm: arm-aros syscall support

git-svn-id: trunk@34809 -
---
 compiler/arm/narmcal.pas | 65 +++++++++++++++++++++++++++++++++++++---
 compiler/arm/symcpu.pas  | 59 ++++++++++++++++++++++++++++++++++--
 compiler/parser.pas      |  1 +
 compiler/pdecsub.pas     |  8 ++---
 compiler/ppu.pas         |  2 +-
 5 files changed, 124 insertions(+), 11 deletions(-)

diff --git a/compiler/arm/narmcal.pas b/compiler/arm/narmcal.pas
index 67978e3f0f..42aaab58fc 100644
--- a/compiler/arm/narmcal.pas
+++ b/compiler/arm/narmcal.pas
@@ -30,18 +30,73 @@ interface
 
     type
        tarmcallnode = class(tcgcallnode)
+         procedure gen_syscall_para(para: tcallparanode); override;
          procedure set_result_location(realresdef: tstoreddef);override;
+       public
+         procedure do_syscall;override;
        end;
 
 implementation
 
   uses
-    verbose,globtype,globals,aasmdata,
-    symconst,
-    cgbase,cgutils,cpuinfo,
-    ncgutil,tgobj,
+    verbose,globtype,globals,aasmdata,aasmtai,
+    symconst,symtype,symbase,symsym,symcpu,parabase,paramgr,
+    cgbase,cgobj,cgutils,cpuinfo,cpubase,cutils,
+    ncgutil,tgobj,nld,
     systems;
 
+  procedure tarmcallnode.gen_syscall_para(para: tcallparanode);
+    begin
+      { lib parameter has no special type but proccalloptions must be a syscall }
+      para.left:=cloadnode.create(tcpuprocdef(procdefinition).libsym,tcpuprocdef(procdefinition).libsym.owner);
+    end;
+
+  procedure tarmcallnode.do_syscall;
+    var
+      tmpref: treference;
+      libparaloc: pcgparalocation;
+      hsym: tsym;
+    begin
+      case target_info.system of
+        system_arm_aros:
+            begin
+              if (po_syscall_baselast in tprocdef(procdefinition).procoptions) then
+                begin
+                  current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('AROS SysCall - BaseLast')));
+
+                  cg.getcpuregister(current_asmdata.CurrAsmList,NR_R12);
+                  hsym:=tsym(procdefinition.parast.Find('syscalllib'));
+                  if not assigned(hsym) then
+                    internalerror(2016110605);
+                  libparaloc:=tparavarsym(hsym).paraloc[callerside].location;
+                  if not assigned(libparaloc) then
+                    internalerror(2016110604);
+
+                  case libparaloc^.loc of
+                    LOC_REGISTER:
+                      reference_reset_base(tmpref,libparaloc^.register,-tprocdef(procdefinition).extnumber,sizeof(pint));
+                    LOC_REFERENCE:
+                      begin
+                        reference_reset_base(tmpref,libparaloc^.reference.index,libparaloc^.reference.offset,sizeof(pint));
+                        cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpref,NR_R12);
+                        reference_reset_base(tmpref,NR_R12,-tprocdef(procdefinition).extnumber,sizeof(pint));
+                      end;
+                    else
+                      internalerror(2016110603);
+                  end;
+
+                  cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpref,NR_R12);
+                  cg.a_call_reg(current_asmdata.CurrAsmList,NR_R12);
+                  cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R12);
+                  exit;
+                end;
+              internalerror(2016110601);
+            end;
+        else
+          internalerror(2016110602);
+      end;
+    end;
+
   procedure tarmcallnode.set_result_location(realresdef: tstoreddef);
     begin
       if (realresdef.typ=floatdef) and 
@@ -77,6 +132,8 @@ implementation
     end;
 
 
+
+
 begin
    ccallnode:=tarmcallnode;
 end.
diff --git a/compiler/arm/symcpu.pas b/compiler/arm/symcpu.pas
index 79e89c19f2..926ef4f581 100644
--- a/compiler/arm/symcpu.pas
+++ b/compiler/arm/symcpu.pas
@@ -26,7 +26,7 @@ unit symcpu;
 interface
 
 uses
-  symtype,symdef,symsym,globtype;
+  symtype,symdef,symsym,symconst,globtype;
 
 type
   { defs }
@@ -92,9 +92,18 @@ type
 
   tcpuprocdef = class(tprocdef)
     { the arm paramanager might need to know the total size of the stackframe
-      to avoid cyclic unit dependencies or global variables, this infomatation is
+      to avoid cyclic unit dependencies or global variables, this information is
       stored in total_stackframe_size }
     total_stackframe_size : aint;
+    procedure ppuload_platform(ppufile: tcompilerppufile); override;
+    procedure ppuwrite_platform(ppufile: tcompilerppufile); override;
+   public
+    { library symbol for AROS }
+    libsym : tsym;
+    libsymderef : tderef;
+    function getcopyas(newtyp: tdeftyp; copytyp: tproccopytyp): tstoreddef; override;
+    procedure buildderef; override;
+    procedure deref; override;
   end;
   tcpuprocdefclass = class of tcpuprocdef;
 
@@ -178,6 +187,52 @@ const
 
 implementation
 
+
+{****************************************************************************
+                             tcpuprocdef
+****************************************************************************}
+
+  procedure tcpuprocdef.ppuload_platform(ppufile: tcompilerppufile);
+    begin
+      inherited;
+      if po_syscall_has_libsym in procoptions then
+        ppufile.getderef(libsymderef);
+    end;
+
+
+  procedure tcpuprocdef.ppuwrite_platform(ppufile: tcompilerppufile);
+    begin
+      inherited;
+      if po_syscall_has_libsym in procoptions then
+        ppufile.putderef(libsymderef);
+    end;
+
+
+  function tcpuprocdef.getcopyas(newtyp: tdeftyp; copytyp: tproccopytyp): tstoreddef;
+    begin
+      result:=inherited;
+      if newtyp=procdef then
+        tcpuprocdef(result).libsym:=libsym;
+    end;
+
+
+  procedure tcpuprocdef.buildderef;
+    begin
+      inherited;
+      if po_syscall_has_libsym in procoptions then
+        libsymderef.build(libsym);
+    end;
+
+
+  procedure tcpuprocdef.deref;
+    begin
+      inherited;
+      if po_syscall_has_libsym in procoptions then
+        libsym:=tsym(libsymderef.resolve)
+      else
+        libsym:=nil;
+    end;
+
 begin
   { used tdef classes }
   cfiledef:=tcpufiledef;
diff --git a/compiler/parser.pas b/compiler/parser.pas
index bddb8ce1ed..21e395b31e 100644
--- a/compiler/parser.pas
+++ b/compiler/parser.pas
@@ -119,6 +119,7 @@ implementation
            system_powerpc_amiga,
            system_powerpc_morphos,
            system_m68k_amiga,
+           system_arm_aros,
            system_i386_aros,
            system_x86_64_aros:
              include(supported_calling_conventions,pocall_syscall);
diff --git a/compiler/pdecsub.pas b/compiler/pdecsub.pas
index 4d93fff8ed..45986afae2 100644
--- a/compiler/pdecsub.pas
+++ b/compiler/pdecsub.pas
@@ -2108,7 +2108,7 @@ procedure pd_syscall(pd:tabstractprocdef);
             internalerror(2016090101);
         end;
 
-{$if defined(powerpc) or defined(m68k) or defined(i386) or defined(x86_64)}
+{$if defined(powerpc) or defined(m68k) or defined(i386) or defined(x86_64) or defined(arm)}
 const
   syscall_paranr: array[boolean] of aint =
       ( paranr_syscall_lib_last, paranr_syscall_lib_first );
@@ -2119,12 +2119,12 @@ var
   v: Tconstexprint;
   vo: tvaroptions;
   paranr: aint;
-{$endif defined(powerpc) or defined(m68k) or defined(i386) or defined(x86_64)}
+{$endif defined(powerpc) or defined(m68k) or defined(i386) or defined(x86_64) or defined(arm)}
 begin
   if (pd.typ<>procdef) and (target_info.system <> system_powerpc_amiga) then
     internalerror(2003042614);
   tprocdef(pd).forwarddef:=false;
-{$if defined(powerpc) or defined(m68k) or defined(i386) or defined(x86_64)}
+{$if defined(powerpc) or defined(m68k) or defined(i386) or defined(x86_64) or defined(arm)}
   include_po_syscall;
 
   if target_info.system = system_m68k_atari then
@@ -2173,7 +2173,7 @@ begin
       Tprocdef(pd).extnumber:=v.uvalue * sizeof(pint)
     else
       Tprocdef(pd).extnumber:=v.uvalue;
-{$endif defined(powerpc) or defined(m68k) or defined(i386) or defined(x86_64)}
+{$endif defined(powerpc) or defined(m68k) or defined(i386) or defined(x86_64) or defined(arm)}
 end;
 
 
diff --git a/compiler/ppu.pas b/compiler/ppu.pas
index 1ded2a9a8a..3882b5ec95 100644
--- a/compiler/ppu.pas
+++ b/compiler/ppu.pas
@@ -43,7 +43,7 @@ type
 {$endif Test_Double_checksum}
 
 const
-  CurrentPPUVersion = 187;
+  CurrentPPUVersion = 188;
 
 { unit flags }
   uf_init                = $000001; { unit has initialization section }