mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-14 14:59:32 +02:00
o patch by Jeppe Johansen to fix mantis #17472:
* generate add.w instead of add for thumb-2 in case one of the registers is > r8 * add register interferences for the "add" instruction so the register allocator can detect invalid instruction forms (even for assembler code) * fixed error in thumb2.inc detected by the previous change git-svn-id: trunk@16633 -
This commit is contained in:
parent
8cbef5627e
commit
780e75bfac
@ -158,6 +158,7 @@ uses
|
||||
type
|
||||
taicpu = class(tai_cpu_abstract_sym)
|
||||
oppostfix : TOpPostfix;
|
||||
wideformat : boolean;
|
||||
roundingmode : troundingmode;
|
||||
procedure loadshifterop(opidx:longint;const so:tshifterop);
|
||||
procedure loadregset(opidx:longint; regsetregtype: tregistertype; regsetsubregtype: tsubregister; const s:tcpuregisterset);
|
||||
@ -246,8 +247,9 @@ uses
|
||||
function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
|
||||
function setcondition(i : taicpu;c : tasmcond) : taicpu;
|
||||
|
||||
{ inserts pc relative symbols at places where they are reachable }
|
||||
procedure insertpcrelativedata(list,listtoinsert : TAsmList);
|
||||
{ inserts pc relative symbols at places where they are reachable
|
||||
and transforms special instructions to valid instruction encodings }
|
||||
procedure finalizearmcode(list,listtoinsert : TAsmList);
|
||||
{ inserts .pdata section and dummy function prolog needed for arm-wince exception handling }
|
||||
procedure InsertPData;
|
||||
|
||||
@ -958,6 +960,74 @@ implementation
|
||||
curdata.free;
|
||||
end;
|
||||
|
||||
|
||||
procedure ensurethumb2encodings(list: TAsmList);
|
||||
var
|
||||
curtai: tai;
|
||||
op2reg: TRegister;
|
||||
begin
|
||||
{ Do Thumb-2 16bit -> 32bit transformations }
|
||||
curtai:=tai(list.first);
|
||||
while assigned(curtai) do
|
||||
begin
|
||||
case curtai.typ of
|
||||
ait_instruction:
|
||||
begin
|
||||
case taicpu(curtai).opcode of
|
||||
A_ADD:
|
||||
begin
|
||||
{ Set wide flag for ADD Rd,Rn,Rm where registers are over R7(high register set) }
|
||||
if taicpu(curtai).ops = 3 then
|
||||
begin
|
||||
if taicpu(curtai).oper[2]^.typ in [top_reg,top_shifterop] then
|
||||
begin
|
||||
if taicpu(curtai).oper[2]^.typ = top_reg then
|
||||
op2reg := taicpu(curtai).oper[2]^.reg
|
||||
else if taicpu(curtai).oper[2]^.shifterop^.rs <> NR_NO then
|
||||
op2reg := taicpu(curtai).oper[2]^.shifterop^.rs
|
||||
else
|
||||
op2reg := NR_NO;
|
||||
|
||||
if op2reg <> NR_NO then
|
||||
begin
|
||||
if (taicpu(curtai).oper[0]^.reg >= NR_R8) or
|
||||
(taicpu(curtai).oper[1]^.reg >= NR_R8) or
|
||||
(op2reg >= NR_R8) then
|
||||
begin
|
||||
taicpu(curtai).wideformat:=true;
|
||||
|
||||
{ Handle special cases where register rules are violated by optimizer/user }
|
||||
{ if d == 13 || (d == 15 && S == ‘0’) || n == 15 || m IN [13,15] then UNPREDICTABLE; }
|
||||
|
||||
{ Transform ADD.W Rx, Ry, R13 into ADD.W Rx, R13, Ry }
|
||||
if (op2reg = NR_R13) and (taicpu(curtai).oper[2]^.typ = top_reg) then
|
||||
begin
|
||||
taicpu(curtai).oper[2]^.reg := taicpu(curtai).oper[1]^.reg;
|
||||
taicpu(curtai).oper[1]^.reg := op2reg;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
curtai:=tai(curtai.Next);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure finalizearmcode(list, listtoinsert: TAsmList);
|
||||
begin
|
||||
insertpcrelativedata(list, listtoinsert);
|
||||
|
||||
{ Do Thumb-2 16bit -> 32bit transformations }
|
||||
if current_settings.cputype in cpu_thumb2 then
|
||||
ensurethumb2encodings(list);
|
||||
end;
|
||||
|
||||
procedure InsertPData;
|
||||
var
|
||||
prolog: TAsmList;
|
||||
|
@ -225,17 +225,21 @@ unit agarmgas;
|
||||
|
||||
Procedure TArmInstrWriter.WriteInstruction(hp : tai);
|
||||
var op: TAsmOp;
|
||||
s: string;
|
||||
postfix,s: string;
|
||||
i: byte;
|
||||
sep: string[3];
|
||||
begin
|
||||
op:=taicpu(hp).opcode;
|
||||
if current_settings.cputype in cpu_thumb2 then
|
||||
begin
|
||||
postfix:='';
|
||||
if taicpu(hp).wideformat then
|
||||
postfix:='.w';
|
||||
|
||||
if taicpu(hp).ops = 0 then
|
||||
s:=#9+gas_op2str[op]+' '+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix]
|
||||
else
|
||||
s:=#9+gas_op2str[op]+oppostfix2str[taicpu(hp).oppostfix]+cond2str[taicpu(hp).condition]; // Conditional infixes are deprecated in unified syntax
|
||||
s:=#9+gas_op2str[op]+oppostfix2str[taicpu(hp).oppostfix]+postfix+cond2str[taicpu(hp).condition]; // Conditional infixes are deprecated in unified syntax
|
||||
end
|
||||
else
|
||||
s:=#9+gas_op2str[op]+cond2str[taicpu(hp).condition]+oppostfix2str[taicpu(hp).oppostfix];
|
||||
|
@ -2810,12 +2810,12 @@ unit cgcpu;
|
||||
inherited init_register_allocators;
|
||||
{ currently, we save R14 always, so we can use it }
|
||||
if (target_info.system<>system_arm_darwin) then
|
||||
rg[R_INTREGISTER]:=trgcputhumb2.create(R_INTREGISTER,R_SUBWHOLE,
|
||||
rg[R_INTREGISTER]:=trgintcputhumb2.create(R_INTREGISTER,R_SUBWHOLE,
|
||||
[RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
|
||||
RS_R9,RS_R10,RS_R12,RS_R14],first_int_imreg,[])
|
||||
else
|
||||
{ r9 is not available on Darwin according to the llvm code generator }
|
||||
rg[R_INTREGISTER]:=trgcputhumb2.create(R_INTREGISTER,R_SUBWHOLE,
|
||||
rg[R_INTREGISTER]:=trgintcputhumb2.create(R_INTREGISTER,R_SUBWHOLE,
|
||||
[RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
|
||||
RS_R10,RS_R12,RS_R14],first_int_imreg,[]);
|
||||
rg[R_FPUREGISTER]:=trgcputhumb2.create(R_FPUREGISTER,R_SUBNONE,
|
||||
|
@ -36,6 +36,7 @@ unit raarm;
|
||||
|
||||
TARMInstruction=class(TInstruction)
|
||||
oppostfix : toppostfix;
|
||||
wideformat : boolean; // For wide(32bit) instructions of the thumb-2 instruction set
|
||||
function ConcatInstruction(p:TAsmList) : tai;override;
|
||||
end;
|
||||
|
||||
@ -48,6 +49,7 @@ unit raarm;
|
||||
begin
|
||||
result:=inherited ConcatInstruction(p);
|
||||
(result as taicpu).oppostfix:=oppostfix;
|
||||
(result as taicpu).wideformat:=wideformat;
|
||||
end;
|
||||
|
||||
|
||||
|
@ -32,6 +32,7 @@ Unit raarmgas;
|
||||
type
|
||||
tarmattreader = class(tattreader)
|
||||
actoppostfix : TOpPostfix;
|
||||
actwideformat : boolean;
|
||||
function is_asmopcode(const s: string):boolean;override;
|
||||
function is_register(const s:string):boolean;override;
|
||||
procedure handleopcode;override;
|
||||
@ -916,6 +917,7 @@ Unit raarmgas;
|
||||
Opcode:=ActOpcode;
|
||||
condition:=ActCondition;
|
||||
oppostfix:=actoppostfix;
|
||||
wideformat:=actwideformat;
|
||||
end;
|
||||
|
||||
{ We are reading operands, so opcode will be an AS_ID }
|
||||
@ -1056,6 +1058,15 @@ Unit raarmgas;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{ check for format postfix }
|
||||
if length(hs)>0 then
|
||||
begin
|
||||
if upcase(copy(hs,1,2)) = '.W' then
|
||||
begin
|
||||
actwideformat:=true;
|
||||
delete(hs,1,2);
|
||||
end;
|
||||
end;
|
||||
{ if we stripped all postfixes, it's a valid opcode }
|
||||
is_asmopcode:=length(hs)=0;
|
||||
end;
|
||||
@ -1094,6 +1105,7 @@ Unit raarmgas;
|
||||
instr.ConcatInstruction(curlist);
|
||||
instr.Free;
|
||||
actoppostfix:=PF_None;
|
||||
actwideformat:=false;
|
||||
end;
|
||||
|
||||
|
||||
|
@ -46,6 +46,10 @@ unit rgcpu;
|
||||
procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
|
||||
end;
|
||||
|
||||
trgintcputhumb2 = class(trgcputhumb2)
|
||||
procedure add_cpu_interferences(p : tai);override;
|
||||
end;
|
||||
|
||||
trgintcpu = class(trgcpu)
|
||||
procedure add_cpu_interferences(p : tai);override;
|
||||
end;
|
||||
@ -57,6 +61,44 @@ unit rgcpu;
|
||||
cgobj,
|
||||
procinfo;
|
||||
|
||||
procedure trgintcputhumb2.add_cpu_interferences(p: tai);
|
||||
begin
|
||||
if p.typ=ait_instruction then
|
||||
begin
|
||||
case taicpu(p).opcode of
|
||||
A_ADD:
|
||||
begin
|
||||
if taicpu(p).ops = 3 then
|
||||
begin
|
||||
if (taicpu(p).oper[0]^.typ = top_reg) and
|
||||
(taicpu(p).oper[1]^.typ = top_reg) and
|
||||
(taicpu(p).oper[2]^.typ in [top_reg, top_shifterop]) then
|
||||
begin
|
||||
{ if d == 13 || (d == 15 && S == ‘0’) || n == 15 || m IN [13,15] then UNPREDICTABLE; }
|
||||
add_edge(getsupreg(taicpu(p).oper[0]^.reg), RS_R13);
|
||||
if taicpu(p).oppostfix <> PF_S then
|
||||
add_edge(getsupreg(taicpu(p).oper[0]^.reg), RS_R15);
|
||||
|
||||
add_edge(getsupreg(taicpu(p).oper[1]^.reg), RS_R15);
|
||||
|
||||
if (taicpu(p).oper[2]^.typ = top_shifterop) and
|
||||
(taicpu(p).oper[2]^.shifterop^.rs <> NR_NO) then
|
||||
begin
|
||||
add_edge(getsupreg(taicpu(p).oper[2]^.shifterop^.rs), RS_R13);
|
||||
add_edge(getsupreg(taicpu(p).oper[2]^.shifterop^.rs), RS_R15);
|
||||
end
|
||||
else if (taicpu(p).oper[2]^.typ = top_reg) then
|
||||
begin
|
||||
add_edge(getsupreg(taicpu(p).oper[2]^.reg), RS_R13);
|
||||
add_edge(getsupreg(taicpu(p).oper[2]^.reg), RS_R15);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure trgcpu.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
|
||||
var
|
||||
|
@ -1227,7 +1227,7 @@ implementation
|
||||
|
||||
{$ifdef ARM}
|
||||
{ because of the limited constant size of the arm, all data access is done pc relative }
|
||||
insertpcrelativedata(aktproccode,aktlocaldata);
|
||||
finalizearmcode(aktproccode,aktlocaldata);
|
||||
{$endif ARM}
|
||||
|
||||
{ Add end symbol and debug info }
|
||||
|
@ -258,6 +258,25 @@ unit raatt;
|
||||
end
|
||||
end;
|
||||
{$endif POWERPC}
|
||||
{$if defined(ARM)}
|
||||
{ Thumb-2 instructions can have a .W postfix to indicate 32bit instructions
|
||||
}
|
||||
case c of
|
||||
'.':
|
||||
begin
|
||||
actasmpattern:=actasmpattern+c;
|
||||
c:=current_scanner.asmgetchar;
|
||||
|
||||
if upcase(c) = 'W' then
|
||||
begin
|
||||
actasmpattern:=actasmpattern+c;
|
||||
c:=current_scanner.asmgetchar;
|
||||
end
|
||||
else
|
||||
internalerror(2010122301);
|
||||
end
|
||||
end;
|
||||
{$endif ARM}
|
||||
{ Opcode ? }
|
||||
If is_asmopcode(upper(actasmpattern)) then
|
||||
Begin
|
||||
|
@ -148,7 +148,7 @@ asm
|
||||
moveq pc,lr
|
||||
rsb r1,r1,#7
|
||||
mov r1,r1,lsl #2
|
||||
add pc,pc,r1
|
||||
add pc,r1
|
||||
mov r0,r0
|
||||
strb r2,[r3],#1
|
||||
strb r2,[r3],#1
|
||||
|
Loading…
Reference in New Issue
Block a user