Browse Source

* synchronized with trunk

git-svn-id: branches/z80@44721 -
nickysn 5 years ago
parent
commit
c3ca85e349

+ 2 - 0
.gitattributes

@@ -106,6 +106,7 @@ compiler/arm/rarmstd.inc svneol=native#text/plain
 compiler/arm/rarmsup.inc svneol=native#text/plain
 compiler/arm/rarmsup.inc svneol=native#text/plain
 compiler/arm/rgcpu.pas svneol=native#text/plain
 compiler/arm/rgcpu.pas svneol=native#text/plain
 compiler/arm/symcpu.pas svneol=native#text/plain
 compiler/arm/symcpu.pas svneol=native#text/plain
+compiler/armgen/aoptarm.pas svneol=native#text/pascal
 compiler/armgen/armpara.pas svneol=native#text/plain
 compiler/armgen/armpara.pas svneol=native#text/plain
 compiler/assemble.pas svneol=native#text/plain
 compiler/assemble.pas svneol=native#text/plain
 compiler/avr/aasmcpu.pas svneol=native#text/plain
 compiler/avr/aasmcpu.pas svneol=native#text/plain
@@ -15811,6 +15812,7 @@ tests/test/units/math/tdivmod.pp svneol=native#text/plain
 tests/test/units/math/tmask.inc svneol=native#text/plain
 tests/test/units/math/tmask.inc svneol=native#text/plain
 tests/test/units/math/tmask.pp svneol=native#text/plain
 tests/test/units/math/tmask.pp svneol=native#text/plain
 tests/test/units/math/tmask2.pp svneol=native#text/plain
 tests/test/units/math/tmask2.pp svneol=native#text/plain
+tests/test/units/math/tminmaxconst.pp svneol=native#text/pascal
 tests/test/units/math/tnaninf.pp svneol=native#text/plain
 tests/test/units/math/tnaninf.pp svneol=native#text/plain
 tests/test/units/math/tpower.pp svneol=native#text/pascal
 tests/test/units/math/tpower.pp svneol=native#text/pascal
 tests/test/units/math/troundm.pp svneol=native#text/plain
 tests/test/units/math/troundm.pp svneol=native#text/plain

+ 5 - 2
compiler/aarch64/a64att.inc

@@ -128,8 +128,11 @@
 'lsl',
 'lsl',
 'lsr',
 'lsr',
 'ror',
 'ror',
-'sxt',
-'uxt',
+'sxtb',
+'sxth',
+'sxtw',
+'uxtb',
+'uxth',
 'neg',
 'neg',
 'ngc',
 'ngc',
 'mvn',
 'mvn',

+ 3 - 0
compiler/aarch64/a64atts.inc

@@ -188,5 +188,8 @@ attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
 attsufNONE,
+attsufNONE,
+attsufNONE,
+attsufNONE,
 attsufNONE
 attsufNONE
 );
 );

+ 8 - 2
compiler/aarch64/a64ins.dat

@@ -257,9 +257,15 @@
 
 
 [ROR]
 [ROR]
 
 
-[SXT]
+[SXTB]
 
 
-[UXT]
+[SXTH]
+
+[SXTW]
+
+[UXTB]
+
+[UXTH]
 
 
 [NEG]
 [NEG]
 
 

+ 5 - 2
compiler/aarch64/a64op.inc

@@ -128,8 +128,11 @@ A_ASR,
 A_LSL,
 A_LSL,
 A_LSR,
 A_LSR,
 A_ROR,
 A_ROR,
-A_SXT,
-A_UXT,
+A_SXTB,
+A_SXTH,
+A_SXTW,
+A_UXTB,
+A_UXTH,
 A_NEG,
 A_NEG,
 A_NGC,
 A_NGC,
 A_MVN,
 A_MVN,

+ 3 - 2
compiler/aarch64/aoptcpu.pas

@@ -32,10 +32,11 @@ Interface
     uses
     uses
       globtype, globals,
       globtype, globals,
       cutils,
       cutils,
-      cgbase, cpubase, aasmtai, aasmcpu, aopt, aoptcpub;
+      cgbase, cpubase, aasmtai, aasmcpu,
+      aopt, aoptcpub, aoptarm;
 
 
     Type
     Type
