{
    Copyright (c) 2002 by Florian Klaempfl

    Implements the ARM specific part of call nodes

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    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.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 ****************************************************************************
}
unit narmcal;

{$i fpcdefs.inc}

interface

    uses
      symdef,ncal,ncgcal;

    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,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;
    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')));

                  cg.getcpuregister(current_asmdata.CurrAsmList,NR_R12);
                  get_syscall_call_ref(tmpref,NR_R12);

                  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 
         (target_info.abi<>abi_eabihf) and
         (procdefinition.proccalloption<>pocall_hardfloat) and
         ((cs_fp_emulation in current_settings.moduleswitches) or
          (current_settings.fputype in [fpu_vfpv2,fpu_vfpv3,fpu_vfpv4,fpu_vfpv3_d16,fpu_fpv4_s16])) then
        begin
          { keep the fpu values in integer registers for now, the code
            generator will move them to memory or an mmregister when necessary
            (avoids double moves in case a function result is assigned to
             another function result, or passed as a parameter) }
          case retloc.size of
            OS_32,
            OS_F32:
              location_allocate_register(current_asmdata.CurrAsmList,location,s32inttype,false);
            OS_64,
            OS_F64:
              location_allocate_register(current_asmdata.CurrAsmList,location,s64inttype,false);
            else
              internalerror(2010053008);
          end
        end
      else if (resultdef.typ=floatdef) and
         (location.loc=LOC_REGISTER) and
         (current_settings.fputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) then
        begin
          location_reset_ref(location,LOC_REFERENCE,location.size,resultdef.alignment,[]);
          tg.gethltemp(current_asmdata.CurrAsmList,resultdef,resultdef.size,tt_normal,location.reference);
        end
      else
        inherited;
    end;




begin
   ccallnode:=tarmcallnode;
end.
