mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-05 08:29:45 +01:00
Added support for X,Y,and Z register aliases plus low/high forms, and post-incrementation in AVR assembler reader.
Cleaned up parameter and funcretloc information generation in AVR paramanger, and made it closer to GCC's calling convention. Fixed a number of codegenerator bugs generating invalid or broken instructions: CP operands were swapped, a number of instructions had immediate operands, and stack frame epilogue wasn't complete. Added a bunch of peephole optimizations that clears the generated code up a lot. git-svn-id: trunk@26925 -
This commit is contained in:
parent
68f1a51164
commit
e33550b67d
@ -246,12 +246,16 @@ implementation
|
|||||||
begin
|
begin
|
||||||
result:=operand_read;
|
result:=operand_read;
|
||||||
case opcode of
|
case opcode of
|
||||||
|
A_CLR,
|
||||||
|
A_MOV, A_MOVW:
|
||||||
|
if opnr=0 then
|
||||||
|
result:=operand_write;
|
||||||
A_CP,A_CPC,A_CPI,A_PUSH :
|
A_CP,A_CPC,A_CPI,A_PUSH :
|
||||||
;
|
;
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if opnr=0 then
|
if opnr=0 then
|
||||||
result:=operand_write;
|
result:=operand_readwrite;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|||||||
@ -28,10 +28,12 @@ Unit aoptcpu;
|
|||||||
|
|
||||||
Interface
|
Interface
|
||||||
|
|
||||||
uses cpubase, aasmtai, aopt, aoptcpub;
|
uses cpubase, cgbase, aasmtai, aopt, aoptcpub;
|
||||||
|
|
||||||
Type
|
Type
|
||||||
TCpuAsmOptimizer = class(TAsmOptimizer)
|
TCpuAsmOptimizer = class(TAsmOptimizer)
|
||||||
|
Function GetNextInstructionUsingReg(Current: tai; Var Next: tai;reg : TRegister): Boolean;
|
||||||
|
|
||||||
{ uses the same constructor as TAopObj }
|
{ uses the same constructor as TAopObj }
|
||||||
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
||||||
procedure PeepHoleOptPass2;override;
|
procedure PeepHoleOptPass2;override;
|
||||||
@ -40,7 +42,8 @@ Type
|
|||||||
Implementation
|
Implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
aasmbase,aasmcpu,cgbase;
|
aasmbase,aasmcpu,
|
||||||
|
globals,globtype;
|
||||||
|
|
||||||
function CanBeCond(p : tai) : boolean;
|
function CanBeCond(p : tai) : boolean;
|
||||||
begin
|
begin
|
||||||
@ -48,40 +51,254 @@ Implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TCpuAsmOptimizer.GetNextInstructionUsingReg(Current: tai;
|
||||||
|
var Next: tai; reg: TRegister): Boolean;
|
||||||
|
begin
|
||||||
|
Next:=Current;
|
||||||
|
repeat
|
||||||
|
Result:=GetNextInstruction(Next,Next);
|
||||||
|
until not(cs_opt_level3 in current_settings.optimizerswitches) or not(Result) or (Next.typ<>ait_instruction) or (RegInInstruction(reg,Next)) or
|
||||||
|
(is_calljmp(taicpu(Next).opcode));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
|
function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
|
||||||
var
|
var
|
||||||
next1: tai;
|
hp1,hp2,hp3: tai;
|
||||||
|
alloc, dealloc: tai_regalloc;
|
||||||
|
i: integer;
|
||||||
begin
|
begin
|
||||||
result := false;
|
result := false;
|
||||||
case p.typ of
|
case p.typ of
|
||||||
ait_instruction:
|
ait_instruction:
|
||||||
begin
|
begin
|
||||||
case taicpu(p).opcode of
|
case taicpu(p).opcode of
|
||||||
|
A_LDI:
|
||||||
|
begin
|
||||||
|
{ turn
|
||||||
|
ldi reg0, imm
|
||||||
|
cp reg1, reg0
|
||||||
|
dealloc reg0
|
||||||
|
into
|
||||||
|
cpi reg1, imm
|
||||||
|
}
|
||||||
|
if (taicpu(p).ops=2) and
|
||||||
|
(taicpu(p).oper[0]^.typ=top_reg) and
|
||||||
|
(taicpu(p).oper[1]^.typ=top_const) and
|
||||||
|
GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
||||||
|
(not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
|
||||||
|
(taicpu(hp1).opcode=A_CP) and
|
||||||
|
(taicpu(hp1).ops=2) and
|
||||||
|
(taicpu(hp1).oper[1]^.typ=top_reg) and
|
||||||
|
(getsupreg(taicpu(hp1).oper[0]^.reg) in [16..31]) and
|
||||||
|
(taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
|
||||||
|
assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
|
||||||
|
begin
|
||||||
|
taicpu(hp1).opcode:=A_CPI;
|
||||||
|
taicpu(hp1).loadconst(1, taicpu(p).oper[1]^.val);
|
||||||
|
|
||||||
|
alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
|
||||||
|
dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
|
||||||
|
|
||||||
|
if assigned(alloc) and assigned(dealloc) then
|
||||||
|
begin
|
||||||
|
asml.Remove(alloc);
|
||||||
|
alloc.Free;
|
||||||
|
asml.Remove(dealloc);
|
||||||
|
dealloc.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
GetNextInstruction(p,hp1);
|
||||||
|
asml.Remove(p);
|
||||||
|
p.Free;
|
||||||
|
p:=hp1;
|
||||||
|
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
A_CLR:
|
||||||
|
begin
|
||||||
|
{ turn the common
|
||||||
|
clr rX
|
||||||
|
mov/ld rX, rY
|
||||||
|
into
|
||||||
|
mov/ld rX, rY
|
||||||
|
}
|
||||||
|
if (taicpu(p).ops=1) and
|
||||||
|
(taicpu(p).oper[0]^.typ=top_reg) and
|
||||||
|
GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
||||||
|
(not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
|
||||||
|
(hp1.typ=ait_instruction) and
|
||||||
|
(taicpu(hp1).opcode in [A_MOV,A_LD]) and
|
||||||
|
(taicpu(hp1).ops>0) and
|
||||||
|
(taicpu(hp1).oper[0]^.typ=top_reg) and
|
||||||
|
(taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) then
|
||||||
|
begin
|
||||||
|
asml.Remove(p);
|
||||||
|
p.Free;
|
||||||
|
p:=hp1;
|
||||||
|
result:=true;
|
||||||
|
end
|
||||||
|
{ turn
|
||||||
|
clr rX
|
||||||
|
...
|
||||||
|
adc rY, rX
|
||||||
|
into
|
||||||
|
...
|
||||||
|
adc rY, r1
|
||||||
|
}
|
||||||
|
else if (taicpu(p).ops=1) and
|
||||||
|
(taicpu(p).oper[0]^.typ=top_reg) and
|
||||||
|
GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
||||||
|
(not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
|
||||||
|
(hp1.typ=ait_instruction) and
|
||||||
|
(taicpu(hp1).opcode in [A_ADC,A_SBC]) and
|
||||||
|
(taicpu(hp1).ops=2) and
|
||||||
|
(taicpu(hp1).oper[1]^.typ=top_reg) and
|
||||||
|
(taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
|
||||||
|
(taicpu(hp1).oper[0]^.reg<>taicpu(p).oper[0]^.reg) and
|
||||||
|
assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
|
||||||
|
begin
|
||||||
|
taicpu(hp1).oper[1]^.reg:=NR_R1;
|
||||||
|
|
||||||
|
alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
|
||||||
|
dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
|
||||||
|
|
||||||
|
if assigned(alloc) and assigned(dealloc) then
|
||||||
|
begin
|
||||||
|
asml.Remove(alloc);
|
||||||
|
alloc.Free;
|
||||||
|
asml.Remove(dealloc);
|
||||||
|
dealloc.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
GetNextInstruction(p,hp1);
|
||||||
|
asml.Remove(p);
|
||||||
|
p.free;
|
||||||
|
p:=hp1;
|
||||||
|
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
A_PUSH:
|
||||||
|
begin
|
||||||
|
{ turn
|
||||||
|
push reg0
|
||||||
|
push reg1
|
||||||
|
pop reg3
|
||||||
|
pop reg2
|
||||||
|
into
|
||||||
|
movw reg2,reg0
|
||||||
|
}
|
||||||
|
if (taicpu(p).ops=1) and
|
||||||
|
(taicpu(p).oper[0]^.typ=top_reg) and
|
||||||
|
GetNextInstruction(p,hp1) and
|
||||||
|
(hp1.typ=ait_instruction) and
|
||||||
|
(taicpu(hp1).opcode=A_PUSH) and
|
||||||
|
(getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
|
||||||
|
((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
|
||||||
|
|
||||||
|
GetNextInstruction(hp1,hp2) and
|
||||||
|
(hp2.typ=ait_instruction) and
|
||||||
|
(taicpu(hp2).opcode=A_POP) and
|
||||||
|
|
||||||
|
GetNextInstruction(hp2,hp3) and
|
||||||
|
(hp3.typ=ait_instruction) and
|
||||||
|
(taicpu(hp3).opcode=A_POP) and
|
||||||
|
(getsupreg(taicpu(hp2).oper[0]^.reg)=getsupreg(taicpu(hp3).oper[0]^.reg)+1) and
|
||||||
|
((getsupreg(taicpu(hp3).oper[0]^.reg) mod 2)=0) then
|
||||||
|
begin
|
||||||
|
taicpu(p).ops:=2;
|
||||||
|
taicpu(p).opcode:=A_MOVW;
|
||||||
|
|
||||||
|
taicpu(p).loadreg(1, taicpu(p).oper[0]^.reg);
|
||||||
|
taicpu(p).loadreg(0, taicpu(hp3).oper[0]^.reg);
|
||||||
|
|
||||||
|
asml.Remove(hp1);
|
||||||
|
hp1.Free;
|
||||||
|
asml.Remove(hp2);
|
||||||
|
hp2.Free;
|
||||||
|
asml.Remove(hp3);
|
||||||
|
hp3.Free;
|
||||||
|
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
A_MOV:
|
A_MOV:
|
||||||
begin
|
begin
|
||||||
|
{ turn
|
||||||
|
mov reg0, reg1
|
||||||
|
push reg0
|
||||||
|
dealloc reg0
|
||||||
|
into
|
||||||
|
push reg1
|
||||||
|
}
|
||||||
|
if (taicpu(p).ops=2) and
|
||||||
|
(taicpu(p).oper[0]^.typ = top_reg) and
|
||||||
|
(taicpu(p).oper[1]^.typ = top_reg) and
|
||||||
|
GetNextInstructionUsingReg(p,hp1,taicpu(p).oper[0]^.reg) and
|
||||||
|
(not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
|
||||||
|
(hp1.typ = ait_instruction) and
|
||||||
|
(taicpu(hp1).opcode in [A_PUSH,A_MOV,A_CP,A_CPC,A_ADD,A_SUB,A_EOR,A_AND,A_OR]) and
|
||||||
|
RegInInstruction(taicpu(p).oper[0]^.reg, hp1) and
|
||||||
|
(not RegModifiedByInstruction(taicpu(p).oper[0]^.reg, hp1)) and
|
||||||
|
{(taicpu(hp1).ops=1) and
|
||||||
|
(taicpu(hp1).oper[0]^.typ = top_reg) and
|
||||||
|
(taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and }
|
||||||
|
assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
|
||||||
|
begin
|
||||||
|
for i := 0 to taicpu(hp1).ops-1 do
|
||||||
|
if taicpu(hp1).oper[i]^.typ=top_reg then
|
||||||
|
if taicpu(hp1).oper[i]^.reg=taicpu(p).oper[0]^.reg then
|
||||||
|
taicpu(hp1).oper[i]^.reg:=taicpu(p).oper[1]^.reg;
|
||||||
|
|
||||||
|
alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
|
||||||
|
dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
|
||||||
|
|
||||||
|
if assigned(alloc) and assigned(dealloc) then
|
||||||
|
begin
|
||||||
|
asml.Remove(alloc);
|
||||||
|
alloc.Free;
|
||||||
|
asml.Remove(dealloc);
|
||||||
|
dealloc.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
GetNextInstruction(p,hp1);
|
||||||
|
asml.Remove(p);
|
||||||
|
p.free;
|
||||||
|
p:=hp1;
|
||||||
|
result:=true;
|
||||||
|
end
|
||||||
{ fold
|
{ fold
|
||||||
mov reg2,reg0
|
mov reg2,reg0
|
||||||
mov reg3,reg1
|
mov reg3,reg1
|
||||||
to
|
to
|
||||||
movw reg2,reg0
|
movw reg2,reg0
|
||||||
}
|
}
|
||||||
if (taicpu(p).ops=2) and
|
else if (taicpu(p).ops=2) and
|
||||||
(taicpu(p).oper[0]^.typ = top_reg) and
|
(taicpu(p).oper[0]^.typ = top_reg) and
|
||||||
(taicpu(p).oper[1]^.typ = top_reg) and
|
(taicpu(p).oper[1]^.typ = top_reg) and
|
||||||
getnextinstruction(p,next1) and
|
getnextinstruction(p,hp1) and
|
||||||
(next1.typ = ait_instruction) and
|
(hp1.typ = ait_instruction) and
|
||||||
(taicpu(next1).opcode = A_MOV) and
|
(taicpu(hp1).opcode = A_MOV) and
|
||||||
(taicpu(next1).ops=2) and
|
(taicpu(hp1).ops=2) and
|
||||||
(taicpu(next1).oper[0]^.typ = top_reg) and
|
(taicpu(hp1).oper[0]^.typ = top_reg) and
|
||||||
(taicpu(next1).oper[1]^.typ = top_reg) and
|
(taicpu(hp1).oper[1]^.typ = top_reg) and
|
||||||
(getsupreg(taicpu(next1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
|
(getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(p).oper[0]^.reg)+1) and
|
||||||
((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
|
((getsupreg(taicpu(p).oper[0]^.reg) mod 2)=0) and
|
||||||
((getsupreg(taicpu(p).oper[1]^.reg) mod 2)=0) and
|
((getsupreg(taicpu(p).oper[1]^.reg) mod 2)=0) and
|
||||||
(getsupreg(taicpu(next1).oper[1]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)+1) then
|
(getsupreg(taicpu(hp1).oper[1]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)+1) then
|
||||||
begin
|
begin
|
||||||
|
alloc:=FindRegAllocBackward(taicpu(hp1).oper[0]^.reg,tai(hp1.Previous));
|
||||||
|
if assigned(alloc) then
|
||||||
|
begin
|
||||||
|
asml.Remove(alloc);
|
||||||
|
asml.InsertBefore(alloc,p);
|
||||||
|
end;
|
||||||
|
|
||||||
taicpu(p).opcode:=A_MOVW;
|
taicpu(p).opcode:=A_MOVW;
|
||||||
asml.remove(next1);
|
asml.remove(hp1);
|
||||||
next1.free;
|
hp1.free;
|
||||||
result := true;
|
result := true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|||||||
@ -36,7 +36,10 @@ Unit aoptcpub; { Assembler OPTimizer CPU specific Base }
|
|||||||
Interface
|
Interface
|
||||||
|
|
||||||
Uses
|
Uses
|
||||||
cpubase,aasmcpu,AOptBase;
|
cpubase,
|
||||||
|
cgbase,
|
||||||
|
aasmcpu,aasmtai,
|
||||||
|
AOptBase;
|
||||||
|
|
||||||
Type
|
Type
|
||||||
|
|
||||||
@ -58,6 +61,7 @@ Type
|
|||||||
{ ************************************************************************* }
|
{ ************************************************************************* }
|
||||||
|
|
||||||
TAoptBaseCpu = class(TAoptBase)
|
TAoptBaseCpu = class(TAoptBase)
|
||||||
|
function RegModifiedByInstruction(Reg: TRegister; p1: tai): boolean; override;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
|
||||||
@ -103,12 +107,26 @@ Implementation
|
|||||||
{ ************************************************************************* }
|
{ ************************************************************************* }
|
||||||
{ **************************** TCondRegs ********************************** }
|
{ **************************** TCondRegs ********************************** }
|
||||||
{ ************************************************************************* }
|
{ ************************************************************************* }
|
||||||
Constructor TCondRegs.init;
|
Constructor TCondRegs.init;
|
||||||
Begin
|
Begin
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
|
Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
|
||||||
Begin
|
Begin
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
|
||||||
|
function TAoptBaseCpu.RegModifiedByInstruction(Reg: TRegister; p1: tai): boolean;
|
||||||
|
var
|
||||||
|
i : Longint;
|
||||||
|
begin
|
||||||
|
result:=false;
|
||||||
|
for i:=0 to taicpu(p1).ops-1 do
|
||||||
|
if (taicpu(p1).oper[i]^.typ=top_reg) and (taicpu(p1).oper[i]^.reg=Reg) and (taicpu(p1).spilling_get_operation_type(i) in [operand_write,operand_readwrite]) then
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
End.
|
End.
|
||||||
|
|||||||
@ -559,7 +559,7 @@ unit cgcpu;
|
|||||||
current_asmdata.getjumplabel(l2);
|
current_asmdata.getjumplabel(l2);
|
||||||
countreg:=getintregister(list,OS_8);
|
countreg:=getintregister(list,OS_8);
|
||||||
a_load_reg_reg(list,size,OS_8,src,countreg);
|
a_load_reg_reg(list,size,OS_8,src,countreg);
|
||||||
list.concat(taicpu.op_reg_const(A_CP,countreg,0));
|
list.concat(taicpu.op_reg_const(A_CPI,countreg,0));
|
||||||
a_jmp_flags(list,F_EQ,l2);
|
a_jmp_flags(list,F_EQ,l2);
|
||||||
cg.a_label(list,l1);
|
cg.a_label(list,l1);
|
||||||
case op of
|
case op of
|
||||||
@ -677,7 +677,7 @@ unit cgcpu;
|
|||||||
end;
|
end;
|
||||||
OP_SUB:
|
OP_SUB:
|
||||||
begin
|
begin
|
||||||
list.concat(taicpu.op_reg_const(A_SUBI,reg,a));
|
list.concat(taicpu.op_reg_const(A_SUBI,reg,a and mask));
|
||||||
if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
|
if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
|
||||||
begin
|
begin
|
||||||
for i:=2 to tcgsize2size[size] do
|
for i:=2 to tcgsize2size[size] do
|
||||||
@ -689,6 +689,20 @@ unit cgcpu;
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
{OP_ADD:
|
||||||
|
begin
|
||||||
|
list.concat(taicpu.op_reg_const(A_SUBI,reg,(-a) and mask));
|
||||||
|
if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
|
||||||
|
begin
|
||||||
|
for i:=2 to tcgsize2size[size] do
|
||||||
|
begin
|
||||||
|
NextReg;
|
||||||
|
mask:=mask shl 8;
|
||||||
|
inc(shift,8);
|
||||||
|
list.concat(taicpu.op_reg_const(A_ADC,reg,(a and mask) shr shift));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end; }
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if size in [OS_64,OS_S64] then
|
if size in [OS_64,OS_S64] then
|
||||||
@ -787,11 +801,11 @@ unit cgcpu;
|
|||||||
else if (ref.base<>NR_NO) and (ref.index<>NR_NO) then
|
else if (ref.base<>NR_NO) and (ref.index<>NR_NO) then
|
||||||
begin
|
begin
|
||||||
maybegetcpuregister(list,tmpreg);
|
maybegetcpuregister(list,tmpreg);
|
||||||
emit_mov(list,tmpreg,ref.index);
|
emit_mov(list,tmpreg,ref.base);
|
||||||
maybegetcpuregister(list,GetNextReg(tmpreg));
|
maybegetcpuregister(list,GetNextReg(tmpreg));
|
||||||
emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.index));
|
emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.base));
|
||||||
list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.base));
|
list.concat(taicpu.op_reg_reg(A_ADD,tmpreg,ref.index));
|
||||||
list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.base)));
|
list.concat(taicpu.op_reg_reg(A_ADC,GetNextReg(tmpreg),GetNextReg(ref.index)));
|
||||||
ref.base:=tmpreg;
|
ref.base:=tmpreg;
|
||||||
ref.index:=NR_NO;
|
ref.index:=NR_NO;
|
||||||
end
|
end
|
||||||
@ -1329,13 +1343,13 @@ unit cgcpu;
|
|||||||
reg1:=reg2;
|
reg1:=reg2;
|
||||||
reg2:=tmpreg;
|
reg2:=tmpreg;
|
||||||
end;
|
end;
|
||||||
list.concat(taicpu.op_reg_reg(A_CP,reg1,reg2));
|
list.concat(taicpu.op_reg_reg(A_CP,reg2,reg1));
|
||||||
|
|
||||||
for i:=2 to tcgsize2size[size] do
|
for i:=2 to tcgsize2size[size] do
|
||||||
begin
|
begin
|
||||||
reg1:=GetNextReg(reg1);
|
reg1:=GetNextReg(reg1);
|
||||||
reg2:=GetNextReg(reg2);
|
reg2:=GetNextReg(reg2);
|
||||||
list.concat(taicpu.op_reg_reg(A_CPC,reg1,reg2));
|
list.concat(taicpu.op_reg_reg(A_CPC,reg2,reg1));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
a_jmp_cond(list,cmp_op,l);
|
a_jmp_cond(list,cmp_op,l);
|
||||||
@ -1513,6 +1527,8 @@ unit cgcpu;
|
|||||||
LocalSize:=current_procinfo.calc_stackframe_size;
|
LocalSize:=current_procinfo.calc_stackframe_size;
|
||||||
a_adjust_sp(list,LocalSize);
|
a_adjust_sp(list,LocalSize);
|
||||||
regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
|
regs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
|
||||||
|
if current_procinfo.framepointer<>NR_STACK_POINTER_REG then
|
||||||
|
regs:=regs+[RS_R28,RS_R29];
|
||||||
|
|
||||||
for reg:=RS_R0 to RS_R31 do
|
for reg:=RS_R0 to RS_R31 do
|
||||||
if reg in regs then
|
if reg in regs then
|
||||||
|
|||||||
@ -235,11 +235,11 @@ unit cpubase;
|
|||||||
}
|
}
|
||||||
NR_PIC_OFFSET_REG = NR_R9;
|
NR_PIC_OFFSET_REG = NR_R9;
|
||||||
{ Results are returned in this register (32-bit values) }
|
{ Results are returned in this register (32-bit values) }
|
||||||
NR_FUNCTION_RETURN_REG = NR_R0;
|
NR_FUNCTION_RETURN_REG = NR_R24;
|
||||||
RS_FUNCTION_RETURN_REG = RS_R0;
|
RS_FUNCTION_RETURN_REG = RS_R24;
|
||||||
{ Low part of 64bit return value }
|
{ Low part of 64bit return value }
|
||||||
NR_FUNCTION_RETURN64_LOW_REG = NR_R0;
|
NR_FUNCTION_RETURN64_LOW_REG = NR_R22;
|
||||||
RS_FUNCTION_RETURN64_LOW_REG = RS_R0;
|
RS_FUNCTION_RETURN64_LOW_REG = RS_R22;
|
||||||
{ High part of 64bit return value }
|
{ High part of 64bit return value }
|
||||||
NR_FUNCTION_RETURN64_HIGH_REG = NR_R1;
|
NR_FUNCTION_RETURN64_HIGH_REG = NR_R1;
|
||||||
RS_FUNCTION_RETURN64_HIGH_REG = RS_R1;
|
RS_FUNCTION_RETURN64_HIGH_REG = RS_R1;
|
||||||
@ -323,6 +323,8 @@ unit cpubase;
|
|||||||
{ returns the register with the offset of ofs of a continuous set of register starting with r and being continued with rhi }
|
{ returns the register with the offset of ofs of a continuous set of register starting with r and being continued with rhi }
|
||||||
function GetOffsetReg64(const r,rhi: TRegister;ofs : shortint): TRegister;
|
function GetOffsetReg64(const r,rhi: TRegister;ofs : shortint): TRegister;
|
||||||
|
|
||||||
|
function is_calljmp(o:tasmop):boolean;{$ifdef USEINLINE}inline;{$endif USEINLINE}
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
@ -476,4 +478,10 @@ unit cpubase;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function is_calljmp(o:tasmop):boolean;{$ifdef USEINLINE}inline;{$endif USEINLINE}
|
||||||
|
begin
|
||||||
|
is_calljmp:= o in jmp_instructions;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|||||||
@ -162,7 +162,10 @@ unit cpupara;
|
|||||||
result:=not(def.size in [1,2,4]);
|
result:=not(def.size in [1,2,4]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result:=inherited ret_in_param(def,pd);
|
if (def.size > 4) then
|
||||||
|
result:=true
|
||||||
|
else
|
||||||
|
result:=inherited ret_in_param(def,pd);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -441,7 +444,57 @@ unit cpupara;
|
|||||||
{ Return in register }
|
{ Return in register }
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if retcgsize in [OS_64,OS_S64] then
|
case retcgsize of
|
||||||
|
OS_32,OS_S32:
|
||||||
|
begin
|
||||||
|
paraloc^.loc:=LOC_REGISTER;
|
||||||
|
paraloc^.register:=NR_R22;
|
||||||
|
paraloc^.size:=OS_8;
|
||||||
|
paraloc^.def:=u8inttype;
|
||||||
|
|
||||||
|
paraloc:=result.add_location;
|
||||||
|
paraloc^.loc:=LOC_REGISTER;
|
||||||
|
paraloc^.register:=NR_R23;
|
||||||
|
paraloc^.size:=OS_8;
|
||||||
|
paraloc^.def:=u8inttype;
|
||||||
|
|
||||||
|
paraloc:=result.add_location;
|
||||||
|
paraloc^.loc:=LOC_REGISTER;
|
||||||
|
paraloc^.register:=NR_R24;
|
||||||
|
paraloc^.size:=OS_8;
|
||||||
|
paraloc^.def:=u8inttype;
|
||||||
|
|
||||||
|
paraloc:=result.add_location;
|
||||||
|
paraloc^.loc:=LOC_REGISTER;
|
||||||
|
paraloc^.register:=NR_R25;
|
||||||
|
paraloc^.size:=OS_8;
|
||||||
|
paraloc^.def:=u8inttype;
|
||||||
|
end;
|
||||||
|
OS_16,OS_S16:
|
||||||
|
begin
|
||||||
|
paraloc^.loc:=LOC_REGISTER;
|
||||||
|
paraloc^.register:=NR_R24;
|
||||||
|
paraloc^.size:=OS_8;
|
||||||
|
paraloc^.def:=u8inttype;
|
||||||
|
|
||||||
|
paraloc:=result.add_location;
|
||||||
|
paraloc^.loc:=LOC_REGISTER;
|
||||||
|
paraloc^.register:=NR_R25;
|
||||||
|
paraloc^.size:=OS_8;
|
||||||
|
paraloc^.def:=u8inttype;
|
||||||
|
end;
|
||||||
|
OS_8,OS_S8:
|
||||||
|
begin
|
||||||
|
paraloc^.loc:=LOC_REGISTER;
|
||||||
|
paraloc^.register:=NR_R24;
|
||||||
|
paraloc^.size:=OS_8;
|
||||||
|
paraloc^.def:=u8inttype;
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
internalerror(2014030101);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{if retcgsize in [OS_64,OS_S64] then
|
||||||
begin
|
begin
|
||||||
paraloc^.loc:=LOC_REGISTER;
|
paraloc^.loc:=LOC_REGISTER;
|
||||||
paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
|
paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
|
||||||
@ -457,9 +510,9 @@ unit cpupara;
|
|||||||
begin
|
begin
|
||||||
paraloc^.loc:=LOC_REGISTER;
|
paraloc^.loc:=LOC_REGISTER;
|
||||||
paraloc^.register:=NR_FUNCTION_RETURN_REG;
|
paraloc^.register:=NR_FUNCTION_RETURN_REG;
|
||||||
paraloc^.size:=OS_32;
|
paraloc^.size:=OS_INT;
|
||||||
paraloc^.def:=u32inttype;
|
paraloc^.def:=u16inttype;
|
||||||
end;
|
end;}
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
@ -69,14 +69,20 @@ Unit raavrgas;
|
|||||||
name : string[2];
|
name : string[2];
|
||||||
reg : tregister;
|
reg : tregister;
|
||||||
end;
|
end;
|
||||||
{
|
|
||||||
const
|
const
|
||||||
extraregs : array[0..19] of treg2str = (
|
extraregs : array[0..8] of treg2str = (
|
||||||
(name: 'X'; reg : NR_Z),
|
(name: 'X'; reg : NR_R26),
|
||||||
(name: 'Y'; reg : NR_R1),
|
(name: 'XL'; reg : NR_R26),
|
||||||
(name: 'Z'; reg : NR_R2),
|
(name: 'XH'; reg : NR_R27),
|
||||||
|
(name: 'Y'; reg : NR_R28),
|
||||||
|
(name: 'YL'; reg : NR_R28),
|
||||||
|
(name: 'YH'; reg : NR_R29),
|
||||||
|
(name: 'Z'; reg : NR_R30),
|
||||||
|
(name: 'ZL'; reg : NR_R30),
|
||||||
|
(name: 'ZH'; reg : NR_R31)
|
||||||
);
|
);
|
||||||
}
|
|
||||||
var
|
var
|
||||||
i : longint;
|
i : longint;
|
||||||
|
|
||||||
@ -85,9 +91,9 @@ Unit raavrgas;
|
|||||||
{ reg found?
|
{ reg found?
|
||||||
possible aliases are always 2 char
|
possible aliases are always 2 char
|
||||||
}
|
}
|
||||||
if result or (length(s)<>2) then
|
if result or (not (length(s) in [1,2])) then
|
||||||
exit;
|
exit;
|
||||||
{
|
|
||||||
for i:=low(extraregs) to high(extraregs) do
|
for i:=low(extraregs) to high(extraregs) do
|
||||||
begin
|
begin
|
||||||
if s=extraregs[i].name then
|
if s=extraregs[i].name then
|
||||||
@ -98,7 +104,6 @@ Unit raavrgas;
|
|||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
}
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -480,7 +485,16 @@ Unit raavrgas;
|
|||||||
{ save the type of register used. }
|
{ save the type of register used. }
|
||||||
tempreg:=actasmregister;
|
tempreg:=actasmregister;
|
||||||
Consume(AS_REGISTER);
|
Consume(AS_REGISTER);
|
||||||
if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
|
if (actasmtoken=AS_PLUS) then
|
||||||
|
begin
|
||||||
|
oper.opr.typ:=OPR_REFERENCE;
|
||||||
|
|
||||||
|
reference_reset_base(oper.opr.ref,tempreg,0,1);
|
||||||
|
oper.opr.ref.addressmode:=AM_POSTINCREMENT;
|
||||||
|
|
||||||
|
consume(AS_PLUS);
|
||||||
|
end
|
||||||
|
else if (actasmtoken in [AS_END,AS_SEPARATOR,AS_COMMA]) then
|
||||||
Begin
|
Begin
|
||||||
if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
|
if not (oper.opr.typ in [OPR_NONE,OPR_REGISTER]) then
|
||||||
Message(asmr_e_invalid_operand_type);
|
Message(asmr_e_invalid_operand_type);
|
||||||
|
|||||||
@ -635,8 +635,7 @@ begin
|
|||||||
Add(' /* Internal text space or external memory. */');
|
Add(' /* Internal text space or external memory. */');
|
||||||
Add(' .text :');
|
Add(' .text :');
|
||||||
Add(' {');
|
Add(' {');
|
||||||
Add(' *(.vectors)');
|
Add(' KEEP(*(.init, .init.*))');
|
||||||
Add(' KEEP(*(.vectors))');
|
|
||||||
Add(' /* For data that needs to reside in the lower 64k of progmem. */');
|
Add(' /* For data that needs to reside in the lower 64k of progmem. */');
|
||||||
Add(' *(.progmem.gcc*)');
|
Add(' *(.progmem.gcc*)');
|
||||||
Add(' *(.progmem*)');
|
Add(' *(.progmem*)');
|
||||||
@ -862,6 +861,10 @@ begin
|
|||||||
success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O ihex '+
|
success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O ihex '+
|
||||||
ChangeFileExt(current_module.exefilename,'.elf')+' '+
|
ChangeFileExt(current_module.exefilename,'.elf')+' '+
|
||||||
ChangeFileExt(current_module.exefilename,'.hex'),true,false);
|
ChangeFileExt(current_module.exefilename,'.hex'),true,false);
|
||||||
|
if success then
|
||||||
|
success:=DoExec(FindUtil(utilsprefix+'objcopy'),'-O binary '+
|
||||||
|
ChangeFileExt(current_module.exefilename,'.elf')+' '+
|
||||||
|
ChangeFileExt(current_module.exefilename,'.bin'),true,false);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
MakeExecutable:=success; { otherwise a recursive call to link method }
|
MakeExecutable:=success; { otherwise a recursive call to link method }
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user