* 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_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 a_op_const_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg, reghi: TRegister);
procedure maybegetcpuregister(list : tasmlist; reg : tregister); procedure maybegetcpuregister(list : tasmlist; reg : tregister);
function addr_is_io_register(const addr: integer): boolean;
end; end;
tcg64favr = class(tcg64f32) tcg64favr = class(tcg64f32)
@ -1084,6 +1085,14 @@ unit cgcpu;
getcpuregister(list,reg); getcpuregister(list,reg);
end; 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; function tcgavr.normalize_ref(list:TAsmList;ref: treference;tmpreg : tregister) : treference;
var var
@ -1372,8 +1381,7 @@ unit cgcpu;
// Avrxmega3: write low byte first then high byte // Avrxmega3: write low byte first then high byte
// See e.g. megaAVR-0 family data sheet 7.5.6 Accessing 16-bit registers // See e.g. megaAVR-0 family data sheet 7.5.6 Accessing 16-bit registers
if (current_settings.cputype <> cpu_avrxmega3) and if (current_settings.cputype <> cpu_avrxmega3) and
(fromsize in [OS_16, OS_S16]) and QuickRef and (href.offset > 31) and (fromsize in [OS_16, OS_S16]) and QuickRef and addr_is_io_register(href.offset) then
(href.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
begin begin
tmpreg:=GetNextReg(reg); tmpreg:=GetNextReg(reg);
href.addressmode:=AM_UNCHANGED; href.addressmode:=AM_UNCHANGED;
@ -2601,16 +2609,14 @@ unit cgcpu;
end; end;
// CC // 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 // write high byte first, then low byte
// but not for avrxmega3 // but not for avrxmega3
if (len = 2) and DestQuickRef and (current_settings.cputype <> cpu_avrxmega3) and if (len = 2) and DestQuickRef and (current_settings.cputype <> cpu_avrxmega3) and
(dest.offset > 31) and addr_is_io_register(dest.offset) then
(dest.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
begin begin
// If src is also a 16 bit ioreg then read low byte then high byte // If src is also a 16 bit ioreg then read low byte then high byte
if SrcQuickRef and (srcref.offset > 31) if SrcQuickRef and addr_is_io_register(srcref.offset) then
and (srcref.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
begin begin
// First read source into temp registers // First read source into temp registers
tmpreg:=getintregister(list, OS_16); tmpreg:=getintregister(list, OS_16);
@ -2625,10 +2631,22 @@ unit cgcpu;
dec(dstref.offset); dec(dstref.offset);
list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,tmpreg)); list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,tmpreg));
end end
else
begin
{ 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 else
begin begin
srcref.addressmode:=AM_UNCHANGED; srcref.addressmode:=AM_UNCHANGED;
inc(srcref.offset); inc(srcref.offset);
end;
dstref.addressmode:=AM_UNCHANGED; dstref.addressmode:=AM_UNCHANGED;
inc(dstref.offset); inc(dstref.offset);
@ -2637,11 +2655,14 @@ unit cgcpu;
list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg)); list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
cg.ungetcpuregister(list,GetDefaultTmpReg); cg.ungetcpuregister(list,GetDefaultTmpReg);
if not(SrcQuickRef) then if not(SrcQuickRef) and (current_settings.cputype <> cpu_avrtiny) then
srcref.addressmode:=AM_POSTINCREMENT srcref.addressmode:=AM_POSTINCREMENT
else if current_settings.cputype = cpu_avrtiny then
srcref.addressmode:=AM_PREDRECEMENT
else else
srcref.addressmode:=AM_UNCHANGED; srcref.addressmode:=AM_UNCHANGED;
if current_settings.cputype <> cpu_avrtiny then
dec(srcref.offset); dec(srcref.offset);
dec(dstref.offset); dec(dstref.offset);