-      TCpuAsmOptimizer = class(TAsmOptimizer)
+      TCpuAsmOptimizer = class(TARMAsmOptimizer)
         { uses the same constructor as TAopObj }
         { uses the same constructor as TAopObj }
         function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
         function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
         function PostPeepHoleOptsCpu(var p: tai): boolean; override;
         function PostPeepHoleOptsCpu(var p: tai): boolean; override;

+ 27 - 10
compiler/aarch64/cgcpu.pas

@@ -681,15 +681,32 @@ implementation
     procedure tcgaarch64.a_load_const_ref(list: TAsmList; size: tcgsize; a: tcgint; const ref: treference);
     procedure tcgaarch64.a_load_const_ref(list: TAsmList; size: tcgsize; a: tcgint; const ref: treference);
       var
       var
         reg: tregister;
         reg: tregister;
+        href: treference;
+        i: Integer;
       begin
       begin
         { use the zero register if possible }
         { use the zero register if possible }
         if a=0 then
         if a=0 then
           begin
           begin
-            if size in [OS_64,OS_S64] then
-              reg:=NR_XZR
+            href:=ref;
+            inc(href.offset,tcgsize2size[size]-1);
+            if (tcgsize2size[size]>1) and (ref.alignment=1) and (simple_ref_type(A_STP,OS_8,PF_None,ref)=sr_simple) and
+              (simple_ref_type(A_STP,OS_8,PF_None,href)=sr_simple) then
+              begin
+                href:=ref;
+                for i:=0 to tcgsize2size[size]-1 do
+                  begin
+                    a_load_const_ref(list,OS_8,0,href);
+                    inc(href.offset);
+                  end;
+              end
             else
             else
-              reg:=NR_WZR;
-            a_load_reg_ref(list,size,size,reg,ref);
+              begin
+                if size in [OS_64,OS_S64] then
+                  reg:=NR_XZR
+                else
+                  reg:=NR_WZR;
+                a_load_reg_ref(list,size,size,reg,ref);
+              end;
           end
           end
         else
         else
           inherited;
           inherited;
@@ -907,13 +924,13 @@ implementation
           begin
           begin
             case tosize of
             case tosize of
               OS_8:
               OS_8:
-                list.concat(setoppostfix(taicpu.op_reg_reg(A_UXT,reg2,makeregsize(reg1,OS_32)),PF_B));
+                list.concat(taicpu.op_reg_reg(A_UXTB,reg2,makeregsize(reg1,OS_32)));
               OS_16:
               OS_16:
-                list.concat(setoppostfix(taicpu.op_reg_reg(A_UXT,reg2,makeregsize(reg1,OS_32)),PF_H));
+                list.concat(taicpu.op_reg_reg(A_UXTH,reg2,makeregsize(reg1,OS_32)));
               OS_S8:
               OS_S8:
-                list.concat(setoppostfix(taicpu.op_reg_reg(A_SXT,reg2,makeregsize(reg1,OS_32)),PF_B));
+                list.concat(taicpu.op_reg_reg(A_SXTB,reg2,makeregsize(reg1,OS_32)));
               OS_S16:
               OS_S16:
