diff options
author | karoly <karoly@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2021-02-13 13:01:21 +0000 |
---|---|---|
committer | karoly <karoly@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2021-02-13 13:01:21 +0000 |
commit | 0a201eea1dfdd651588b438fcb7e7a3257cfa560 (patch) | |
tree | ec02ad1d6351cb5c1321c595b8759332e29f6992 | |
parent | 279343f2a3786dd4a86ebb83a94c2bb3ec1deeac (diff) | |
download | fpc-0a201eea1dfdd651588b438fcb7e7a3257cfa560.tar.gz |
* Merging recent m68k FPU fixes from trunk: r42829, r48413, r48414, r48522, r48523, r48524
git-svn-id: https://svn.freepascal.org/svn/fpc/branches/fixes_3_2@48666 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r-- | compiler/m68k/ag68kgas.pas | 16 | ||||
-rw-r--r-- | compiler/m68k/aoptcpu.pas | 48 | ||||
-rw-r--r-- | compiler/m68k/cgcpu.pas | 40 | ||||
-rw-r--r-- | compiler/m68k/n68kadd.pas | 2 | ||||
-rw-r--r-- | compiler/m68k/n68kinl.pas | 6 |
5 files changed, 77 insertions, 35 deletions
diff --git a/compiler/m68k/ag68kgas.pas b/compiler/m68k/ag68kgas.pas index 4c049b9d23..4399b2a53e 100644 --- a/compiler/m68k/ag68kgas.pas +++ b/compiler/m68k/ag68kgas.pas @@ -169,7 +169,7 @@ interface end; - function getopstr(var o:toper) : string; + function getopstr(size: topsize; var o:toper) : string; var i : tsuperregister; begin @@ -220,10 +220,14 @@ interface getopstr:='#'+tostr(longint(o.val)); top_realconst: begin - str(o.val_real,getopstr); - if getopstr[1]=' ' then - getopstr[1]:='+'; - getopstr:='#0d'+getopstr; + case size of + S_FS: + getopstr:='#0x'+hexstr(longint(single(o.val_real)),sizeof(single)*2); + S_FD: + getopstr:='#0x'+hexstr(BestRealRec(o.val_real).Data,sizeof(bestreal)*2); + else + internalerror(2021020801); + end; end; else internalerror(200405021); end; @@ -337,7 +341,7 @@ interface sep:=':' else sep:=','; - s:=s+sep+getopstr(taicpu(hp).oper[i]^); + s:=s+sep+getopstr(taicpu(hp).opsize,taicpu(hp).oper[i]^); end; end; end; diff --git a/compiler/m68k/aoptcpu.pas b/compiler/m68k/aoptcpu.pas index 896d8bd6d3..28290958cd 100644 --- a/compiler/m68k/aoptcpu.pas +++ b/compiler/m68k/aoptcpu.pas @@ -154,26 +154,30 @@ unit aoptcpu; opstr:=opname(p); case taicpu(p).oper[0]^.typ of top_reg: - begin - { move %reg0, %tmpreg; move %tmpreg, <ea> -> move %reg0, <ea> } - taicpu(p).loadOper(1,taicpu(next).oper[1]^); - asml.remove(next); - next.free; - result:=true; - { also remove leftover move %reg0, %reg0, which can occur as the result - of the previous optimization, if %reg0 and %tmpreg was different types - (addr vs. data), so these moves were left in by the cg } - if MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) then - begin - DebugMsg('Optimizer: '+opstr+' + '+opstr+' removed',p); - GetNextInstruction(p,next); - asml.remove(p); - p.free; - p:=next; - end - else - DebugMsg('Optimizer: '+opstr+' + '+opstr+' to '+opstr+' #1',p) - end; + { do not optimize away FPU to INT to FPU reg moves. These are used for + to-single-rounding on FPUs which have no FSMOVE/FDMOVE. (KB) } + if not ((taicpu(p).opcode = A_FMOVE) and + (getregtype(taicpu(p).oper[0]^.reg) <> getregtype(taicpu(p).oper[1]^.reg))) then + begin + { move %reg0, %tmpreg; move %tmpreg, <ea> -> move %reg0, <ea> } + taicpu(p).loadOper(1,taicpu(next).oper[1]^); + asml.remove(next); + next.free; + result:=true; + { also remove leftover move %reg0, %reg0, which can occur as the result + of the previous optimization, if %reg0 and %tmpreg was different types + (addr vs. data), so these moves were left in by the cg } + if MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) then + begin + DebugMsg('Optimizer: '+opstr+' + '+opstr+' removed',p); + GetNextInstruction(p,next); + asml.remove(p); + p.free; + p:=next; + end + else + DebugMsg('Optimizer: '+opstr+' + '+opstr+' to '+opstr+' #1',p) + end; top_const: begin // DebugMsg('Optimizer: '+opstr+' + '+opstr+' to '+opstr+' #2',p); @@ -271,10 +275,10 @@ unit aoptcpu; (taicpu(p).oper[0]^.ref^.offset = 0) then begin DebugMsg('Optimizer: LEA 0(Ax),Ax removed',p); - GetNextInstruction(p,next); + GetNextInstruction(p,next); asml.remove(p); p.free; - p:=next; + p:=next; result:=true; end; { Address register sub/add can be replaced with ADDQ/SUBQ or LEA if the value is in the diff --git a/compiler/m68k/cgcpu.pas b/compiler/m68k/cgcpu.pas index c86f75c65b..c9bda79c70 100644 --- a/compiler/m68k/cgcpu.pas +++ b/compiler/m68k/cgcpu.pas @@ -1051,10 +1051,42 @@ unit cgcpu; procedure tcg68k.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); var instr : taicpu; + op: tasmop; + href: treference; + hreg: tregister; begin - instr:=taicpu.op_reg_reg(A_FMOVE,fpuregopsize,reg1,reg2); - add_move_instruction(instr); - list.concat(instr); + if fromsize > tosize then + begin + { we have to do a load-store through an intregister or the stack in this case, + which is probably the fastest way, and simpler than messing around with FPU control + words for one-off custom rounding (KB) } + case tosize of + OS_F32: + begin + //list.concat(tai_comment.create(strpnew('a_loadfpu_reg_reg rounding via intreg'))); + hreg := getintregister(list,OS_32); + list.concat(taicpu.op_reg_reg(A_FMOVE, tcgsize2opsize[tosize], reg1, hreg)); + list.concat(taicpu.op_reg_reg(A_FMOVE, tcgsize2opsize[tosize], hreg, reg2)); + end; + OS_F64: + begin + //list.concat(tai_comment.create(strpnew('a_loadfpu_reg_reg rounding via stack'))); + reference_reset_base(href, NR_STACK_POINTER_REG, 0, ctempposinvalid, 0, []); + href.direction:=dir_dec; + list.concat(taicpu.op_reg_ref(A_FMOVE, tcgsize2opsize[tosize], reg1, href)); + href.direction:=dir_inc; + list.concat(taicpu.op_ref_reg(A_FMOVE, tcgsize2opsize[tosize], href, reg2)); + end; + else + internalerror(2021020802); + end; + end + else + begin + instr:=taicpu.op_reg_reg(A_FMOVE,fpuregopsize,reg1,reg2); + add_move_instruction(instr); + list.concat(instr); + end; end; @@ -1067,6 +1099,8 @@ unit cgcpu; href := ref; fixref(list,href,current_settings.fputype = fpu_coldfire); list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg)); + if fromsize > tosize then + a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg); end; procedure tcg68k.a_loadfpu_reg_ref(list: TAsmList; fromsize,tosize: tcgsize; reg: tregister; const ref: treference); diff --git a/compiler/m68k/n68kadd.pas b/compiler/m68k/n68kadd.pas index 9854111ffb..ee1c29e3b9 100644 --- a/compiler/m68k/n68kadd.pas +++ b/compiler/m68k/n68kadd.pas @@ -202,7 +202,7 @@ implementation hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true); location.register := cg.getfpuregister(current_asmdata.CurrAsmList,location.size); - cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmlist,OS_NO,OS_NO,left.location.register,location.register); + cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmlist,left.location.size,location.size,left.location.register,location.register); end; { emit the actual operation } diff --git a/compiler/m68k/n68kinl.pas b/compiler/m68k/n68kinl.pas index ef61d0e94e..4590ef6825 100644 --- a/compiler/m68k/n68kinl.pas +++ b/compiler/m68k/n68kinl.pas @@ -210,7 +210,7 @@ implementation //current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('second_srq_real called!: left was cfpuregister!'))); location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size); location.loc := LOC_FPUREGISTER; - cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmlist,OS_NO,OS_NO,left.location.register,location.register); + cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmlist,left.location.size,location.size,left.location.register,location.register); end; current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FMUL,fpuregopsize,left.location.register,location.register)); end; @@ -296,7 +296,7 @@ implementation begin hreg:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size); location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size); - cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmlist,OS_NO,OS_NO,left.location.register,location.register); + cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmlist,left.location.size,location.size,left.location.register,location.register); current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FINTRZ,fpuregopsize,left.location.register,hreg)); current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSUB,fpuregopsize,hreg,location.register)); end; @@ -306,7 +306,7 @@ implementation location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size); href:=left.location.reference; tcg68k(cg).fixref(current_asmdata.CurrAsmList,href,current_settings.fputype = fpu_coldfire); - cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmlist,left.location.size,OS_NO,href,location.register); + cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmlist,left.location.size,location.size,href,location.register); current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FINTRZ,fpuregopsize,location.register,hreg)); current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSUB,fpuregopsize,hreg,location.register)); end; |