* prevent generation of mul/mla statements with illegal registers

git-svn-id: trunk@25343 -
This commit is contained in:
florian 2013-08-23 15:22:41 +00:00
parent 7df123aa1e
commit bb73a2891b
4 changed files with 59 additions and 7 deletions

View File

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

View File

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

View File

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

View File

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