-                list.concat(setoppostfix(taicpu.op_reg_reg(A_SXT,reg2,makeregsize(reg1,OS_32)),PF_H));
+                list.concat(taicpu.op_reg_reg(A_SXTH,reg2,makeregsize(reg1,OS_32)));
               { while "mov wN, wM" automatically inserts a zero-extension and
               { while "mov wN, wM" automatically inserts a zero-extension and
                 hence we could encode a 64->32 bit move like that, the problem
                 hence we could encode a 64->32 bit move like that, the problem
                 is that we then can't distinguish 64->32 from 32->32 moves, and
                 is that we then can't distinguish 64->32 from 32->32 moves, and
@@ -928,7 +945,7 @@ implementation
                 list.concat(taicpu.op_reg_reg_const_const(A_UBFIZ,makeregsize(reg2,OS_64),makeregsize(reg1,OS_64),0,32));
                 list.concat(taicpu.op_reg_reg_const_const(A_UBFIZ,makeregsize(reg2,OS_64),makeregsize(reg1,OS_64),0,32));
               OS_64,
               OS_64,
               OS_S64:
               OS_S64:
-                list.concat(setoppostfix(taicpu.op_reg_reg(A_SXT,reg2,makeregsize(reg1,OS_32)),PF_W));
+                list.concat(taicpu.op_reg_reg(A_SXTW,reg2,makeregsize(reg1,OS_32)));
               else
               else
                 internalerror(2002090901);
                 internalerror(2002090901);
             end;
             end;
@@ -1157,7 +1174,7 @@ implementation
         list.Concat(taicpu.op_reg_reg_reg_cond(A_CSINV,dst,dst,makeregsize(NR_XZR,dstsize),C_NE));
         list.Concat(taicpu.op_reg_reg_reg_cond(A_CSINV,dst,dst,makeregsize(NR_XZR,dstsize),C_NE));
         { mask the -1 to 255 if src was 0 (anyone find a two-instruction
         { mask the -1 to 255 if src was 0 (anyone find a two-instruction
           branch-free version? All of mine are 3...) }
           branch-free version? All of mine are 3...) }
-        list.Concat(setoppostfix(taicpu.op_reg_reg(A_UXT,makeregsize(dst,OS_32),makeregsize(dst,OS_32)),PF_B));
+        list.Concat(taicpu.op_reg_reg(A_UXTB,makeregsize(dst,OS_32),makeregsize(dst,OS_32)));
       end;
       end;
 
 
 
 

+ 207 - 2
compiler/arm/aoptcpu.pas

@@ -30,10 +30,13 @@ Unit aoptcpu;
 
 
 Interface
 Interface
 
 
-uses cgbase, cgutils, cpubase, aasmtai, aasmcpu,aopt, aoptobj;
+uses
+  cgbase, cgutils, cpubase, aasmtai,
+  aasmcpu,
+  aopt, aoptobj, aoptarm;
 
 
 Type
 Type
-  TCpuAsmOptimizer = class(TAsmOptimizer)
+  TCpuAsmOptimizer = class(TARMAsmOptimizer)
     { Can't be done in some cases due to the limited range of jumps }
     { Can't be done in some cases due to the limited range of jumps }
     function CanDoJumpOpts: Boolean; override;
     function CanDoJumpOpts: Boolean; override;
 
 
@@ -2247,6 +2250,208 @@ Implementation
                          RemoveSuperfluousMove(p, hp1, 'UxthMov2Data') then
                          RemoveSuperfluousMove(p, hp1, 'UxthMov2Data') then
                       Result:=true;
                       Result:=true;
                   end;
                   end;
+                A_SXTB:
+                  begin
+                    {
+                      change
+                      sxtb reg2,reg1
+                      strb reg2,[...]
+                      dealloc reg2
+                      to
+                      strb reg1,[...]
+                    }
+                    if MatchInstruction(p, taicpu(p).opcode, [C_None], [PF_None]) and
+                      (taicpu(p).ops=2) and
+                      GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+                      MatchInstruction(hp1, A_STR, [C_None], [PF_B]) and
+                      assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) and
+                      { the reference in strb might not use reg2 }
+                      not(RegInRef(taicpu(p).oper[0]^.reg,taicpu(hp1).oper[1]^.ref^)) and
+                      { reg1 might not be modified inbetween }
+                      not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
+                      begin
+                        DebugMsg('Peephole SxtbStrb2Strb done', p);
+                        taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg);
+                        GetNextInstruction(p,hp2);
+                        asml.remove(p);
+                        p.free;
+                        p:=hp2;
+                        result:=true;
+                      end
+                    {
+                      change
+                      sxtb reg2,reg1
+                      sxth reg3,reg2
+                      dealloc reg2
+                      to
+                      sxtb reg3,reg1
+                    }
+                    else if MatchInstruction(p, A_SXTB, [C_None], [PF_None]) and
+                      (taicpu(p).ops=2) and
+                      GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+                      MatchInstruction(hp1, A_SXTH, [C_None], [PF_None]) and
+                      (taicpu(hp1).ops = 2) and
+                      MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
+                      RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
+                      { reg1 might not be modified inbetween }
+                      not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
+                      begin
+                        DebugMsg('Peephole SxtbSxth2Sxtb done', p);
+                        AllocRegBetween(taicpu(hp1).oper[0]^.reg,p,hp1,UsedRegs);
+                        taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg);
+                        asml.remove(hp1);
+                        hp1.free;
+                        result:=true;
+                      end
+                    {
+                      change
+                      sxtb reg2,reg1
+                      sxtb reg3,reg2
+                      dealloc reg2
+                      to
+                      uxtb reg3,reg1
+                    }
+                    else if MatchInstruction(p, A_SXTB, [C_None], [PF_None]) and
+                      (taicpu(p).ops=2) and
+                      GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+                      MatchInstruction(hp1, A_SXTB, [C_None], [PF_None]) and
+                      (taicpu(hp1).ops = 2) and
+                      MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
+                      RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
+                      { reg1 might not be modified inbetween }
+                      not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
+                      begin
+                        DebugMsg('Peephole SxtbSxtb2Sxtb done', p);
+                        AllocRegBetween(taicpu(hp1).oper[0]^.reg,p,hp1,UsedRegs);
+                        taicpu(p).loadReg(0,taicpu(hp1).oper[0]^.reg);
+                        asml.remove(hp1);
+                        hp1.free;
+                        result:=true;
+                      end
+                    {
+                      change
+                      sxtb reg2,reg1
+                      and reg3,reg2,#0x*FF
+                      dealloc reg2
+                      to
+                      uxtb reg3,reg1
+                    }
+                    else if MatchInstruction(p, A_SXTB, [C_None], [PF_None]) and
+                      (taicpu(p).ops=2) and
+                      GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+                      MatchInstruction(hp1, A_AND, [C_None], [PF_None]) and
+                      (taicpu(hp1).ops=3) and
+                      (taicpu(hp1).oper[2]^.typ=top_const) and
+                      ((taicpu(hp1).oper[2]^.val and $FF)=$FF) and
+                      MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
+                      RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
+                      { reg1 might not be modified inbetween }
+                      not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
+                      begin
+                        DebugMsg('Peephole SxtbAndImm2Sxtb done', p);
+                        taicpu(hp1).opcode:=A_SXTB;
+                        taicpu(hp1).ops:=2;
+                        taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
+                        GetNextInstruction(p,hp2);
+                        asml.remove(p);
+                        p.free;
+                        p:=hp2;
+                        result:=true;
+                      end
+                    else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+                         RemoveSuperfluousMove(p, hp1, 'SxtbMov2Data') then
+                      Result:=true;
+                  end;
+                A_SXTH:
+                  begin
+                    {
+                      change
+                      sxth reg2,reg1
+                      strh reg2,[...]
+                      dealloc reg2
+                      to
+                      strh reg1,[...]
+                    }
+                    if MatchInstruction(p, taicpu(p).opcode, [C_None], [PF_None]) and
+                      (taicpu(p).ops=2) and
+                      GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+                      MatchInstruction(hp1, A_STR, [C_None], [PF_H]) and
+                      RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
+                      { the reference in strb might not use reg2 }
+                      not(RegInRef(taicpu(p).oper[0]^.reg,taicpu(hp1).oper[1]^.ref^)) and
+                      { reg1 might not be modified inbetween }
+                      not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
+                      begin
+                        DebugMsg('Peephole SXTHStrh2Strh done', p);
+                        taicpu(hp1).loadReg(0,taicpu(p).oper[1]^.reg);
+                        GetNextInstruction(p, hp1);
+                        asml.remove(p);
+                        p.free;
+                        p:=hp1;
+                        result:=true;
+                      end
+                    {
+                      change
+                      sxth reg2,reg1
+                      sxth reg3,reg2
+                      dealloc reg2
+                      to
+                      sxth reg3,reg1
+                    }
+                    else if MatchInstruction(p, A_SXTH, [C_None], [PF_None]) and
+                      (taicpu(p).ops=2) and
+                      GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+                      MatchInstruction(hp1, A_SXTH, [C_None], [PF_None]) and
+                      (taicpu(hp1).ops=2) and
+                      MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
+                      RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
+                      { reg1 might not be modified inbetween }
+                      not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
+                      begin
+                        DebugMsg('Peephole SxthSxth2Sxth done', p);
+                        AllocRegBetween(taicpu(p).oper[1]^.reg,p,hp1,UsedRegs);
+                        taicpu(hp1).opcode:=A_SXTH;
+                        taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
+                        GetNextInstruction(p, hp1);
+                        asml.remove(p);
+                        p.free;
+                        p:=hp1;
+                        result:=true;
+                      end
+                    {
+                      change
+                      sxth reg2,reg1
+                      and reg3,reg2,#65535
+                      dealloc reg2
+                      to
+                      sxth reg3,reg1
+                    }
+                    else if MatchInstruction(p, A_SXTH, [C_None], [PF_None]) and
+                      (taicpu(p).ops=2) and
+                      GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
+                      MatchInstruction(hp1, A_AND, [C_None], [PF_None]) and
+                      (taicpu(hp1).ops=3) and
+                      (taicpu(hp1).oper[2]^.typ=top_const) and
+                      ((taicpu(hp1).oper[2]^.val and $FFFF)=$FFFF) and
+                      MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) and
+                      RegEndofLife(taicpu(p).oper[0]^.reg,taicpu(hp1)) and
+                      { reg1 might not be modified inbetween }
+                      not(RegModifiedBetween(taicpu(p).oper[1]^.reg,p,hp1)) then
+                      begin
+                        DebugMsg('Peephole SxthAndImm2Sxth done', p);
+                        taicpu(hp1).opcode:=A_SXTH;
+                        taicpu(hp1).ops:=2;
+                        taicpu(hp1).loadReg(1,taicpu(p).oper[1]^.reg);
+                        GetNextInstruction(p, hp1);
+                        asml.remove(p);
+                        p.free;
+                        p:=hp1;
+                        result:=true;
+                      end
+                    else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
+                         RemoveSuperfluousMove(p, hp1, 'SxthMov2Data') then
+                      Result:=true;
+                  end;
                 A_CMP:
                 A_CMP:
                   begin
                   begin
                     {
                     {

+ 2 - 5
compiler/arm/cpuinfo.pas

@@ -77,14 +77,11 @@ Type
       fpu_vfpv4,
       fpu_vfpv4,
       fpu_fpv4_sp_d16,  { 32 registers single precision, for load/store/move they can be accessed as 16 double registers }
       fpu_fpv4_sp_d16,  { 32 registers single precision, for load/store/move they can be accessed as 16 double registers }
       fpu_neon_vfpv4
       fpu_neon_vfpv4
-      { when new elements added afterwards, update also fpu_vfp_last below and
-        update class procedure tarmnodeutils.InsertObjectInfo; in narmutil.pas }
+      { when new elements added afterwards, update
+        class procedure tarmnodeutils.InsertObjectInfo; in narmutil.pas }
      );
      );
 
 
 Const
 Const
