mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 18:09:30 +02:00
* synchronized with trunk
git-svn-id: branches/z80@44710 -
This commit is contained in:
commit
1cfbae82c6
@ -2234,6 +2234,7 @@ implementation
|
||||
{ fpu_vfpv3_d16 } IF_VFPv2 or IF_VFPv3,
|
||||
{ fpu_fpv4_s16 } IF_NONE,
|
||||
{ fpu_vfpv4 } IF_VFPv2 or IF_VFPv3 or IF_VFPv4,
|
||||
{ fpu_vfpv4 } IF_VFPv2 or IF_VFPv3 or IF_VFPv4,
|
||||
{ fpu_neon_vfpv4 } IF_VFPv2 or IF_VFPv3 or IF_VFPv4 or IF_NEON
|
||||
);
|
||||
begin
|
||||
|
@ -116,6 +116,7 @@ unit agarmgas;
|
||||
result:='-mfpu=neon-vfpv3 '+result;
|
||||
fpu_vfpv3_d16:
|
||||
result:='-mfpu=vfpv3-d16 '+result;
|
||||
fpu_fpv4_sp_d16,
|
||||
fpu_fpv4_s16:
|
||||
result:='-mfpu=fpv4-sp-d16 '+result;
|
||||
fpu_vfpv4:
|
||||
|
@ -2084,7 +2084,7 @@ unit cgcpu;
|
||||
begin
|
||||
reference_reset(ref,4,[]);
|
||||
if (tg.direction*tcpuprocinfo(current_procinfo).floatregstart>=1023) or
|
||||
(FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[current_settings.fputype]) then
|
||||
(FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype]) then
|
||||
begin
|
||||
if not is_shifter_const(tcpuprocinfo(current_procinfo).floatregstart,shift) then
|
||||
begin
|
||||
@ -2115,14 +2115,16 @@ unit cgcpu;
|
||||
begin
|
||||
ref.index:=ref.base;
|
||||
ref.base:=NR_NO;
|
||||
{ FSTMX is deprecated on ARMv6 and later }
|
||||
{if (current_settings.cputype<cpu_armv6) then
|
||||
postfix:=PF_IAX
|
||||
else
|
||||
postfix:=PF_IAD;}
|
||||
if mmregs<>[] then
|
||||
list.concat(taicpu.op_ref_regset(A_VSTM,ref,R_MMREGISTER,R_SUBFD,mmregs));
|
||||
end
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
|
||||
begin
|
||||
ref.index:=ref.base;
|
||||
ref.base:=NR_NO;
|
||||
if mmregs<>[] then
|
||||
list.concat(taicpu.op_ref_regset(A_VSTM,ref,R_MMREGISTER,R_SUBFS,mmregs));
|
||||
end
|
||||
else
|
||||
internalerror(2019050923);
|
||||
end;
|
||||
@ -2176,7 +2178,7 @@ unit cgcpu;
|
||||
}
|
||||
end;
|
||||
end;
|
||||
else if FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[current_settings.fputype] then
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
|
||||
begin
|
||||
{ restore vfp registers? }
|
||||
{ the *[0..31] is a hack to prevent that the compiler tries to save odd single-type registers,
|
||||
@ -2193,7 +2195,7 @@ unit cgcpu;
|
||||
begin
|
||||
reference_reset(ref,4,[]);
|
||||
if (tg.direction*tcpuprocinfo(current_procinfo).floatregstart>=1023) or
|
||||
(FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[current_settings.fputype]) then
|
||||
(FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype]) then
|
||||
begin
|
||||
if not is_shifter_const(tcpuprocinfo(current_procinfo).floatregstart,shift) then
|
||||
begin
|
||||
@ -2223,13 +2225,15 @@ unit cgcpu;
|
||||
begin
|
||||
ref.index:=ref.base;
|
||||
ref.base:=NR_NO;
|
||||
{ FLDMX is deprecated on ARMv6 and later }
|
||||
{if (current_settings.cputype<cpu_armv6) then
|
||||
mmpostfix:=PF_IAX
|
||||
else
|
||||
mmpostfix:=PF_IAD;}
|
||||
if mmregs<>[] then
|
||||
list.concat(taicpu.op_ref_regset(A_VLDM,ref,R_MMREGISTER,R_SUBFD,mmregs));
|
||||
if mmregs<>[] then
|
||||
list.concat(taicpu.op_ref_regset(A_VLDM,ref,R_MMREGISTER,R_SUBFD,mmregs));
|
||||
end
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
|
||||
begin
|
||||
ref.index:=ref.base;
|
||||
ref.base:=NR_NO;
|
||||
if mmregs<>[] then
|
||||
list.concat(taicpu.op_ref_regset(A_VLDM,ref,R_MMREGISTER,R_SUBFS,mmregs));
|
||||
end
|
||||
else
|
||||
internalerror(2019050921);
|
||||
@ -4328,12 +4332,19 @@ unit cgcpu;
|
||||
rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
|
||||
[RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7],first_fpu_imreg,[]);
|
||||
|
||||
if FPUARM_HAS_32REGS in fpu_capabilities[current_settings.fputype] then
|
||||
if (FPUARM_HAS_32REGS in fpu_capabilities[current_settings.fputype]) and
|
||||
(FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[current_settings.fputype]) then
|
||||
rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBFD,
|
||||
[RS_D0,RS_D1,RS_D2,RS_D3,RS_D4,RS_D5,RS_D6,RS_D7,
|
||||
RS_D16,RS_D17,RS_D18,RS_D19,RS_D20,RS_D21,RS_D22,RS_D23,RS_D24,RS_D25,RS_D26,RS_D27,RS_D28,RS_D29,RS_D30,RS_D31,
|
||||
RS_D8,RS_D9,RS_D10,RS_D11,RS_D12,RS_D13,RS_D14,RS_D15
|
||||
],first_mm_imreg,[])
|
||||
else if (FPUARM_HAS_32REGS in fpu_capabilities[current_settings.fputype]) then
|
||||
rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBFS,
|
||||
[RS_S0,RS_S1,RS_S2,RS_S3,RS_S4,RS_S5,RS_S6,RS_S7,
|
||||
RS_S16,RS_S17,RS_S18,RS_S19,RS_S20,RS_S21,RS_S22,RS_S23,RS_S24,RS_S25,RS_S26,RS_S27,RS_S28,RS_S29,RS_S30,RS_S31,
|
||||
RS_S8,RS_S9,RS_S10,RS_S11,RS_S12,RS_S13,RS_S14,RS_S15
|
||||
],first_mm_imreg,[])
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
|
||||
rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBFD,
|
||||
[RS_D0,RS_D1,RS_D2,RS_D3,RS_D4,RS_D5,RS_D6,RS_D7,
|
||||
|
@ -73,8 +73,9 @@ Type
|
||||
fpu_vfpv3,
|
||||
fpu_neon_vfpv3,
|
||||
fpu_vfpv3_d16,
|
||||
fpu_fpv4_s16,
|
||||
fpu_fpv4_s16, { same as fpu_fpv4_sp_d32, kept for backwards compatibility }
|
||||
fpu_vfpv4,
|
||||
fpu_fpv4_sp_d16, { 32 registers single precision, for load/store/move they can be accessed as 16 double registers }
|
||||
fpu_neon_vfpv4
|
||||
{ when new elements added afterwards, update also fpu_vfp_last below and
|
||||
update class procedure tarmnodeutils.InsertObjectInfo; in narmutil.pas }
|
||||
@ -84,7 +85,7 @@ Const
|
||||
fpu_vfp_first = fpu_vfpv2;
|
||||
fpu_vfp_last = fpu_neon_vfpv4;
|
||||
|
||||
fputypestrllvm : array[tfputype] of string[14] = ('',
|
||||
fputypestrllvm : array[tfputype] of string[15] = ('',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
@ -96,6 +97,7 @@ Const
|
||||
'fpu=vfpv3-d16',
|
||||
'fpu=vfpv4-s16',
|
||||
'fpu=vfpv4',
|
||||
'fpu=fpv4-sp-d16',
|
||||
'fpu=neon-vfpv4'
|
||||
);
|
||||
|
||||
@ -570,7 +572,7 @@ Const
|
||||
'ARMV7EM'
|
||||
);
|
||||
|
||||
fputypestr : array[tfputype] of string[10] = (
|
||||
fputypestr : array[tfputype] of string[11] = (
|
||||
'NONE',
|
||||
'SOFT',
|
||||
'LIBGCC',
|
||||
@ -583,6 +585,7 @@ Const
|
||||
'VFPV3_D16',
|
||||
'FPV4_S16',
|
||||
'VFPV4',
|
||||
'FPV4_SP_D16',
|
||||
'NEON_VFPV4'
|
||||
);
|
||||
|
||||
@ -1071,9 +1074,9 @@ Const
|
||||
tfpuflags =
|
||||
(
|
||||
FPUARM_HAS_FPA, { fpu is an fpa based FPU }
|
||||
FPUARM_HAS_VFP_EXTENSION, { fpu is a vfp extension }
|
||||
FPUARM_HAS_VFP_EXTENSION, { fpu is a vfp extension, it means at least single operation support }
|
||||
FPUARM_HAS_VFP_DOUBLE, { vfp has double support }
|
||||
FPUARM_HAS_VFP_SINGLE_ONLY, { vfp has only single support, disjunct to FPUARM_HAS_VFP_DOUBLE, for error checking }
|
||||
FPUARM_HAS_VFP_DOUBLE_MOVLDST, { vfp has only single support, but MOV, LD, ST can be done on pairs as double }
|
||||
FPUARM_HAS_32REGS, { vfp has 32 regs, without this flag, 16 are assumed }
|
||||
FPUARM_HAS_VMOV_CONST, { vmov supports (some) real constants }
|
||||
FPUARM_HAS_EXCEPTION_TRAPPING, { vfp does exceptions trapping }
|
||||
@ -1105,19 +1108,20 @@ Const
|
||||
);
|
||||
|
||||
fpu_capabilities : array[tfputype] of set of tfpuflags =
|
||||
( { fpu_none } [],
|
||||
{ fpu_soft } [],
|
||||
{ fpu_libgcc } [],
|
||||
{ fpu_fpa } [FPUARM_HAS_FPA],
|
||||
{ fpu_fpa10 } [FPUARM_HAS_FPA],
|
||||
{ fpu_fpa11 } [FPUARM_HAS_FPA],
|
||||
{ fpu_vfpv2 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_VFP_DOUBLE],
|
||||
{ fpu_vfpv3 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_VFP_DOUBLE,FPUARM_HAS_32REGS,FPUARM_HAS_VMOV_CONST],
|
||||
{ fpu_neon_vfpv3 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_VFP_DOUBLE,FPUARM_HAS_32REGS,FPUARM_HAS_VMOV_CONST,FPUARM_HAS_NEON],
|
||||
{ fpu_vfpv3_d16 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_VFP_DOUBLE,FPUARM_HAS_VMOV_CONST],
|
||||
{ fpu_fpv4_s16 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_VFP_SINGLE_ONLY,FPUARM_HAS_VMOV_CONST],
|
||||
{ fpu_vfpv4 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_VFP_DOUBLE,FPUARM_HAS_32REGS,FPUARM_HAS_VMOV_CONST,FPUARM_HAS_FMA],
|
||||
{ fpu_neon_vfpv4 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_VFP_DOUBLE,FPUARM_HAS_32REGS,FPUARM_HAS_VMOV_CONST,FPUARM_HAS_NEON,FPUARM_HAS_FMA]
|
||||
( { fpu_none } [],
|
||||
{ fpu_soft } [],
|
||||
{ fpu_libgcc } [],
|
||||
{ fpu_fpa } [FPUARM_HAS_FPA],
|
||||
{ fpu_fpa10 } [FPUARM_HAS_FPA],
|
||||
{ fpu_fpa11 } [FPUARM_HAS_FPA],
|
||||
{ fpu_vfpv2 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_VFP_DOUBLE],
|
||||
{ fpu_vfpv3 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_VFP_DOUBLE,FPUARM_HAS_32REGS,FPUARM_HAS_VMOV_CONST],
|
||||
{ fpu_neon_vfpv3 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_VFP_DOUBLE,FPUARM_HAS_32REGS,FPUARM_HAS_VMOV_CONST,FPUARM_HAS_NEON],
|
||||
{ fpu_vfpv3_d16 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_VFP_DOUBLE,FPUARM_HAS_VMOV_CONST],
|
||||
{ fpu_fpv4_s16 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_32REGS,FPUARM_HAS_VFP_DOUBLE_MOVLDST,FPUARM_HAS_VMOV_CONST,FPUARM_HAS_FMA],
|
||||
{ fpu_vfpv4 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_VFP_DOUBLE,FPUARM_HAS_32REGS,FPUARM_HAS_VMOV_CONST,FPUARM_HAS_FMA],
|
||||
{ fpu_fpv4_sp_d16 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_32REGS,FPUARM_HAS_VFP_DOUBLE_MOVLDST,FPUARM_HAS_VMOV_CONST,FPUARM_HAS_FMA],
|
||||
{ fpu_neon_vfpv4 } [FPUARM_HAS_VFP_EXTENSION,FPUARM_HAS_VFP_DOUBLE,FPUARM_HAS_32REGS,FPUARM_HAS_VMOV_CONST,FPUARM_HAS_NEON,FPUARM_HAS_FMA]
|
||||
);
|
||||
|
||||
{ contains all CPU supporting any kind of thumb instruction set }
|
||||
|
@ -149,7 +149,7 @@ unit cpupara;
|
||||
getparaloc:=LOC_MMREGISTER
|
||||
else if (calloption in cdecl_pocalls) or
|
||||
(cs_fp_emulation in current_settings.moduleswitches) or
|
||||
(current_settings.fputype in [fpu_vfp_first..fpu_vfp_last]) then
|
||||
(FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype]) then
|
||||
{ the ARM eabi also allows passing VFP values via VFP registers,
|
||||
but Mac OS X doesn't seem to do that and linux only does it if
|
||||
built with the "-mfloat-abi=hard" option }
|
||||
@ -782,7 +782,7 @@ unit cpupara;
|
||||
end
|
||||
else if (p.proccalloption in [pocall_softfloat]) or
|
||||
(cs_fp_emulation in current_settings.moduleswitches) or
|
||||
(current_settings.fputype in [fpu_vfp_first..fpu_vfp_last]) then
|
||||
(FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype]) then
|
||||
begin
|
||||
case retcgsize of
|
||||
OS_64,
|
||||
|
@ -240,7 +240,7 @@ interface
|
||||
location.register,left.location.register,right.location.register),pf));
|
||||
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
|
||||
end
|
||||
else if FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype] then
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
|
||||
begin
|
||||
{ force mmreg as location, left right doesn't matter
|
||||
as both will be in a fpureg }
|
||||
@ -326,7 +326,7 @@ interface
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_VMRS,NR_APSR_nzcv,NR_FPSCR));
|
||||
location.resflags:=GetFpuResFlags;
|
||||
end
|
||||
else if FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype] then
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
|
||||
begin
|
||||
hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
|
||||
hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
|
||||
@ -576,77 +576,19 @@ interface
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function tarmaddnode.first_addfloat: tnode;
|
||||
var
|
||||
procname: string[31];
|
||||
{ do we need to reverse the result ? }
|
||||
notnode : boolean;
|
||||
fdef : tdef;
|
||||
begin
|
||||
result := nil;
|
||||
notnode := false;
|
||||
|
||||
if FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype] then
|
||||
if (FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype]) and
|
||||
not(FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[current_settings.fputype]) then
|
||||
begin
|
||||
case tfloatdef(left.resultdef).floattype of
|
||||
s32real:
|
||||
begin
|
||||
result:=nil;
|
||||
notnode:=false;
|
||||
end;
|
||||
;
|
||||
s64real:
|
||||
begin
|
||||
fdef:=search_system_type('FLOAT64').typedef;
|
||||
procname:='float64';
|
||||
|
||||
case nodetype of
|
||||
addn:
|
||||
procname:=procname+'_add';
|
||||
muln:
|
||||
procname:=procname+'_mul';
|
||||
subn:
|
||||
procname:=procname+'_sub';
|
||||
slashn:
|
||||
procname:=procname+'_div';
|
||||
ltn:
|
||||
procname:=procname+'_lt';
|
||||
lten:
|
||||
procname:=procname+'_le';
|
||||
gtn:
|
||||
begin
|
||||
procname:=procname+'_lt';
|
||||
swapleftright;
|
||||
end;
|
||||
gten:
|
||||
begin
|
||||
procname:=procname+'_le';
|
||||
swapleftright;
|
||||
end;
|
||||
equaln:
|
||||
procname:=procname+'_eq';
|
||||
unequaln:
|
||||
begin
|
||||
procname:=procname+'_eq';
|
||||
notnode:=true;
|
||||
end;
|
||||
else
|
||||
CGMessage3(type_e_operator_not_supported_for_types,node2opstr(nodetype),left.resultdef.typename,right.resultdef.typename);
|
||||
end;
|
||||
|
||||
if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
|
||||
resultdef:=pasbool1type;
|
||||
result:=ctypeconvnode.create_internal(ccallnode.createintern(procname,ccallparanode.create(
|
||||
ctypeconvnode.create_internal(right,fdef),
|
||||
ccallparanode.create(
|
||||
ctypeconvnode.create_internal(left,fdef),nil))),resultdef);
|
||||
|
||||
left:=nil;
|
||||
right:=nil;
|
||||
|
||||
{ do we need to reverse the result }
|
||||
if notnode then
|
||||
result:=cnotnode.create(result);
|
||||
end;
|
||||
result:=first_addfloat_soft;
|
||||
else
|
||||
internalerror(2019050933);
|
||||
end;
|
||||
|
@ -60,7 +60,7 @@ implementation
|
||||
{$ifdef cpufpemu}
|
||||
(current_settings.fputype=fpu_soft) or
|
||||
{$endif cpufpemu}
|
||||
(FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype]) then
|
||||
not(FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[current_settings.fputype]) then
|
||||
result:=inherited first_int_to_real
|
||||
else
|
||||
begin
|
||||
@ -109,7 +109,7 @@ implementation
|
||||
|
||||
function tarmtypeconvnode.first_real_to_real: tnode;
|
||||
begin
|
||||
if FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype] then
|
||||
if not(FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[current_settings.fputype]) then
|
||||
begin
|
||||
case tfloatdef(left.resultdef).floattype of
|
||||
s32real:
|
||||
@ -237,7 +237,7 @@ implementation
|
||||
location.register,left.location.register),
|
||||
signedprec2vfppf[signed,location.size]));
|
||||
end
|
||||
else if FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype] then
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
|
||||
begin
|
||||
location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
|
||||
signed:=left.location.size=OS_S32;
|
||||
|
@ -55,7 +55,9 @@ interface
|
||||
begin
|
||||
result:=nil;
|
||||
if (FPUARM_HAS_VMOV_CONST in fpu_capabilities[current_settings.fputype]) and
|
||||
IsVFPFloatImmediate(tfloatdef(resultdef).floattype,value_real) then
|
||||
IsVFPFloatImmediate(tfloatdef(resultdef).floattype,value_real) and
|
||||
((tfloatdef(resultdef).floattype=s32real) or
|
||||
(FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[init_settings.fputype])) then
|
||||
expectloc:=LOC_MMREGISTER
|
||||
else
|
||||
expectloc:=LOC_CREFERENCE;
|
||||
@ -76,7 +78,9 @@ interface
|
||||
|
||||
begin
|
||||
if (FPUARM_HAS_VMOV_CONST in fpu_capabilities[current_settings.fputype]) and
|
||||
IsVFPFloatImmediate(tfloatdef(resultdef).floattype,value_real) then
|
||||
IsVFPFloatImmediate(tfloatdef(resultdef).floattype,value_real) and
|
||||
((tfloatdef(resultdef).floattype=s32real) or
|
||||
(FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[init_settings.fputype])) then
|
||||
begin
|
||||
location_reset(location,LOC_MMREGISTER,def_cgsize(resultdef));
|
||||
location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
|
||||
|
@ -125,7 +125,7 @@ implementation
|
||||
expectloc:=LOC_FPUREGISTER;
|
||||
else if FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[current_settings.fputype] then
|
||||
expectloc:=LOC_MMREGISTER
|
||||
else if FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype] then
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
|
||||
begin
|
||||
if tfloatdef(left.resultdef).floattype=s32real then
|
||||
expectloc:=LOC_MMREGISTER
|
||||
@ -153,7 +153,7 @@ implementation
|
||||
expectloc:=LOC_FPUREGISTER;
|
||||
else if FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[current_settings.fputype] then
|
||||
expectloc:=LOC_MMREGISTER
|
||||
else if FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype] then
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
|
||||
begin
|
||||
if tfloatdef(left.resultdef).floattype=s32real then
|
||||
expectloc:=LOC_MMREGISTER
|
||||
@ -181,7 +181,7 @@ implementation
|
||||
expectloc:=LOC_FPUREGISTER;
|
||||
else if FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[current_settings.fputype] then
|
||||
expectloc:=LOC_MMREGISTER
|
||||
else if FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype] then
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
|
||||
begin
|
||||
if tfloatdef(left.resultdef).floattype=s32real then
|
||||
expectloc:=LOC_MMREGISTER
|
||||
@ -265,7 +265,7 @@ implementation
|
||||
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VABS,location.register,left.location.register),pf));
|
||||
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
|
||||
end
|
||||
else if FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype] then
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
|
||||
begin
|
||||
current_asmdata.CurrAsmList.Concat(setoppostfix(taicpu.op_reg_reg(A_VABS,location.register,left.location.register), PF_F32));
|
||||
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
|
||||
@ -296,7 +296,7 @@ implementation
|
||||
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_VMUL,location.register,left.location.register,left.location.register),pf));
|
||||
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
|
||||
end
|
||||
else if FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype] then
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
|
||||
begin
|
||||
current_asmdata.CurrAsmList.Concat(setoppostfix(taicpu.op_reg_reg_reg(A_VMUL,location.register,left.location.register,left.location.register), PF_F32));
|
||||
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
|
||||
@ -327,7 +327,7 @@ implementation
|
||||
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VSQRT,location.register,left.location.register),pf));
|
||||
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
|
||||
end
|
||||
else if FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype] then
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
|
||||
begin
|
||||
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VSQRT,location.register,left.location.register), PF_F32));
|
||||
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
|
||||
|
@ -367,7 +367,7 @@ implementation
|
||||
exit;
|
||||
end;
|
||||
|
||||
if not(FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[current_settings.fputype]) or
|
||||
if (FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[current_settings.fputype]) or
|
||||
(tfloatdef(resultdef).floattype=s32real) then
|
||||
exit(inherited pass_1);
|
||||
|
||||
@ -447,7 +447,7 @@ implementation
|
||||
location.register,left.location.register), pf));
|
||||
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
|
||||
end
|
||||
else if FPUARM_HAS_VFP_SINGLE_ONLY in fpu_capabilities[init_settings.fputype] then
|
||||
else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[init_settings.fputype] then
|
||||
begin
|
||||
hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
|
||||
location:=left.location;
|
||||
|
@ -207,6 +207,7 @@ interface
|
||||
current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,3));
|
||||
fpu_vfpv3_d16:
|
||||
current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,4));
|
||||
fpu_fpv4_sp_d16,
|
||||
fpu_fpv4_s16:
|
||||
current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,6));
|
||||
fpu_vfpv4,
|
||||
|
@ -951,6 +951,7 @@ implementation
|
||||
Replace(s,'$FPCDATE',date_string);
|
||||
Replace(s,'$FPCCPU',target_cpu_string);
|
||||
Replace(s,'$FPCOS',target_os_string);
|
||||
Replace(s,'$FPCBINDIR',exepath);
|
||||
if (tf_use_8_3 in Source_Info.Flags) or
|
||||
(tf_use_8_3 in Target_Info.Flags) then
|
||||
Replace(s,'$FPCTARGET',target_os_string)
|
||||
|
@ -2361,6 +2361,10 @@ implementation
|
||||
{$ifdef xtensa}
|
||||
and (FPUXTENSA_SINGLE in fpu_capabilities[init_settings.fputype]) and (tfloatdef(self).floattype=s32real)
|
||||
{$endif xtensa}
|
||||
{$ifdef arm}
|
||||
and (((FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[init_settings.fputype]) and (tfloatdef(self).floattype=s32real)) or
|
||||
(FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[init_settings.fputype]))
|
||||
{$endif arm}
|
||||
;
|
||||
{$endif x86}
|
||||
end;
|
||||
|
@ -439,9 +439,9 @@ interface
|
||||
(name: 'AIX' ; supported:{$if defined(powerpc) or defined(powerpc64)}true{$else}false{$endif}),
|
||||
(name: 'DARWIN' ; supported:{$if defined(powerpc) or defined(powerpc64)}true{$else}false{$endif}),
|
||||
(name: 'ELFV2' ; supported:{$if defined(powerpc64)}true{$else}false{$endif}),
|
||||
(name: 'EABI' ; supported:{$ifdef FPC_ARMEL}true{$else}false{$endif}),
|
||||
(name: 'EABI' ; supported:{$if defined(arm)}true{$else}false{$endif}),
|
||||
(name: 'ARMEB' ; supported:{$ifdef FPC_ARMEB}true{$else}false{$endif}),
|
||||
(name: 'EABIHF' ; supported:{$ifdef FPC_ARMHF}true{$else}false{$endif}),
|
||||
(name: 'EABIHF' ; supported:{$if defined(arm)}true{$else}false{$endif}),
|
||||
(name: 'OLDWIN32GNU'; supported:{$ifdef I386}true{$else}false{$endif}),
|
||||
(name: 'AARCH64IOS'; supported:{$ifdef aarch64}true{$else}false{$endif}),
|
||||
(name: 'RISCVHF'; supported:{$if defined(riscv32) or defined(riscv64)}true{$else}false{$endif}),
|
||||
|
@ -150,14 +150,16 @@ begin
|
||||
{$ifdef arm}
|
||||
{ some newer Debian have the crt*.o files at uncommon locations,
|
||||
for other arm flavours, this cannot hurt }
|
||||
{$ifdef FPC_ARMHF}
|
||||
LibrarySearchPath.AddLibraryPath(sysrootpath,'=/usr/lib/arm-linux-gnueabihf',true);
|
||||
LibrarySearchPath.AddLibraryPath(sysrootpath,'=/lib/arm-linux-gnueabihf',true);
|
||||
{$endif FPC_ARMHF}
|
||||
{$ifdef FPC_ARMEL}
|
||||
LibrarySearchPath.AddLibraryPath(sysrootpath,'=/usr/lib/arm-linux-gnueabi',true);
|
||||
LibrarySearchPath.AddLibraryPath(sysrootpath,'=/lib/arm-linux-gnueabi',true);
|
||||
{$endif}
|
||||
if target_info.abi=abi_eabihf then
|
||||
begin
|
||||
LibrarySearchPath.AddLibraryPath(sysrootpath,'=/usr/lib/arm-linux-gnueabihf',true);
|
||||
LibrarySearchPath.AddLibraryPath(sysrootpath,'=/lib/arm-linux-gnueabihf',true);
|
||||
end;
|
||||
if target_info.abi=abi_eabi then
|
||||
begin
|
||||
LibrarySearchPath.AddLibraryPath(sysrootpath,'=/usr/lib/arm-linux-gnueabi',true);
|
||||
LibrarySearchPath.AddLibraryPath(sysrootpath,'=/lib/arm-linux-gnueabi',true);
|
||||
end;
|
||||
{$endif arm}
|
||||
{$ifdef x86_64}
|
||||
LibrarySearchPath.AddLibraryPath(sysrootpath,'=/usr/lib/x86_64-linux-gnu',true);
|
||||
|
@ -1081,33 +1081,37 @@ Var
|
||||
Res: Integer;
|
||||
begin
|
||||
SetLength(EnvList, 0);
|
||||
ThisProcess := PProcess(FindTask(nil)); //Get the pointer to our process
|
||||
LocalVars_List := @(ThisProcess^.pr_LocalVars); //get the list of pr_LocalVars as pointer
|
||||
LocalVar_Node := pLocalVar(LocalVars_List^.mlh_head); //get the headnode of the LocalVars list
|
||||
|
||||
// loop through the localvar list
|
||||
while ( Pointer(LocalVar_Node^.lv_node.ln_Succ) <> Pointer(LocalVars_List^.mlh_Tail)) do
|
||||
// pr_LocalVars are introduced with OS2.0
|
||||
if PLibrary(AOS_ExecBase)^.lib_Version >= 36 then
|
||||
begin
|
||||
// make sure the active node is valid instead of empty
|
||||
If not(LocalVar_Node <> nil) then
|
||||
break;
|
||||
ThisProcess := PProcess(FindTask(nil)); //Get the pointer to our process
|
||||
LocalVars_List := @(ThisProcess^.pr_LocalVars); //get the list of pr_LocalVars as pointer
|
||||
LocalVar_Node := pLocalVar(LocalVars_List^.mlh_head); //get the headnode of the LocalVars list
|
||||
|
||||
{ - process the current node - }
|
||||
If (LocalVar_Node^.lv_node.ln_Type = LV_Var) then
|
||||
// loop through the localvar list
|
||||
while ( Pointer(LocalVar_Node^.lv_node.ln_Succ) <> Pointer(LocalVars_List^.mlh_Tail)) do
|
||||
begin
|
||||
FillChar(Buffer[0], Length(Buffer), #0); // clear Buffer
|
||||
// make sure the active node is valid instead of empty
|
||||
If not(LocalVar_Node <> nil) then
|
||||
break;
|
||||
|
||||
// get active node's name environment variable value ino buffer and make sure it's local
|
||||
TempLen := GetVar(LocalVar_Node^.lv_Node.ln_Name, @Buffer[0], BUFFER_SIZE, GVF_LOCAL_ONLY);
|
||||
If TempLen <> -1 then
|
||||
{ - process the current node - }
|
||||
If (LocalVar_Node^.lv_node.ln_Type = LV_Var) then
|
||||
begin
|
||||
SetLength(EnvList, Length(EnvList) + 1);
|
||||
EnvList[High(EnvList)].Name := LocalVar_Node^.lv_Node.ln_Name;
|
||||
EnvList[High(EnvList)].Value := string(PChar(@Buffer[0]));
|
||||
EnvList[High(EnvList)].Local := True;
|
||||
FillChar(Buffer[0], Length(Buffer), #0); // clear Buffer
|
||||
|
||||
// get active node's name environment variable value ino buffer and make sure it's local
|
||||
TempLen := GetVar(LocalVar_Node^.lv_Node.ln_Name, @Buffer[0], BUFFER_SIZE, GVF_LOCAL_ONLY);
|
||||
If TempLen <> -1 then
|
||||
begin
|
||||
SetLength(EnvList, Length(EnvList) + 1);
|
||||
EnvList[High(EnvList)].Name := LocalVar_Node^.lv_Node.ln_Name;
|
||||
EnvList[High(EnvList)].Value := string(PChar(@Buffer[0]));
|
||||
EnvList[High(EnvList)].Local := True;
|
||||
end;
|
||||
end;
|
||||
LocalVar_Node := pLocalVar(LocalVar_Node^.lv_node.ln_Succ); //we need to get the next node
|
||||
end;
|
||||
LocalVar_Node := pLocalVar(LocalVar_Node^.lv_node.ln_Succ); //we need to get the next node
|
||||
end;
|
||||
// search in env for all Variables
|
||||
FillChar(Anchor,sizeof(TAnchorPath),#0);
|
||||
|
@ -113,29 +113,191 @@ begin
|
||||
NextDosEntry:=nil;
|
||||
end;
|
||||
|
||||
// Very first dirty version of MatchFirst/Next/End)
|
||||
//TODO: pattern detection, for now only simple "*" or "#?" or full name (without patterns) is supported
|
||||
function MatchFirst(pat : PChar;
|
||||
anchor: PAnchorPath): LongInt; public name '_fpc_amiga_matchfirst';
|
||||
var
|
||||
p: PChar;
|
||||
len: LongInt;
|
||||
Path,FileN: AnsiString;
|
||||
LastSeparatorPos: Integer;
|
||||
i: Integer;
|
||||
DirLock: BPTR;
|
||||
ib: TFileInfoBlock;
|
||||
Res: LongInt;
|
||||
NChain: PAChain;
|
||||
begin
|
||||
{$warning MatchFirst unimplemented!}
|
||||
MatchFirst:=-1;
|
||||
MatchFirst := -1;
|
||||
if not Assigned(Anchor) then
|
||||
Exit;
|
||||
// Search for last '/' or ':' and determine length
|
||||
Len := strlen(Pat);
|
||||
P := Pat;
|
||||
LastSeparatorPos := 0;
|
||||
for i := 1 to Len do
|
||||
begin
|
||||
if (P^ = '/') or (P^ = ':') then
|
||||
begin
|
||||
LastSeparatorPos := i;
|
||||
end;
|
||||
Inc(P);
|
||||
end;
|
||||
// copy Directory name
|
||||
SetLength(Path, LastSeparatorPos);
|
||||
Move(Pat^, Path[1], LastSeparatorPos);
|
||||
// copy filename
|
||||
SetLength(FileN, Len - LastSeparatorPos);
|
||||
P := Pat;
|
||||
Inc(P, LastSeparatorPos);
|
||||
Move(P^, FileN[1], Len - LastSeparatorPos);
|
||||
// searchpattern lowercase
|
||||
FileN := LowerCase(FileN);
|
||||
|
||||
// if no path is given use the current working dir, or try to lock the dir
|
||||
if Path = '' then
|
||||
DirLock := CurrentDir(0)
|
||||
else
|
||||
DirLock := Lock(PChar(Path), ACCESS_READ);
|
||||
//
|
||||
// no dirlock found -> dir not found
|
||||
if DirLock = 0 then
|
||||
begin
|
||||
MatchFirst := -1;
|
||||
Exit;
|
||||
end;
|
||||
// examine the dir to get the fib for ExNext
|
||||
if Examine(DirLock, @ib) = 0 then
|
||||
begin
|
||||
MatchFirst := -1;
|
||||
Exit;
|
||||
end;
|
||||
// we search here directly what we need to find
|
||||
// guess it's not meant that way but works
|
||||
repeat
|
||||
// get next dir entry
|
||||
Res := ExNext(DirLock, @ib);
|
||||
// nothing nore found -> exit
|
||||
if Res = 0 then
|
||||
break;
|
||||
// include some nifty pattern compare here? later maybe!
|
||||
if (FileN = '*') or (FileN = '#?') or (FileN = lowercase(AnsiString(ib.fib_FileName))) then
|
||||
begin
|
||||
// Match found
|
||||
// new chain
|
||||
NChain := AllocMem(SizeOf(TAChain));
|
||||
if Assigned(Anchor^.ap_First) then
|
||||
begin
|
||||
// put chain entry to the list
|
||||
Anchor^.ap_Last^.an_Child := NChain;
|
||||
NChain^.an_Parent := Anchor^.ap_Last;
|
||||
Anchor^.ap_Last := NChain;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// first chain Entry
|
||||
Anchor^.ap_Last := NChain;
|
||||
Anchor^.ap_First := NChain;
|
||||
NChain^.an_Parent := Pointer(Anchor);
|
||||
end;
|
||||
// copy the fileinfoblock into the chain
|
||||
Move(ib, NChain^.an_Info, SizeOf(TFileInfoBlock));
|
||||
end;
|
||||
until Res = 0; // useless... we jump oput earlier
|
||||
//
|
||||
// if we found something
|
||||
if Assigned(Anchor^.ap_Last) then
|
||||
begin
|
||||
// set current to the first entry we found
|
||||
Anchor^.ap_Last := Anchor^.ap_First;
|
||||
// we only copy the file info block, rest is not needed for freepascal stuff
|
||||
Move(Anchor^.ap_First^.an_Info, Anchor^.ap_Info, SizeOf(TFileInfoBlock));
|
||||
// most importantly set the return code
|
||||
MatchFirst := 0;
|
||||
end;
|
||||
Unlock(DirLock);
|
||||
end;
|
||||
|
||||
function MatchNext(anchor: PAnchorPath): LongInt; public name '_fpc_amiga_matchnext';
|
||||
begin
|
||||
{$warning MatchNext unimplemented!}
|
||||
MatchNext:=-1;
|
||||
MatchNext := -1;
|
||||
if not Assigned(Anchor) then
|
||||
Exit;
|
||||
// was already last entry?
|
||||
if not Assigned(Anchor^.ap_Last) then
|
||||
Exit;
|
||||
// Get the next Chain Entry
|
||||
anchor^.ap_Last := anchor^.ap_Last^.an_Child;
|
||||
// check if next one is valid and copy the file infoblock, or just set the error code ;)
|
||||
if Assigned(anchor^.ap_Last) then
|
||||
begin
|
||||
Move(Anchor^.ap_Last^.an_Info, Anchor^.ap_Info, SizeOf(TFileInfoBlock));
|
||||
MatchNext := 0;
|
||||
end
|
||||
else
|
||||
MatchNext := ERROR_NO_MORE_ENTRIES;
|
||||
end;
|
||||
|
||||
procedure MatchEnd(anchor: PAnchorPath); public name '_fpc_amiga_matchend';
|
||||
var
|
||||
p, nextp: PAChain;
|
||||
begin
|
||||
{$warning MatchEnd unimplemented!}
|
||||
if Assigned(Anchor) then
|
||||
begin
|
||||
// destroy all the chain entries we created before
|
||||
p := Anchor^.ap_First;
|
||||
while Assigned(p) do
|
||||
begin
|
||||
Nextp := p^.an_Child;
|
||||
FreeMem(P);
|
||||
P := NextP;
|
||||
end;
|
||||
// reset the contents (is this needed?)
|
||||
Anchor^.ap_First := nil;
|
||||
Anchor^.ap_Last := nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure NextTag(var Tag: PTagItem); inline;
|
||||
begin
|
||||
if Tag^.ti_Tag = TAG_END then
|
||||
Exit;
|
||||
Inc(Tag);
|
||||
repeat
|
||||
case Tag^.ti_Tag of
|
||||
TAG_IGNORE: Inc(Tag);
|
||||
TAG_SKIP: Inc(Tag, Tag^.ti_Data);
|
||||
TAG_MORE: Tag := PTagItem(Tag^.ti_Data);
|
||||
else
|
||||
Break;
|
||||
end;
|
||||
until False;
|
||||
end;
|
||||
|
||||
// we emulate that by the old execute command, should be enough for most cases
|
||||
function SystemTagList(command: PChar;
|
||||
tags : PTagItem): LongInt; public name '_fpc_amiga_systemtaglist';
|
||||
var
|
||||
I,O: BPTR; // in / ouput handles
|
||||
tag: PTagItem;
|
||||
begin
|
||||
{$warning SystemTagList unimplemented!}
|
||||
SystemTagList:=-1;
|
||||
i := 0;
|
||||
O := 0;
|
||||
tag := Tags;
|
||||
if Assigned(tag) then
|
||||
begin
|
||||
repeat
|
||||
case Tag^.ti_Tag of
|
||||
SYS_Input: I := Tag^.ti_Data;
|
||||
SYS_Output: O := Tag^.ti_Data;
|
||||
end;
|
||||
NextTag(Tag);
|
||||
until tag^.ti_Tag = TAG_END;
|
||||
end;
|
||||
if Execute(command, I, O) then
|
||||
SystemTagList := 0
|
||||
else
|
||||
SystemTagList := -1;
|
||||
end;
|
||||
|
||||
function GetVar(name : PChar;
|
||||
@ -181,7 +343,7 @@ begin
|
||||
begin
|
||||
pn:=PChar(pcli^.cli_CommandName shl 2) + 1;
|
||||
pl:=Byte(pn[-1]);
|
||||
if pl > len-1 then
|
||||
if pl > len-1 then
|
||||
pl:=len-1;
|
||||
move(pn[0],buf[0],pl);
|
||||
GetProgramName:=true;
|
||||
|
@ -22,14 +22,133 @@
|
||||
functional enough for the RTL code.
|
||||
}
|
||||
|
||||
const
|
||||
// Start day of every month (without leap)
|
||||
StartOfMonth: array[0..11] of LongInt = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
|
||||
SecsPerMin = 60;
|
||||
SecsPerHour = 60 * SecsPerMin;
|
||||
SecsPerDay = 24 * SecsPerHour;
|
||||
SecsPerYear = 365 * SecsPerDay;// without leap
|
||||
AmigaStartYear = 1978; // Amiga starts @1978;
|
||||
DaysPerYear = 365;
|
||||
DaysPerLeapYear = DaysPerYear + 1;
|
||||
Daysof4Years = DaysPerLeapYear + 3 * DaysPerYear;
|
||||
Daysof100Years = 24 * DaysPerLeapYear + 76 * DaysPerYear;
|
||||
Daysof400Years = 97 * DaysPerLeapYear + 303 * DaysPerYear;
|
||||
|
||||
|
||||
procedure Amiga2Date(seconds: Cardinal;
|
||||
result : PClockData); public name '_fpc_amiga_amiga2date';
|
||||
begin
|
||||
{$warning Amiga2Date unimplemented!}
|
||||
var
|
||||
IsLeap: boolean;
|
||||
d, y, i: LongWord;
|
||||
begin// how many days are passed
|
||||
d := seconds div SecsPerDay;
|
||||
|
||||
// the easier time part
|
||||
Result^.wday := d mod 7;
|
||||
Result^.sec := seconds mod 60;
|
||||
seconds := seconds div 60;
|
||||
Result^.min := seconds mod 60;
|
||||
seconds := seconds div 60;
|
||||
Result^.hour := seconds mod 24;
|
||||
|
||||
// the leap year correction part
|
||||
IsLeap := True;
|
||||
//
|
||||
// before 2100 easier case (function mostly used for now(), so its usually in this range)
|
||||
if d < 92 * DaysPerYear + 30 * DaysPerLeapYear then // 1978 - 2100 = 92 non leap, 30 leap years
|
||||
begin
|
||||
d := d + DaysPerLeapYear + DaysPerYear; // we want to start from 1976 (a leap year) so we add 2 more years to the nubmer we have
|
||||
y := 4 *(d div Daysof4Years) + 1976; // how many 4 year spans (1 leap + 3 non leap) are there?
|
||||
d := d mod Daysof4Years; //( get the day in the 4 year span)
|
||||
// the first yoear of such a 4 year span, is always a leap year, all other not (thats the reason we want to start at 1976)
|
||||
if d > DaysPerLeapYear then
|
||||
begin
|
||||
IsLeap := False;
|
||||
d := d - 1;
|
||||
y := y + d div DaysPerYear;
|
||||
d := d mod DaysPerYear;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// more complicated way for dates > 2100 (not tested until now!)
|
||||
// we do the same as before but not 4 years together but 400 (because of the special years which are not leap even divided by 4)
|
||||
// and we start at 2000
|
||||
d := d - 17 * DaysPerYear + 5 * DaysPerLeapYear;
|
||||
y := 400 * (d div Daysof400Years) + 2000;
|
||||
d := d mod Daysof400Years;
|
||||
// first is always NOT leap year.. other we have to test
|
||||
if d >= DaysPerLeapYear then
|
||||
begin
|
||||
// we do the same again, and test for 100 year spans
|
||||
d := d - 1; // not a leap year one day down
|
||||
IsLeap := False;
|
||||
y := y + 100 * (d div Daysof100Years);
|
||||
d := d mod Daysof100Years;
|
||||
if d >= DaysPerYear then
|
||||
begin
|
||||
d := d + 1; // a leap year, one day up
|
||||
IsLeap := True;
|
||||
// and the same as we did before 4 years span
|
||||
y := y + 4 * (d div Daysof4Years);
|
||||
d := d mod Daysof4Years;
|
||||
if d >= DaysPerLeapYear then
|
||||
begin
|
||||
d := d - 1;
|
||||
IsLeap := False;
|
||||
y := y + d div DaysPerYear;
|
||||
d := d mod DaysPerYear;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
// the current year is a leap year and we are after Februar
|
||||
if IsLeap and (d >= StartOfMonth[2]) then
|
||||
d := d + 1;
|
||||
// get the actual month
|
||||
for i := 1 to High(StartOfMonth) do
|
||||
begin
|
||||
if StartOfMonth[i] > d then
|
||||
begin
|
||||
Result^.Month := i;
|
||||
d := d - (StartOfMonth[i - 1] + 1);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
Result^.year := y;
|
||||
Result^.mday := d;
|
||||
end;
|
||||
|
||||
function Date2Amiga(date: PClockData): Cardinal; public name '_fpc_amiga_date2amiga';
|
||||
var
|
||||
Y: LongInt;
|
||||
Leaps, LeapsBefore1978, Res: LongWord;
|
||||
begin
|
||||
{$warning Date2Amiga unimplemented!}
|
||||
Date2Amiga:=0;
|
||||
// the easy time part
|
||||
Res := date^.hour * SecsPerHour + date^.min * SecsPerMin + date^.sec;
|
||||
Res := Res + ((date^.mday - 1) + StartOfMonth[date^.month - 1]) * SecsPerDay;
|
||||
Res := Res + (date^.year - AmigaStartYear) * SecsPerYear;
|
||||
|
||||
// leap year correction ;)
|
||||
|
||||
// current year
|
||||
y := date^.year;
|
||||
// from IsLeapYear dos.pp
|
||||
if (y mod 400 = 0) or ((y mod 4 = 0) and (y mod 100 <> 0)) then
|
||||
begin
|
||||
// add a day if its after feb in a leap year
|
||||
if date^.month > 2 then
|
||||
Res := Res + SecsPerDay;
|
||||
end;
|
||||
|
||||
// previous years
|
||||
y := date^.year - 1;
|
||||
Leaps := (y div 4) - (y div 100) + (y div 400);
|
||||
// exclude the ones before 1978
|
||||
LeapsBefore1978 := (AmigaStartYear div 4) - (AmigaStartYear div 100) + (AmigaStartYear div 400);
|
||||
|
||||
Date2Amiga := Res + (leaps - leapsBefore1978) * SecsPerDay;
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user