* patch (slighly modified) by Christo Crause to write 16 bit registers on avr in hi/lo order, resolves #34721

git-svn-id: trunk@40678 -
This commit is contained in:
florian 2018-12-27 21:41:36 +00:00
parent a7c347fe56
commit 917de001d6

View File

@ -1345,21 +1345,38 @@ unit cgcpu;
end;
if not conv_done then
begin
for i:=1 to tcgsize2size[fromsize] do
// CC
// Write to 16 bit ioreg, first high byte then low byte
// sequence required for 16 bit timer registers
// See e.g. atmega328p manual para 15.3 Accessing 16 bit registers
if (fromsize in [OS_16, OS_S16]) and QuickRef and (href.offset > 31)
and (href.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
begin
if not(QuickRef) and (i<tcgsize2size[fromsize]) then
href.addressmode:=AM_POSTINCREMENT
else
href.addressmode:=AM_UNCHANGED;
tmpreg:=GetNextReg(reg);
href.addressmode:=AM_UNCHANGED;
inc(href.offset);
list.concat(taicpu.op_ref_reg(GetStore(href),href,tmpreg));
dec(href.offset);
list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
end
else
begin
for i:=1 to tcgsize2size[fromsize] do
begin
if not(QuickRef) and (i<tcgsize2size[fromsize]) then
href.addressmode:=AM_POSTINCREMENT
else
href.addressmode:=AM_UNCHANGED;
if QuickRef then
inc(href.offset);
list.concat(taicpu.op_ref_reg(GetStore(href),href,reg));
{ check if we are not in the last iteration to avoid an internalerror in GetNextReg }
if i<tcgsize2size[fromsize] then
reg:=GetNextReg(reg);
if QuickRef then
inc(href.offset);
{ check if we are not in the last iteration to avoid an internalerror in GetNextReg }
if i<tcgsize2size[fromsize] then
reg:=GetNextReg(reg);
end;
end;
end;
@ -2124,7 +2141,7 @@ unit cgcpu;
procedure tcgavr.g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);
var
countreg,tmpreg : tregister;
countreg,tmpreg,tmpreg2: tregister;
srcref,dstref : treference;
copysize,countregsize : tcgsize;
l : TAsmLabel;
@ -2269,40 +2286,91 @@ unit cgcpu;
dstref:=dest;
end;
for i:=1 to len do
begin
if not(SrcQuickRef) and (i<len) then
srcref.addressmode:=AM_POSTINCREMENT
else
srcref.addressmode:=AM_UNCHANGED;
// CC
// If dest is an ioreg (31 < offset < srambase) and size = 16 bit then
// load high byte first, then low byte
if (len = 2) and DestQuickRef
and (dest.offset > 31)
and (dest.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) 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
begin
// First read source into temp registers
tmpreg:=getintregister(list, OS_16);
list.concat(taicpu.op_reg_ref(GetLoad(srcref),tmpreg,srcref));
inc(srcref.offset);
tmpreg2:=GetNextReg(tmpreg);
list.concat(taicpu.op_reg_ref(GetLoad(srcref),tmpreg2,srcref));
if not(DestQuickRef) and (i<len) then
dstref.addressmode:=AM_POSTINCREMENT
else
dstref.addressmode:=AM_UNCHANGED;
// then move temp registers to dest in reverse order
inc(dstref.offset);
list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,tmpreg2));
dec(dstref.offset);
list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,tmpreg));
end
else
begin
srcref.addressmode:=AM_UNCHANGED;
inc(srcref.offset);
dstref.addressmode:=AM_UNCHANGED;
inc(dstref.offset);
cg.getcpuregister(list,NR_R0);
list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
cg.ungetcpuregister(list,NR_R0);
cg.getcpuregister(list,NR_R0);
list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
cg.ungetcpuregister(list,NR_R0);
if SrcQuickRef then
inc(srcref.offset);
if DestQuickRef then
inc(dstref.offset);
end;
if not(SrcQuickRef) then
begin
ungetcpuregister(list,srcref.base);
ungetcpuregister(list,TRegister(ord(srcref.base)+1));
end;
if not(DestQuickRef) then
begin
ungetcpuregister(list,dstref.base);
ungetcpuregister(list,TRegister(ord(dstref.base)+1));
end;
end;
end;
if not(SrcQuickRef) then
srcref.addressmode:=AM_POSTINCREMENT
else
srcref.addressmode:=AM_UNCHANGED;
dec(srcref.offset);
dec(dstref.offset);
cg.getcpuregister(list,NR_R0);
list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
cg.ungetcpuregister(list,NR_R0);
end;
end
else
for i:=1 to len do
begin
if not(SrcQuickRef) and (i<len) then
srcref.addressmode:=AM_POSTINCREMENT
else
srcref.addressmode:=AM_UNCHANGED;
if not(DestQuickRef) and (i<len) then
dstref.addressmode:=AM_POSTINCREMENT
else
dstref.addressmode:=AM_UNCHANGED;
cg.getcpuregister(list,NR_R0);
list.concat(taicpu.op_reg_ref(GetLoad(srcref),NR_R0,srcref));
list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,NR_R0));
cg.ungetcpuregister(list,NR_R0);
if SrcQuickRef then
inc(srcref.offset);
if DestQuickRef then
inc(dstref.offset);
end;
if not(SrcQuickRef) then
begin
ungetcpuregister(list,srcref.base);
ungetcpuregister(list,TRegister(ord(srcref.base)+1));
end;
if not(DestQuickRef) then
begin
ungetcpuregister(list,dstref.base);
ungetcpuregister(list,TRegister(ord(dstref.base)+1));
end;
end;
end;
procedure tcgavr.g_overflowCheck(list : TAsmList;const l : tlocation;def : tdef);