-   fpu_vfp_first = fpu_vfpv2;
-   fpu_vfp_last  = fpu_neon_vfpv4;
-
   fputypestrllvm : array[tfputype] of string[15] = ('',
   fputypestrllvm : array[tfputype] of string[15] = ('',
     '',
     '',
     '',
     '',

+ 1 - 1
compiler/arm/narmcal.pas

@@ -83,7 +83,7 @@ implementation
          (target_info.abi<>abi_eabihf) and
          (target_info.abi<>abi_eabihf) and
          (procdefinition.proccalloption<>pocall_hardfloat) and
          (procdefinition.proccalloption<>pocall_hardfloat) and
          ((cs_fp_emulation in current_settings.moduleswitches) 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
         begin
           { keep the fpu values in integer registers for now, the code
           { keep the fpu values in integer registers for now, the code
             generator will move them to memory or an mmregister when necessary
             generator will move them to memory or an mmregister when necessary

+ 8 - 4
compiler/arm/narmcnv.pas

@@ -40,7 +40,9 @@ interface
 implementation
 implementation
 
 
    uses
    uses
-      verbose,globtype,globals,symdef,aasmbase,aasmtai,aasmdata,symtable,
+      verbose,globtype,globals,
+      systems,
+      symdef,aasmbase,aasmtai,aasmdata,symtable,
       defutil,
       defutil,
       cgbase,cgutils,
       cgbase,cgutils,
       pass_1,pass_2,procinfo,ncal,
       pass_1,pass_2,procinfo,ncal,
@@ -99,17 +101,19 @@ implementation
               fpu_fpa10,
               fpu_fpa10,
               fpu_fpa11:
               fpu_fpa11:
                 expectloc:=LOC_FPUREGISTER;
                 expectloc:=LOC_FPUREGISTER;
-              fpu_vfp_first..fpu_vfp_last:
-                expectloc:=LOC_MMREGISTER;
+              else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
+                expectloc:=LOC_MMREGISTER
               else
               else
                 internalerror(2009112702);
                 internalerror(2009112702);
             end;
             end;
           end;
           end;
       end;
       end;
 
 
+
     function tarmtypeconvnode.first_real_to_real: tnode;
     function tarmtypeconvnode.first_real_to_real: tnode;
       begin
       begin
-        if not(FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[current_settings.fputype]) then
+        if not(FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[current_settings.fputype]) and
+          not (target_info.system in systems_wince) then
           begin
           begin
             case tfloatdef(left.resultdef).floattype of
             case tfloatdef(left.resultdef).floattype of
               s32real:
               s32real:

+ 6 - 6
compiler/arm/narminl.pas

@@ -86,7 +86,12 @@ implementation
                  location.loc := LOC_FPUREGISTER;
                  location.loc := LOC_FPUREGISTER;
                end;
                end;
             end;
             end;
-          fpu_vfp_first..fpu_vfp_last:
+          fpu_soft:
+            begin
+              hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+              location_copy(location,left.location);
+            end
+          else if FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype] then
             begin
             begin
               hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
               hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
               location_copy(location,left.location);
               location_copy(location,left.location);
@@ -95,11 +100,6 @@ implementation
                  location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
                  location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
                  location.loc := LOC_MMREGISTER;
                  location.loc := LOC_MMREGISTER;
                end;
                end;
-            end;
-          fpu_soft:
-            begin
-              hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
-              location_copy(location,left.location);
             end
             end
           else
           else
             internalerror(2009111801);
             internalerror(2009111801);

+ 7 - 3
compiler/arm/narmutil.pas

@@ -197,8 +197,12 @@ interface
                 Internalerror(2019100602);
                 Internalerror(2019100602);
             end;
             end;
             case current_settings.fputype of
             case current_settings.fputype of
+              fpu_none,
               fpu_soft,
               fpu_soft,
-              fpu_libgcc:
+              fpu_libgcc,
+              fpu_fpa,
+              fpu_fpa10,
+              fpu_fpa11:
                 current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,0));
                 current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,0));
               fpu_vfpv2:
               fpu_vfpv2:
                 current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,2));
                 current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,2));
