|
@@ -108,7 +108,7 @@ uses
|
|
|
|
|
|
{ replaces cond. branches by rjmp/jmp and the inverse cond. branch if needed
|
|
{ replaces cond. branches by rjmp/jmp and the inverse cond. branch if needed
|
|
and transforms special instructions to valid instruction encodings }
|
|
and transforms special instructions to valid instruction encodings }
|
|
- procedure finalizeavrcode(list : TAsmList);
|
|
|
|
|
|
+ function finalizeavrcode(list : TAsmList) : Boolean;
|
|
|
|
|
|
implementation
|
|
implementation
|
|
|
|
|
|
@@ -396,15 +396,42 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
- procedure finalizeavrcode(list : TAsmList);
|
|
|
|
|
|
+ function finalizeavrcode(list : TAsmList) : Boolean;
|
|
var
|
|
var
|
|
CurrOffset : longint;
|
|
CurrOffset : longint;
|
|
- curtai : tai;
|
|
|
|
|
|
+ curtai, firstinstruction: tai;
|
|
again : boolean;
|
|
again : boolean;
|
|
l : tasmlabel;
|
|
l : tasmlabel;
|
|
inasmblock : Boolean;
|
|
inasmblock : Boolean;
|
|
|
|
+
|
|
|
|
+ procedure remove_instruction;
|
|
|
|
+ var
|
|
|
|
+ i: Integer;
|
|
|
|
+ hp: tai;
|
|
|
|
+ begin
|
|
|
|
+ taicpu(firstinstruction).opcode:=A_SLEEP;
|
|
|
|
+ for i:=0 to taicpu(firstinstruction).opercnt-1 do
|
|
|
|
+ taicpu(firstinstruction).freeop(i);
|
|
|
|
+ taicpu(firstinstruction).opercnt:=0;
|
|
|
|
+ taicpu(firstinstruction).ops:=0;
|
|
|
|
+ firstinstruction:=tai(firstinstruction.Next);
|
|
|
|
+ while assigned(firstinstruction) do
|
|
|
|
+ begin
|
|
|
|
+ if firstinstruction.typ in [ait_symbol_end,ait_label] then
|
|
|
|
+ firstinstruction:=tai(firstinstruction.Next)
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ hp:=tai(firstinstruction.Next);
|
|
|
|
+ list.Remove(firstinstruction);
|
|
|
|
+ firstinstruction.free;
|
|
|
|
+ firstinstruction:=hp;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
begin
|
|
begin
|
|
again:=true;
|
|
again:=true;
|
|
|
|
+ Result:=true;
|
|
while again do
|
|
while again do
|
|
begin
|
|
begin
|
|
again:=false;
|
|
again:=false;
|
|
@@ -439,62 +466,95 @@ implementation
|
|
|
|
|
|
curtai:=tai(list.first);
|
|
curtai:=tai(list.first);
|
|
inasmblock:=false;
|
|
inasmblock:=false;
|
|
|
|
+ firstinstruction:=nil;
|
|
while assigned(curtai) do
|
|
while assigned(curtai) do
|
|
begin
|
|
begin
|
|
case curtai.typ of
|
|
case curtai.typ of
|
|
ait_instruction:
|
|
ait_instruction:
|
|
- case taicpu(curtai).opcode of
|
|
|
|
- A_BRxx:
|
|
|
|
- if (taicpu(curtai).oper[0]^.typ=top_ref) 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
|
|
|
|
+ if not(assigned(firstinstruction)) then
|
|
|
|
+ firstinstruction:=curtai;
|
|
|
|
+ case taicpu(curtai).opcode of
|
|
|
|
+ A_BRxx:
|
|
|
|
+ if (taicpu(curtai).oper[0]^.typ=top_ref) 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
|
|
|
|
+ if inasmblock then
|
|
|
|
+ Message(asmw_e_brxx_out_of_range)
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ current_asmdata.getjumplabel(l);
|
|
|
|
+ list.insertafter(tai_label.create(l),curtai);
|
|
|
|
+ if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
|
|
|
|
+ list.insertafter(taicpu.op_sym(A_JMP,taicpu(curtai).oper[0]^.ref^.symbol),curtai)
|
|
|
|
+ else
|
|
|
|
+ list.insertafter(taicpu.op_sym(A_RJMP,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;
|
|
|
|
+ end;
|
|
|
|
+ A_JMP:
|
|
|
|
+ { replace JMP by RJMP? ...
|
|
|
|
+ ... but do not mess with asm block }
|
|
|
|
+ if not(inasmblock) and (taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset<=2048) and
|
|
|
|
+ (taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset>=-2047) and
|
|
|
|
+ { jmps to function go outside the currently considered scope, so do not mess with them.
|
|
|
|
+ Those are generated by the peephole optimizer from call/ret sequences }
|
|
|
|
+ not(taicpu(curtai).oper[0]^.ref^.symbol.typ=AT_FUNCTION) then
|
|
begin
|
|
begin
|
|
- if inasmblock then
|
|
|
|
- Message(asmw_e_brxx_out_of_range)
|
|
|
|
- else
|
|
|
|
|
|
+ taicpu(curtai).opcode:=A_RJMP;
|
|
|
|
+ again:=true;
|
|
|
|
+ end;
|
|
|
|
+ A_STS:
|
|
|
|
+ begin
|
|
|
|
+ if current_settings.cputype=cpu_avr1 then
|
|
begin
|
|
begin
|
|
- current_asmdata.getjumplabel(l);
|
|
|
|
- list.insertafter(tai_label.create(l),curtai);
|
|
|
|
- if CPUAVR_HAS_JMP_CALL in cpu_capabilities[current_settings.cputype] then
|
|
|
|
- list.insertafter(taicpu.op_sym(A_JMP,taicpu(curtai).oper[0]^.ref^.symbol),curtai)
|
|
|
|
- else
|
|
|
|
- list.insertafter(taicpu.op_sym(A_RJMP,taicpu(curtai).oper[0]^.ref^.symbol),curtai);
|
|
|
|
- taicpu(curtai).oper[0]^.ref^.symbol:=l;
|
|
|
|
- taicpu(curtai).condition:=inverse_cond(taicpu(curtai).condition);
|
|
|
|
- again:=true;
|
|
|
|
|
|
+ remove_instruction;
|
|
|
|
+ result:=false;
|
|
|
|
+ end
|
|
|
|
+ else if current_settings.cputype=cpu_avrtiny then
|
|
|
|
+ with taicpu(curtai).oper[0]^ do
|
|
|
|
+ if (ref^.base=NR_NO) and (ref^.index=NR_NO) and (ref^.symbol=nil) and (ref^.offset<$40) then
|
|
|
|
+ begin
|
|
|
|
+ taicpu(curtai).opcode:=A_OUT;
|
|
|
|
+ taicpu(curtai).loadconst(0,ref^.offset);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ A_LDS:
|
|
|
|
+ begin
|
|
|
|
+ if current_settings.cputype=cpu_avr1 then
|
|
|
|
+ begin
|
|
|
|
+ remove_instruction;
|
|
|
|
+ result:=false;
|
|
|
|
+ end
|
|
|
|
+ else if current_settings.cputype=cpu_avrtiny then
|
|
|
|
+ with taicpu(curtai).oper[1]^ do
|
|
|
|
+ if (ref^.base=NR_NO) and (ref^.index=NR_NO) and (ref^.symbol=nil) and (ref^.offset<$40) then
|
|
|
|
+ begin
|
|
|
|
+ taicpu(curtai).opcode:=A_IN;
|
|
|
|
+ taicpu(curtai).loadconst(1,ref^.offset)
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+ A_SBIW,
|
|
|
|
+ A_MULS,
|
|
|
|
+ A_ICALL,
|
|
|
|
+ A_IJMP,
|
|
|
|
+ A_STD,
|
|
|
|
+ A_LD,
|
|
|
|
+ A_LDD,
|
|
|
|
+ A_ST,
|
|
|
|
+ A_ROR,
|
|
|
|
+ A_POP,
|
|
|
|
+ A_PUSH:
|
|
|
|
+ begin
|
|
|
|
+ if current_settings.cputype=cpu_avr1 then
|
|
|
|
+ begin
|
|
|
|
+ remove_instruction;
|
|
|
|
+ result:=false;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
- A_JMP:
|
|
|
|
- { replace JMP by RJMP? ...
|
|
|
|
- ... but do not mess with asm block }
|
|
|
|
- if not(inasmblock) and (taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset<=2048) and
|
|
|
|
- (taicpu(curtai).InsOffset-taicpu(curtai).oper[0]^.ref^.symbol.offset>=-2047) and
|
|
|
|
- { jmps to function go outside the currently considered scope, so do not mess with them.
|
|
|
|
- Those are generated by the peephole optimizer from call/ret sequences }
|
|
|
|
- not(taicpu(curtai).oper[0]^.ref^.symbol.typ=AT_FUNCTION) then
|
|
|
|
- begin
|
|
|
|
- taicpu(curtai).opcode:=A_RJMP;
|
|
|
|
- again:=true;
|
|
|
|
- end;
|
|
|
|
- A_STS:
|
|
|
|
- begin
|
|
|
|
- if (current_settings.cputype=cpu_avrtiny) then
|
|
|
|
- with taicpu(curtai).oper[0]^ do
|
|
|
|
- if (ref^.base=NR_NO) and (ref^.index=NR_NO) and (ref^.symbol=nil) and (ref^.offset<$40) then
|
|
|
|
- begin
|
|
|
|
- taicpu(curtai).opcode:=A_OUT;
|
|
|
|
- taicpu(curtai).loadconst(0,ref^.offset);
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
- A_LDS:
|
|
|
|
- begin
|
|
|
|
- if (current_settings.cputype=cpu_avrtiny) then
|
|
|
|
- with taicpu(curtai).oper[1]^ do
|
|
|
|
- if (ref^.base=NR_NO) and (ref^.index=NR_NO) and (ref^.symbol=nil) and (ref^.offset<$40) then
|
|
|
|
- begin
|
|
|
|
- taicpu(curtai).opcode:=A_IN;
|
|
|
|
- taicpu(curtai).loadconst(1,ref^.offset)
|
|
|
|
- end;
|
|
|
|
- end;
|
|
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
ait_marker:
|
|
ait_marker:
|
|
case tai_marker(curtai).Kind of
|
|
case tai_marker(curtai).Kind of
|