summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjanbruns <janbruns@3ad0048d-3df7-0310-abae-a5850022a9f2>2008-04-19 14:36:55 +0000
committerjanbruns <janbruns@3ad0048d-3df7-0310-abae-a5850022a9f2>2008-04-19 14:36:55 +0000
commit20b60766016dedfe74ca1f02edde4d66e4f590f6 (patch)
treea58d13eccc5570a8ce50aef73298e33bc2e8cc8b
parent5bd5308c126e1cdeac24d7f1830fe834c3c179c4 (diff)
downloadfpc-20b60766016dedfe74ca1f02edde4d66e4f590f6.tar.gz
ARM: Add rg-support for the new virtual instructions
The virtual instructions are still unused, so this change shouldn't influence the actual compiler behaviour. git-svn-id: http://svn.freepascal.org/svn/fpc/branches/janbruns@10715 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--initial/compiler/arm/aasmcpu.pas67
-rw-r--r--initial/compiler/arm/rgcpu.pas68
2 files changed, 131 insertions, 4 deletions
diff --git a/initial/compiler/arm/aasmcpu.pas b/initial/compiler/arm/aasmcpu.pas
index 7d6cab7f6c..7461e86d1f 100644
--- a/initial/compiler/arm/aasmcpu.pas
+++ b/initial/compiler/arm/aasmcpu.pas
@@ -499,6 +499,21 @@ implementation
end;
+{$IFDEF USE_VIRTUAL_INSTRUCTIONS}
+
+ function spilling_create_load(const ref:treference;r:tregister):Taicpu;
+ begin
+ result:=taicpu.op_reg_ref(A_ZZZ_VIRTUALUNSPILL,r,ref);
+ end;
+
+
+ function spilling_create_store(r:tregister; const ref:treference):Taicpu;
+ begin
+ result:=taicpu.op_reg_ref(A_ZZZ_VIRTUALSPILL,r,ref);
+ end;
+
+{$ELSE don't USE_VIRTUAL_INSTRUCTIONS}
+
function spilling_create_load(const ref:treference;r:tregister):Taicpu;
begin
case getregtype(r) of
@@ -530,6 +545,8 @@ implementation
end;
end;
+{$ENDIF}
+
function taicpu.spilling_get_operation_type(opnr: longint): topertype;
begin
@@ -573,8 +590,56 @@ implementation
else
{ check for pre/post indexed }
result := operand_read;
+
+ A_ZZZ_VIRTUALSAVE :
+ begin
+ // when storing a reg, the reg to be stored is read,
+ // temps might be written, refs read
+ if opnr=0
+ then result := operand_read
+ else begin
+ if (oper[opnr]^.typ = top_reg)
+ or (oper[opnr]^.typ = top_regset) then result := operand_write
+ else result := operand_read;
+ end;
+ end;
+
+ A_ZZZ_VIRTUALLOAD :
+ begin
+ // same as virtualstore, only that the reg is written (read from mem)
+ if opnr=0
+ then result := operand_write
+ else begin
+ if (oper[opnr]^.typ = top_reg)
+ or (oper[opnr]^.typ = top_regset) then result := operand_write
+ else result := operand_read;
+ end;
+ end;
+
+ A_ZZZ_VIRTUALCOPY :
+ begin
+ // if this instrctuction has reg-operands, they're
+ // used as temps, so they're virtually only written to
+ if (oper[opnr]^.typ = top_reg)
+ or (oper[opnr]^.typ = top_regset) then result := operand_write
+ else result := operand_read;
+ end;
+
+ A_ZZZ_VIRTUALSPILL :
+ begin
+ // we won't modify registers when spilling
+ result := operand_read;
+ end;
+
+ A_ZZZ_VIRTUALUNSPILL :
+ begin
+ // we read the register back, so the register is written
+ if opnr=0 then result := operand_write
+ else result := operand_read;
+ end;
+
else
- internalerror(200403151);
+ internalerror(2008041802);
end;
end;
diff --git a/initial/compiler/arm/rgcpu.pas b/initial/compiler/arm/rgcpu.pas
index 58b8d9cc43..0676840558 100644
--- a/initial/compiler/arm/rgcpu.pas
+++ b/initial/compiler/arm/rgcpu.pas
@@ -41,6 +41,8 @@ unit rgcpu;
trgintcpu = class(trgcpu)
procedure add_cpu_interferences(p : tai);override;
+
+ procedure add_regset_edges(s : Tcpuregisterset; v:Tsuperregister); virtual;
end;
implementation
@@ -157,9 +159,25 @@ unit rgcpu;
end;
+
+ procedure trgintcpu.add_regset_edges(s : Tcpuregisterset; v:Tsuperregister);
+ const num2reg : array[0..15] of Tsuperregister = (RS_R0,RS_R1,RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15);
+ var i : longint; r : Tsuperregister;
+ begin
+ for i := 0 to 15 do begin
+ r := num2reg[i];
+ if (r in s) then begin
+ add_edge(r,v);
+ add_edge(v,r);
+ end;
+ end;
+ end;
+
+
+
procedure trgintcpu.add_cpu_interferences(p : tai);
var
- r : tregister;
+ r : tregister; i,j : longint;
begin
if p.typ=ait_instruction then
begin
@@ -181,6 +199,13 @@ unit rgcpu;
A_LDR,
A_LDRH,
A_STRH:
+ {
+ Did this happen?
+ Where/why, and if so, why disallow?
+ For now, I (JB) leave this here, but I think this "problem"
+ should be fixed elsewhere.
+ }
+
{ don't mix up the framepointer and stackpointer with pre/post indexed operations }
if (taicpu(p).oper[1]^.typ=top_ref) and
(taicpu(p).oper[1]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) then
@@ -192,8 +217,45 @@ unit rgcpu;
if current_procinfo.framepointer<>r then
add_edge(getsupreg(taicpu(p).oper[1]^.ref^.base),getsupreg(r));
end;
- end;
- end;
+
+ A_ZZZ_VIRTUALLOAD,
+ A_ZZZ_VIRTUALSAVE,
+ A_ZZZ_VIRTUALCOPY :
+ begin
+ { if the instruction contains tempregs, make sure they're
+ all diffrent, also from the reg to load/store. regs given
+ in the ref may probably be shared, if they aren't needed
+ anymore.
+ }
+ for i := taicpu(p).ops-1 downto 0 do begin
+
+ if (taicpu(p).oper[i]^.typ in [top_reg,top_regset]) then begin
+
+ for j := taicpu(p).ops-1 downto 0 do begin
+
+ if not(i=j) and (taicpu(p).oper[j]^.typ=top_reg) then begin
+ if (taicpu(p).oper[i]^.typ=top_reg)
+ then add_edge( getsupreg( taicpu(p).oper[i]^.reg ) ,getsupreg(taicpu(p).oper[j]^.reg))
+ else add_regset_edges( taicpu(p).oper[i]^.regset^,getsupreg(taicpu(p).oper[j]^.reg));
+ end;
+
+ end;
+ end;
+ if taicpu(p).opcode=A_ZZZ_VIRTUALCOPY then begin
+ { Maybe it's needed to add additional constraints
+ for copying refs, here. I'm unsure what to do
+ if tempregs are equal to refregs of both refs.
+ We should probably not generate that case, or
+ maybe concatcopy will be able to deal with this
+ situation.
+ }
+ end;
+ end;
+ end;
+ A_ZZZ_VIRTUALSPILL,
+ A_ZZZ_VIRTUALUNSPILL : ; // actually no known constraints
+ end; {case instr}
+ end; {if tai-instr}
end;