* synchronized with trunk

git-svn-id: branches/z80@44710 -
This commit is contained in:
nickysn 2020-04-12 20:45:34 +00:00
commit 1cfbae82c6
18 changed files with 412 additions and 156 deletions

View File

@ -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

View File

@ -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:

View File

@ -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,

View File

@ -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 }

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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)

View File

@ -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;

View File

@ -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}),

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;