@@ -213,8 +217,8 @@ interface
               fpu_vfpv4,
               fpu_vfpv4,
               fpu_neon_vfpv4:
               fpu_neon_vfpv4:
                 current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,5));
                 current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_FP_Arch,5));
-              else
-                Internalerror(2019100603);
+              { else not needed anymore PM 2020/04/13
+                Internalerror(2019100603); }
             end;
             end;
             if FPUARM_HAS_FMA in fpu_capabilities[current_settings.fputype] then
             if FPUARM_HAS_FMA in fpu_capabilities[current_settings.fputype] then
               current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_Advanced_SIMD_arch,2))
               current_asmdata.asmlists[al_start].Concat(tai_eabi_attribute.create(Tag_Advanced_SIMD_arch,2))

+ 52 - 0
compiler/armgen/aoptarm.pas

@@ -0,0 +1,52 @@
+{
+    Copyright (c) 1998-2020 by Jonas Maebe and Florian Klaempfl, members of the Free Pascal
+    Development Team
+
+    This unit implements an ARM optimizer object used commonly for ARM and AAarch64
+
+    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 aoptarm;
+
+{$i fpcdefs.inc}
+
+{ $define DEBUG_PREREGSCHEDULER}
+{ $define DEBUG_AOPTCPU}
+
+Interface
+
+uses
+  cgbase, cgutils, cpubase, aasmtai, aasmcpu,aopt, aoptobj;
+
+Type
+  { while ARM and AAarch64 look not very similar at a first glance,
+    several optimizations can be shared between both }
+  TARMAsmOptimizer = class(TAsmOptimizer)
+  End;
+
+Implementation
+
+  uses
+    cutils,verbose,globtype,globals,
+    systems,
+    cpuinfo,
+    cgobj,procinfo,
+    aasmbase,aasmdata;
+
+end.
+

+ 8 - 0
compiler/ncnv.pas

@@ -3181,6 +3181,7 @@ implementation
         { must be done before code below, because we need the
         { must be done before code below, because we need the
           typeconversions for ordconstn's as well }
           typeconversions for ordconstn's as well }
         case convtype of
         case convtype of
+          tc_bool_2_int,
           tc_int_2_bool,
           tc_int_2_bool,
           tc_int_2_int:
           tc_int_2_int:
             begin
             begin
@@ -3216,6 +3217,13 @@ implementation
                       left:=nil;
                       left:=nil;
                       exit;
                       exit;
                     end;
                     end;
+                  if (convtype=tc_int_2_int) and (left.nodetype=typeconvn) and (ttypeconvnode(left).convtype=tc_bool_2_int) then
+                    begin
+                      ttypeconvnode(left).resultdef:=resultdef;
+                      result:=left;
+                      left:=nil;
+                      exit;
+                    end;
                 end;
                 end;
             end;
             end;
           else
           else

+ 2 - 0
rtl/amicommon/dos.pp

@@ -1082,7 +1082,9 @@ Var
 begin
 begin
   SetLength(EnvList, 0);
   SetLength(EnvList, 0);
   // pr_LocalVars are introduced with OS2.0
   // pr_LocalVars are introduced with OS2.0
+  {$ifdef AMIGA68k}
   if PLibrary(AOS_ExecBase)^.lib_Version >= 36 then
   if PLibrary(AOS_ExecBase)^.lib_Version >= 36 then
+  {$endif}
   begin
   begin
     ThisProcess := PProcess(FindTask(nil));  //Get the pointer to our process
     ThisProcess := PProcess(FindTask(nil));  //Get the pointer to our process
     LocalVars_List := @(ThisProcess^.pr_LocalVars);  //get the list of pr_LocalVars as pointer
     LocalVars_List := @(ThisProcess^.pr_LocalVars);  //get the list of pr_LocalVars as pointer

+ 10 - 4
rtl/objpas/math.pp

@@ -71,13 +71,19 @@ Const
     { Ranges of the IEEE floating point types, including denormals }
     { Ranges of the IEEE floating point types, including denormals }
 {$ifdef FPC_HAS_TYPE_SINGLE}
 {$ifdef FPC_HAS_TYPE_SINGLE}
     const
     const
-      MinSingle    =  1.5e-45;
-      MaxSingle    =  3.4e+38;
+      { values according to
+        https://en.wikipedia.org/wiki/Single-precision_floating-point_format#Single-precision_examples
+      }
+      MinSingle    =  1.1754943508e-38;
+      MaxSingle    =  3.4028234664e+38;
 {$endif FPC_HAS_TYPE_SINGLE}
 {$endif FPC_HAS_TYPE_SINGLE}
 {$ifdef FPC_HAS_TYPE_DOUBLE}
 {$ifdef FPC_HAS_TYPE_DOUBLE}
     const
     const
-      MinDouble    =  5.0e-324;
-      MaxDouble    =  1.7e+308;
+      { values according to
+        https://en.wikipedia.org/wiki/Double-precision_floating-point_format#Double-precision_examples
+      }
+      MinDouble    =  2.2250738585072014e-308;
+      MaxDouble    =  1.7976931348623157e+308;
 {$endif FPC_HAS_TYPE_DOUBLE}
 {$endif FPC_HAS_TYPE_DOUBLE}
 {$ifdef FPC_HAS_TYPE_EXTENDED}
 {$ifdef FPC_HAS_TYPE_EXTENDED}
     const
     const

+ 24 - 0
tests/test/units/math/tminmaxconst.pp

@@ -0,0 +1,24 @@
+uses
+  sysutils,math;
+var
+  s: Single;
+  d: Double;
+begin
+  s := MaxSingle;
+  d := MaxDouble;
+  Writeln(IntToHex(PLongInt(@s)^, 8));
+  if IntToHex(PLongInt(@s)^, 8)<>'7F7FFFFF' then
+     halt(1);
+  Writeln(IntToHex(PInt64(@d)^, 16));
+  if IntToHex(PInt64(@d)^, 16)<>'7FEFFFFFFFFFFFFF' then
+    halt(2);
+  s := MinSingle;
+  d := MinDouble;
+  Writeln(IntToHex(PLongInt(@s)^, 8));
+  if IntToHex(PLongInt(@s)^, 8)<>'00800000' then
+    halt(3);
+  Writeln(IntToHex(PInt64(@d)^, 16));
+  if IntToHex(PInt64(@d)^, 16)<>'0010000000000000' then
+    halt(4);
+  writeln('ok');
+end.