mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 14:27:59 +02:00
* prevent generation of mul/mla statements with illegal registers
git-svn-id: trunk@25343 -
This commit is contained in:
parent
7df123aa1e
commit
bb73a2891b
@ -112,6 +112,9 @@ unit cgcpu;
|
||||
{ clear out potential overflow bits from 8 or 16 bit operations }
|
||||
{ the upper 24/16 bits of a register after an operation }
|
||||
procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
|
||||
|
||||
{ mla for thumb requires that none of the registers is equal to r13/r15, this method ensures this }
|
||||
procedure safe_mla(list: TAsmList;op1,op2,op3,op4 : TRegister);
|
||||
end;
|
||||
|
||||
{ tcgarm is shared between normal arm and thumb-2 }
|
||||
@ -3191,6 +3194,30 @@ unit cgcpu;
|
||||
end;
|
||||
|
||||
|
||||
procedure tbasecgarm.safe_mla(list : TAsmList; op1,op2,op3,op4 : TRegister);
|
||||
|
||||
procedure checkreg(var reg : TRegister);
|
||||
var
|
||||
tmpreg : TRegister;
|
||||
begin
|
||||
if ((current_settings.cputype in cpu_thumb+cpu_thumb2) and (getsupreg(reg)=RS_R13)) or
|
||||
(getsupreg(reg)=RS_R15) then
|
||||
begin
|
||||
tmpreg:=getintregister(list,OS_INT);
|
||||
a_load_reg_reg(list,OS_INT,OS_INT,reg,tmpreg);
|
||||
reg:=tmpreg;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
checkreg(op1);
|
||||
checkreg(op2);
|
||||
checkreg(op3);
|
||||
checkreg(op4);
|
||||
list.concat(taicpu.op_reg_reg_reg_reg(A_MLA,op1,op2,op3,op4));
|
||||
end;
|
||||
|
||||
|
||||
procedure tcg64farm.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
|
||||
begin
|
||||
case op of
|
||||
|
@ -53,7 +53,7 @@ interface
|
||||
defutil,htypechk,cgbase,cgutils,
|
||||
cpuinfo,pass_1,pass_2,procinfo,
|
||||
ncon,nadd,ncnv,ncal,nmat,
|
||||
ncgutil,cgobj,
|
||||
ncgutil,cgobj,cgcpu,
|
||||
hlcgobj
|
||||
;
|
||||
|
||||
@ -509,7 +509,7 @@ interface
|
||||
tmpreg := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
|
||||
asmList.concat(taicpu.op_reg_reg_reg(A_MUL,tmpreg,ll.reglo,rl.reghi));
|
||||
asmList.concat(taicpu.op_reg_reg_reg_reg(A_UMULL,res.reglo,res.reghi,rl.reglo,ll.reglo));
|
||||
asmList.concat(taicpu.op_reg_reg_reg_reg(A_MLA,tmpreg,rl.reglo,ll.reghi,tmpreg));
|
||||
tbasecgarm(cg).safe_mla(asmList,tmpreg,rl.reglo,ll.reghi,tmpreg);
|
||||
asmList.concat(taicpu.op_reg_reg_reg(A_ADD,res.reghi,tmpreg,res.reghi));
|
||||
end
|
||||
else
|
||||
|
@ -42,7 +42,7 @@ interface
|
||||
implementation
|
||||
|
||||
uses
|
||||
cutils,verbose,globals,aasmdata,aasmcpu,cgobj,
|
||||
cutils,verbose,globals,aasmdata,aasmcpu,cgobj,cgcpu,
|
||||
cpuinfo,
|
||||
cgutils,
|
||||
procinfo;
|
||||
@ -84,7 +84,7 @@ implementation
|
||||
begin
|
||||
hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_ADDR,l,hreg);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_reg(A_MLA,hreg,maybe_const_reg,hreg,location.reference.base));
|
||||
tbasecgarm(cg).safe_mla(current_asmdata.CurrAsmList,hreg,maybe_const_reg,hreg,location.reference.base);
|
||||
location.reference.base:=hreg;
|
||||
{ update alignment }
|
||||
if (location.reference.alignment=0) then
|
||||
@ -95,7 +95,7 @@ implementation
|
||||
begin
|
||||
hreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_ADDR,l,hreg);
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_reg(A_MLA,hreg,maybe_const_reg,hreg,location.reference.index));
|
||||
tbasecgarm(cg).safe_mla(current_asmdata.CurrAsmList,hreg,maybe_const_reg,hreg,location.reference.index);
|
||||
location.reference.base:=hreg;
|
||||
location.reference.index:=NR_NO;
|
||||
{ update alignment }
|
||||
|
@ -121,6 +121,24 @@ unit rgcpu;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
A_MLA,
|
||||
A_MUL:
|
||||
begin
|
||||
if current_settings.cputype<cpu_armv6 then
|
||||
add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[1]^.reg));
|
||||
add_edge(getsupreg(taicpu(p).oper[0]^.reg),RS_R13);
|
||||
add_edge(getsupreg(taicpu(p).oper[0]^.reg),RS_R15);
|
||||
add_edge(getsupreg(taicpu(p).oper[1]^.reg),RS_R13);
|
||||
add_edge(getsupreg(taicpu(p).oper[1]^.reg),RS_R15);
|
||||
add_edge(getsupreg(taicpu(p).oper[2]^.reg),RS_R13);
|
||||
add_edge(getsupreg(taicpu(p).oper[2]^.reg),RS_R15);
|
||||
if taicpu(p).opcode=A_MLA then
|
||||
begin
|
||||
add_edge(getsupreg(taicpu(p).oper[3]^.reg),RS_R13);
|
||||
add_edge(getsupreg(taicpu(p).oper[3]^.reg),RS_R15);
|
||||
end;
|
||||
end;
|
||||
|
||||
A_LDRB,
|
||||
A_STRB,
|
||||
A_STR,
|
||||
@ -486,8 +504,15 @@ unit rgcpu;
|
||||
case taicpu(p).opcode of
|
||||
A_MLA,
|
||||
A_MUL:
|
||||
if current_settings.cputype<cpu_armv6 then
|
||||
add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[1]^.reg));
|
||||
begin
|
||||
if current_settings.cputype<cpu_armv6 then
|
||||
add_edge(getsupreg(taicpu(p).oper[0]^.reg),getsupreg(taicpu(p).oper[1]^.reg));
|
||||
add_edge(getsupreg(taicpu(p).oper[0]^.reg),RS_R15);
|
||||
add_edge(getsupreg(taicpu(p).oper[1]^.reg),RS_R15);
|
||||
add_edge(getsupreg(taicpu(p).oper[2]^.reg),RS_R15);
|
||||
if taicpu(p).opcode=A_MLA then
|
||||
add_edge(getsupreg(taicpu(p).oper[3]^.reg),RS_R15);
|
||||
end;
|
||||
A_UMULL,
|
||||
A_UMLAL,
|
||||
A_SMULL,
|
||||
|
Loading…
Reference in New Issue
Block a user