|
@@ -45,6 +45,9 @@ unit rgcpu;
|
|
|
end;
|
|
|
|
|
|
trgcputhumb2 = class(trgobj)
|
|
|
+ private
|
|
|
+ procedure SplitITBlock(list:TAsmList;pos:tai);
|
|
|
+ public
|
|
|
procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
|
|
|
procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
|
|
|
end;
|
|
@@ -245,6 +248,100 @@ unit rgcpu;
|
|
|
result:=getsubreg(r);
|
|
|
end;
|
|
|
|
|
|
+ function IsIT(op: TAsmOp) : boolean;
|
|
|
+ begin
|
|
|
+ case op of
|
|
|
+ A_IT,
|
|
|
+ A_ITE, A_ITT,
|
|
|
+ A_ITEE, A_ITTE, A_ITET, A_ITTT,
|
|
|
+ A_ITEEE, A_ITTEE, A_ITETE, A_ITTTE,
|
|
|
+ A_ITEET, A_ITTET, A_ITETT, A_ITTTT:
|
|
|
+ result:=true;
|
|
|
+ else
|
|
|
+ result:=false;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ function GetITLevels(op: TAsmOp) : longint;
|
|
|
+ begin
|
|
|
+ case op of
|
|
|
+ A_IT:
|
|
|
+ result:=1;
|
|
|
+ A_ITE, A_ITT:
|
|
|
+ result:=2;
|
|
|
+ A_ITEE, A_ITTE, A_ITET, A_ITTT:
|
|
|
+ result:=3;
|
|
|
+ A_ITEEE, A_ITTEE, A_ITETE, A_ITTTE,
|
|
|
+ A_ITEET, A_ITTET, A_ITETT, A_ITTTT:
|
|
|
+ result:=4;
|
|
|
+ else
|
|
|
+ result:=0;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ function GetITRemainderOp(originalOp:TAsmOp;remLevels:longint;var newOp: TAsmOp;var NeedsCondSwap:boolean) : TAsmOp;
|
|
|
+ const
|
|
|
+ remOps : array[1..3] of array[A_ITE..A_ITTTT] of TAsmOp = (
|
|
|
+ (A_IT,A_IT, A_IT,A_IT,A_IT,A_IT, A_IT,A_IT,A_IT,A_IT,A_IT,A_IT,A_IT,A_IT),
|
|
|
+ (A_NONE,A_NONE, A_ITT,A_ITE,A_ITE,A_ITT, A_ITT,A_ITT,A_ITE,A_ITE,A_ITE,A_ITE,A_ITT,A_ITT),
|
|
|
+ (A_NONE,A_NONE, A_NONE,A_NONE,A_NONE,A_NONE, A_ITTT,A_ITEE,A_ITET,A_ITTE,A_ITTE,A_ITET,A_ITEE,A_ITTT));
|
|
|
+ newOps : array[1..3] of array[A_ITE..A_ITTTT] of TAsmOp = (
|
|
|
+ (A_IT,A_IT, A_ITE,A_ITT,A_ITE,A_ITT, A_ITEE,A_ITTE,A_ITET,A_ITTT,A_ITEE,A_ITTE,A_ITET,A_ITTT),
|
|
|
+ (A_NONE,A_NONE, A_IT,A_IT,A_IT,A_IT, A_ITE,A_ITT,A_ITE,A_ITT,A_ITE,A_ITT,A_ITE,A_ITT),
|
|
|
+ (A_NONE,A_NONE, A_NONE,A_NONE,A_NONE,A_NONE, A_IT,A_IT,A_IT,A_IT,A_IT,A_IT,A_IT,A_IT));
|
|
|
+ needsSwap: array[1..3] of array[A_ITE..A_ITTTT] of Boolean = (
|
|
|
+ (true ,false, true ,true ,false,false, true ,true ,true ,true ,false,false,false,false),
|
|
|
+ (false,false, true ,false,true ,false, true ,true ,false,false,true ,true ,false,false),
|
|
|
+ (false,false, false,false,false,false, true ,false,true ,false,true ,false,true ,false));
|
|
|
+ begin
|
|
|
+ result:=remOps[remLevels][originalOp];
|
|
|
+ newOp:=newOps[remLevels][originalOp];
|
|
|
+ NeedsCondSwap:=needsSwap[remLevels][originalOp];
|
|
|
+ end;
|
|
|
+
|
|
|
+ procedure trgcputhumb2.SplitITBlock(list: TAsmList; pos: tai);
|
|
|
+ var
|
|
|
+ hp : tai;
|
|
|
+ level,itLevel : LongInt;
|
|
|
+ remOp,newOp : TAsmOp;
|
|
|
+ needsSwap : boolean;
|
|
|
+ begin
|
|
|
+ hp:=pos;
|
|
|
+ level := 0;
|
|
|
+ while assigned(hp) do
|
|
|
+ begin
|
|
|
+ if IsIT(taicpu(hp).opcode) then
|
|
|
+ break
|
|
|
+ else if hp.typ=ait_instruction then
|
|
|
+ inc(level);
|
|
|
+
|
|
|
+ hp:=tai(hp.Previous);
|
|
|
+ end;
|
|
|
+
|
|
|
+ if not assigned(hp) then
|
|
|
+ internalerror(2012100801); // We are supposed to have found the ITxxx instruction here
|
|
|
+
|
|
|
+ if (hp.typ<>ait_instruction) or
|
|
|
+ (not IsIT(taicpu(hp).opcode)) then
|
|
|
+ internalerror(2012100802); // Sanity check
|
|
|
+
|
|
|
+ itLevel := GetITLevels(taicpu(hp).opcode);
|
|
|
+ if level=itLevel then
|
|
|
+ exit; // pos was the last instruction in the IT block anyway
|
|
|
+
|
|
|
+ remOp:=GetITRemainderOp(taicpu(hp).opcode,itLevel-level,newOp,needsSwap);
|
|
|
+
|
|
|
+ if (remOp=A_NONE) or
|
|
|
+ (newOp=A_NONE) then
|
|
|
+ Internalerror(2012100803);
|
|
|
+
|
|
|
+ taicpu(hp).opcode:=newOp;
|
|
|
+
|
|
|
+ if needsSwap then
|
|
|
+ list.InsertAfter(taicpu.op_cond(remOp,inverse_cond(taicpu(hp).oper[0]^.cc)), pos)
|
|
|
+ else
|
|
|
+ list.InsertAfter(taicpu.op_cond(remOp,taicpu(hp).oper[0]^.cc), pos);
|
|
|
+ end;
|
|
|
|
|
|
procedure trgcputhumb2.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
|
|
|
var
|
|
@@ -267,6 +364,18 @@ unit rgcpu;
|
|
|
(taicpu(pos).oper[1]^.reg=NR_PC) then
|
|
|
pos:=tai(pos.previous);
|
|
|
|
|
|
+ if (pos.typ=ait_instruction) and
|
|
|
+ (taicpu(pos).condition<>C_None) and
|
|
|
+ (taicpu(pos).opcode<>A_B) then
|
|
|
+ SplitITBlock(list, pos)
|
|
|
+ else if (pos.typ=ait_instruction) and
|
|
|
+ IsIT(taicpu(pos).opcode) then
|
|
|
+ begin
|
|
|
+ if not assigned(pos.Previous) then
|
|
|
+ list.InsertBefore(tai_comment.Create('Dummy'), pos);
|
|
|
+ pos:=tai(pos.Previous);
|
|
|
+ end;
|
|
|
+
|
|
|
if (spilltemp.offset>4095) or (spilltemp.offset<-255) then
|
|
|
begin
|
|
|
helplist:=TAsmList.create;
|
|
@@ -313,6 +422,18 @@ unit rgcpu;
|
|
|
l : tasmlabel;
|
|
|
hreg : tregister;
|
|
|
begin
|
|
|
+ if (pos.typ=ait_instruction) and
|
|
|
+ (taicpu(pos).condition<>C_None) and
|
|
|
+ (taicpu(pos).opcode<>A_B) then
|
|
|
+ SplitITBlock(list, pos)
|
|
|
+ else if (pos.typ=ait_instruction) and
|
|
|
+ IsIT(taicpu(pos).opcode) then
|
|
|
+ begin
|
|
|
+ if not assigned(pos.Previous) then
|
|
|
+ list.InsertBefore(tai_comment.Create('Dummy'), pos);
|
|
|
+ pos:=tai(pos.Previous);
|
|
|
+ end;
|
|
|
+
|
|
|
if (spilltemp.offset>4095) or (spilltemp.offset<-255) then
|
|
|
begin
|
|
|
helplist:=TAsmList.create;
|