* patch by Christo Crause: do not generate LDD for avrtiny, resolves #38958

git-svn-id: trunk@49473 -
This commit is contained in:
florian 2021-06-03 18:48:40 +00:00
parent 33b29b0df4
commit 9d6ceda532

View File

@ -120,6 +120,7 @@ unit cgcpu;
procedure a_op_reg_reg_internal(list: TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
procedure a_op_const_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg, reghi: TRegister);
procedure maybegetcpuregister(list : tasmlist; reg : tregister);
function addr_is_io_register(const addr: integer): boolean;
end;
tcg64favr = class(tcg64f32)
@ -1084,6 +1085,14 @@ unit cgcpu;
getcpuregister(list,reg);
end;
{ Returns true if dataspace address falls in I/O register range }
function tcgavr.addr_is_io_register(const addr: integer): boolean;
begin
result := (not(current_settings.cputype in [cpu_avrxmega3,cpu_avrtiny]) and (addr>31)) or
((current_settings.cputype in [cpu_avrxmega3,cpu_avrtiny]) and (addr>=0)) and
(addr<cpuinfo.embedded_controllers[current_settings.controllertype].srambase);
end;
function tcgavr.normalize_ref(list:TAsmList;ref: treference;tmpreg : tregister) : treference;
var
@ -1372,8 +1381,7 @@ unit cgcpu;
// Avrxmega3: write low byte first then high byte
// See e.g. megaAVR-0 family data sheet 7.5.6 Accessing 16-bit registers
if (current_settings.cputype <> cpu_avrxmega3) and
(fromsize in [OS_16, OS_S16]) and QuickRef and (href.offset > 31) and
(href.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
(fromsize in [OS_16, OS_S16]) and QuickRef and addr_is_io_register(href.offset) then
begin
tmpreg:=GetNextReg(reg);
href.addressmode:=AM_UNCHANGED;
@ -2601,16 +2609,14 @@ unit cgcpu;
end;
// CC
// If dest is an ioreg (31 < offset < srambase) and size = 16 bit then
// If dest is an ioreg and size = 16 bit then
// write high byte first, then low byte
// but not for avrxmega3
if (len = 2) and DestQuickRef and (current_settings.cputype <> cpu_avrxmega3) and
(dest.offset > 31) and
(dest.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
addr_is_io_register(dest.offset) then
begin
// If src is also a 16 bit ioreg then read low byte then high byte
if SrcQuickRef and (srcref.offset > 31)
and (srcref.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
if SrcQuickRef and addr_is_io_register(srcref.offset) then
begin
// First read source into temp registers
tmpreg:=getintregister(list, OS_16);
@ -2627,8 +2633,20 @@ unit cgcpu;
end
else
begin
srcref.addressmode:=AM_UNCHANGED;
inc(srcref.offset);
{ avrtiny doesn't have LDD instruction, so use
predecrement version of LD with pre-incremented pointer }
if current_settings.cputype = cpu_avrtiny then
begin
srcref.addressmode:=AM_PREDRECEMENT;
list.concat(taicpu.op_reg_const(A_SUBI,srcref.base,-2));
list.concat(taicpu.op_reg_const(A_SBCI,GetNextReg(srcref.base),$FF));
end
else
begin
srcref.addressmode:=AM_UNCHANGED;
inc(srcref.offset);
end;
dstref.addressmode:=AM_UNCHANGED;
inc(dstref.offset);
@ -2637,12 +2655,15 @@ unit cgcpu;
list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
cg.ungetcpuregister(list,GetDefaultTmpReg);
if not(SrcQuickRef) then
if not(SrcQuickRef) and (current_settings.cputype <> cpu_avrtiny) then
srcref.addressmode:=AM_POSTINCREMENT
else if current_settings.cputype = cpu_avrtiny then
srcref.addressmode:=AM_PREDRECEMENT
else
srcref.addressmode:=AM_UNCHANGED;
dec(srcref.offset);
if current_settings.cputype <> cpu_avrtiny then
dec(srcref.offset);
dec(dstref.offset);
cg.getcpuregister(list,GetDefaultTmpReg);