|
@@ -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
|
|
|
|
- (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
|
|
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
|
|
|
|
- (dest.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
|
|
|
|
|
|
+ addr_is_io_register(dest.offset) 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)
|
|
|
|
- and (srcref.offset < cpuinfo.embedded_controllers[current_settings.controllertype].srambase) then
|
|
|
|
|
|
+ if SrcQuickRef and addr_is_io_register(srcref.offset) 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);
|
|
@@ -2627,8 +2633,20 @@ unit cgcpu;
|
|
end
|
|
end
|
|
else
|
|
else
|
|
begin
|
|
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;
|
|
dstref.addressmode:=AM_UNCHANGED;
|
|
inc(dstref.offset);
|
|
inc(dstref.offset);
|
|
|
|
|
|
@@ -2637,12 +2655,15 @@ 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;
|
|
|
|
|
|
- dec(srcref.offset);
|
|
|
|
|
|
+ if current_settings.cputype <> cpu_avrtiny then
|
|
|
|
+ dec(srcref.offset);
|
|
dec(dstref.offset);
|
|
dec(dstref.offset);
|
|
|
|
|
|
cg.getcpuregister(list,GetDefaultTmpReg);
|
|
cg.getcpuregister(list,GetDefaultTmpReg);
|