|
@@ -29,7 +29,8 @@ uses
|
|
cclasses,
|
|
cclasses,
|
|
globtype,globals,verbose,
|
|
globtype,globals,verbose,
|
|
aasmbase,aasmtai,aasmdata,aasmsym,
|
|
aasmbase,aasmtai,aasmdata,aasmsym,
|
|
- cgbase,cgutils,cpubase,cpuinfo;
|
|
|
|
|
|
+ cgbase,cgutils,cpubase,cpuinfo,
|
|
|
|
+ ogbase;
|
|
|
|
|
|
const
|
|
const
|
|
{ "mov reg,reg" source operand number }
|
|
{ "mov reg,reg" source operand number }
|
|
@@ -37,7 +38,19 @@ uses
|
|
{ "mov reg,reg" source operand number }
|
|
{ "mov reg,reg" source operand number }
|
|
O_MOV_DEST = 0;
|
|
O_MOV_DEST = 0;
|
|
|
|
|
|
|
|
+ maxinfolen = 5;
|
|
|
|
+
|
|
type
|
|
type
|
|
|
|
+ tinsentry = record
|
|
|
|
+ opcode : tasmop;
|
|
|
|
+ ops : byte;
|
|
|
|
+ optypes : array[0..3] of longint;
|
|
|
|
+ code : array[0..maxinfolen] of char;
|
|
|
|
+ flags : longint;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ pinsentry=^tinsentry;
|
|
|
|
+
|
|
taicpu = class(tai_cpu_abstract_sym)
|
|
taicpu = class(tai_cpu_abstract_sym)
|
|
constructor op_none(op : tasmop);
|
|
constructor op_none(op : tasmop);
|
|
|
|
|
|
@@ -61,6 +74,24 @@ uses
|
|
|
|
|
|
{ register spilling code }
|
|
{ register spilling code }
|
|
function spilling_get_operation_type(opnr: longint): topertype;override;
|
|
function spilling_get_operation_type(opnr: longint): topertype;override;
|
|
|
|
+
|
|
|
|
+ { assembler }
|
|
|
|
+ public
|
|
|
|
+ { the next will reset all instructions that can change in pass 2 }
|
|
|
|
+ procedure ResetPass1;override;
|
|
|
|
+ procedure ResetPass2;override;
|
|
|
|
+{ function CheckIfValid:boolean;
|
|
|
|
+ function GetString:string; }
|
|
|
|
+ function Pass1(objdata:TObjData):longint;override;
|
|
|
|
+// procedure Pass2(objdata:TObjData);override;
|
|
|
|
+ function calcsize(p:PInsEntry):shortint;
|
|
|
|
+ private
|
|
|
|
+ { next fields are filled in pass1, so pass2 is faster }
|
|
|
|
+ inssize : shortint;
|
|
|
|
+ insoffset : longint;
|
|
|
|
+ insentry : PInsEntry;
|
|
|
|
+ LastInsOffset : longint; { need to be public to be reset }
|
|
|
|
+ function FindInsentry(objdata:TObjData):boolean;
|
|
end;
|
|
end;
|
|
|
|
|
|
tai_align = class(tai_align_abstract)
|
|
tai_align = class(tai_align_abstract)
|
|
@@ -75,6 +106,10 @@ uses
|
|
|
|
|
|
function setcondition(i : taicpu;c : tasmcond) : taicpu;
|
|
function setcondition(i : taicpu;c : tasmcond) : taicpu;
|
|
|
|
|
|
|
|
+ { replaces cond. branches by rjmp/jmp and the inverse cond. branch if needed
|
|
|
|
+ and transforms special instructions to valid instruction encodings }
|
|
|
|
+ procedure finalizeavrcode(list : TAsmList);
|
|
|
|
+
|
|
implementation
|
|
implementation
|
|
|
|
|
|
{*****************************************************************************
|
|
{*****************************************************************************
|
|
@@ -222,6 +257,84 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
+ function taicpu.calcsize(p:PInsEntry):shortint;
|
|
|
|
+ begin
|
|
|
|
+ case opcode of
|
|
|
|
+ A_CALL,
|
|
|
|
+ A_JMP:
|
|
|
|
+ result:=4;
|
|
|
|
+ A_LDS:
|
|
|
|
+ if (getsupreg(oper[0]^.reg)>=RS_R16) and (getsupreg(oper[0]^.reg)<=RS_R31) and
|
|
|
|
+ (oper[1]^.val>=0) and (oper[1]^.val<=127) then
|
|
|
|
+ result:=2
|
|
|
|
+ else
|
|
|
|
+ result:=4;
|
|
|
|
+ A_STS:
|
|
|
|
+ if (getsupreg(oper[1]^.reg)>=RS_R16) and (getsupreg(oper[1]^.reg)<=RS_R31) and
|
|
|
|
+ (oper[0]^.val>=0) and (oper[0]^.val<=127) then
|
|
|
|
+ result:=2
|
|
|
|
+ else
|
|
|
|
+ result:=4;
|
|
|
|
+ else
|
|
|
|
+ result:=2;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ procedure taicpu.ResetPass1;
|
|
|
|
+ begin
|
|
|
|
+ { we need to reset everything here, because the choosen insentry
|
|
|
|
+ can be invalid for a new situation where the previously optimized
|
|
|
|
+ insentry is not correct }
|
|
|
|
+ InsEntry:=nil;
|
|
|
|
+ InsSize:=0;
|
|
|
|
+ LastInsOffset:=-1;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ procedure taicpu.ResetPass2;
|
|
|
|
+ begin
|
|
|
|
+{ { we are here in a second pass, check if the instruction can be optimized }
|
|
|
|
+ if assigned(InsEntry) and
|
|
|
|
+ ((InsEntry^.flags and IF_PASS2)<>0) then
|
|
|
|
+ begin
|
|
|
|
+ InsEntry:=nil;
|
|
|
|
+ InsSize:=0;
|
|
|
|
+ end;
|
|
|
|
+}
|
|
|
|
+ LastInsOffset:=-1;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ function taicpu.FindInsentry(objdata:TObjData):boolean;
|
|
|
|
+ begin
|
|
|
|
+ result:=false;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ function taicpu.Pass1(objdata:TObjData):longint;
|
|
|
|
+ begin
|
|
|
|
+ Pass1:=0;
|
|
|
|
+ { Save the old offset and set the new offset }
|
|
|
|
+ InsOffset:=ObjData.CurrObjSec.Size;
|
|
|
|
+ InsSize:=calcsize(InsEntry);
|
|
|
|
+ { Error? }
|
|
|
|
+ if (Insentry=nil) and (InsSize=-1) then
|
|
|
|
+ exit;
|
|
|
|
+ { set the file postion }
|
|
|
|
+ current_filepos:=fileinfo;
|
|
|
|
+
|
|
|
|
+ { Get InsEntry }
|
|
|
|
+ if FindInsEntry(objdata) then
|
|
|
|
+ begin
|
|
|
|
+ LastInsOffset:=InsOffset;
|
|
|
|
+ Pass1:=InsSize;
|
|
|
|
+ exit;
|
|
|
|
+ end;
|
|
|
|
+ LastInsOffset:=-1;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
function spilling_create_load(const ref:treference;r:tregister):Taicpu;
|
|
function spilling_create_load(const ref:treference;r:tregister):Taicpu;
|
|
begin
|
|
begin
|
|
case getregtype(r) of
|
|
case getregtype(r) of
|
|
@@ -277,6 +390,65 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
+ procedure finalizeavrcode(list : TAsmList);
|
|
|
|
+ var
|
|
|
|
+ CurrOffset : longint;
|
|
|
|
+ curtai : tai;
|
|
|
|
+ again : boolean;
|
|
|
|
+ l : tasmlabel;
|
|
|
|
+ begin
|
|
|
|
+ again:=true;
|
|
|
|
+ while again do
|
|
|
|
+ begin
|
|
|
|
+ again:=false;
|
|
|
|
+ CurrOffset:=0;
|
|
|
|
+ curtai:=tai(list.first);
|
|
|
|
+ while assigned(curtai) do
|
|
|
|
+ begin
|
|
|
|
+ { instruction? }
|
|
|
|
+ if not(curtai.typ in SkipInstr) then
|
|
|
|
+ case curtai.typ of
|
|
|
|
+ ait_instruction:
|
|
|
|
+ begin
|
|
|
|
+ taicpu(curtai).InsOffset:=CurrOffset;
|
|
|
|
+ inc(CurrOffset,taicpu(curtai).calcsize(nil));
|
|
|
|
+ end;
|
|
|
|
+ ait_align:
|
|
|
|
+ inc(CurrOffset,tai_align(curtai).aligntype);
|
|
|
|
+ ait_marker:
|
|
|
|
+ ;
|
|
|
|
+ ait_label:
|
|
|
|
+ begin
|
|
|
|
+ tai_label(curtai).labsym.offset:=CurrOffset;
|
|
|
|
+ end;
|
|
|
|
+ else
|
|
|
|
+ internalerror(2011082401);
|
|
|
|
+ end;
|
|
|
|
+ curtai:=tai(curtai.next);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ curtai:=tai(list.first);
|
|
|
|
+ while assigned(curtai) do
|
|
|
|
+ begin
|
|
|
|
+ if (curtai.typ=ait_instruction) and
|
|
|
|
+ (taicpu(curtai).opcode in [A_BRxx]) and
|
|
|
|
+ ((taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset>64) or
|
|
|
|
+ (taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset<-63)
|
|
|
|
+ ) then
|
|
|
|
+ begin
|
|
|
|
+ current_asmdata.getjumplabel(l);
|
|
|
|
+ list.insertafter(tai_label.create(l),curtai);
|
|
|
|
+ list.insertafter(taicpu.op_sym(A_JMP,taicpu(curtai).oper[0]^.ref^.symbol),curtai);
|
|
|
|
+ taicpu(curtai).oper[0]^.ref^.symbol:=l;
|
|
|
|
+ taicpu(curtai).condition:=inverse_cond(taicpu(curtai).condition);
|
|
|
|
+ again:=true;
|
|
|
|
+ end;
|
|
|
|
+ curtai:=tai(curtai.next);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
begin
|
|
begin
|
|
cai_cpu:=taicpu;
|
|
cai_cpu:=taicpu;
|
|
cai_align:=tai_align;
|
|
cai_align:=tai_align;
|