|
@@ -114,6 +114,8 @@ unit cgcpu;
|
|
|
|
|
|
procedure gen_multiply(list: TAsmList; op: topcg; size: TCgSize; src2, src1, dst: tregister; check_overflow: boolean; var ovloc: tlocation);
|
|
|
|
|
|
+ private
|
|
|
+ procedure a_op_const_reg_reg_internal(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, srchi, dst, dsthi: tregister);
|
|
|
protected
|
|
|
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);
|
|
@@ -123,6 +125,7 @@ unit cgcpu;
|
|
|
tcg64favr = class(tcg64f32)
|
|
|
procedure a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);override;
|
|
|
procedure a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);override;
|
|
|
+ procedure a_op64_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; value: int64;src,dst: tregister64);override;
|
|
|
end;
|
|
|
|
|
|
procedure create_codegen;
|
|
@@ -145,10 +148,14 @@ unit cgcpu;
|
|
|
procedure tcgavr.init_register_allocators;
|
|
|
begin
|
|
|
inherited init_register_allocators;
|
|
|
- rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
|
|
|
- [RS_R18,RS_R19,RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25,
|
|
|
- RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
|
|
|
- RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17],first_int_imreg,[]);
|
|
|
+ if CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype] then
|
|
|
+ rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
|
|
|
+ [RS_R18,RS_R19,RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25],first_int_imreg,[])
|
|
|
+ else
|
|
|
+ rg[R_INTREGISTER]:=trgintcpu.create(R_INTREGISTER,R_SUBWHOLE,
|
|
|
+ [RS_R18,RS_R19,RS_R20,RS_R21,RS_R22,RS_R23,RS_R24,RS_R25,
|
|
|
+ RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
|
|
|
+ RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17],first_int_imreg,[]);
|
|
|
end;
|
|
|
|
|
|
|
|
@@ -199,8 +206,12 @@ unit cgcpu;
|
|
|
a_load_reg_reg(list,paraloc^.size,paraloc^.size,r,paraloc^.register);
|
|
|
LOC_REFERENCE,LOC_CREFERENCE:
|
|
|
begin
|
|
|
- reference_reset_base(ref,paraloc^.reference.index,paraloc^.reference.offset,ctempposinvalid,2,[]);
|
|
|
- a_load_reg_ref(list,paraloc^.size,paraloc^.size,r,ref);
|
|
|
+ reference_reset_base(ref,paraloc^.reference.index,paraloc^.reference.offset,ctempposinvalid,2,[]);
|
|
|
+ if ref.base<>NR_STACK_POINTER_REG then
|
|
|
+ Internalerror(2020011801);
|
|
|
+
|
|
|
+ { as AVR allows no stack indirect addressing, everything else than a push makes no sense }
|
|
|
+ list.concat(taicpu.op_reg(A_PUSH,r));
|
|
|
end;
|
|
|
else
|
|
|
internalerror(2002071004);
|
|
@@ -212,91 +223,49 @@ unit cgcpu;
|
|
|
hp : PCGParaLocation;
|
|
|
|
|
|
begin
|
|
|
-{ if use_push(cgpara) then
|
|
|
- begin
|
|
|
- if tcgsize2size[cgpara.Size] > 2 then
|
|
|
- begin
|
|
|
- if tcgsize2size[cgpara.Size] <> 4 then
|
|
|
- internalerror(2013031101);
|
|
|
- if cgpara.location^.Next = nil then
|
|
|
- begin
|
|
|
- if tcgsize2size[cgpara.location^.size] <> 4 then
|
|
|
- internalerror(2013031101);
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- if tcgsize2size[cgpara.location^.size] <> 2 then
|
|
|
- internalerror(2013031101);
|
|
|
- if tcgsize2size[cgpara.location^.Next^.size] <> 2 then
|
|
|
- internalerror(2013031101);
|
|
|
- if cgpara.location^.Next^.Next <> nil then
|
|
|
- internalerror(2013031101);
|
|
|
- end;
|
|
|
+ if not(tcgsize2size[cgpara.Size] in [1..4]) then
|
|
|
+ internalerror(2014011101);
|
|
|
|
|
|
- if tcgsize2size[cgpara.size]>cgpara.alignment then
|
|
|
- pushsize:=cgpara.size
|
|
|
- else
|
|
|
- pushsize:=int_cgsize(cgpara.alignment);
|
|
|
- pushsize2 := int_cgsize(tcgsize2size[pushsize] - 2);
|
|
|
- list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize2],makeregsize(list,GetNextReg(r),pushsize2)));
|
|
|
- list.concat(taicpu.op_reg(A_PUSH,S_W,makeregsize(list,r,OS_16)));
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- cgpara.check_simple_location;
|
|
|
- if tcgsize2size[cgpara.location^.size]>cgpara.alignment then
|
|
|
- pushsize:=cgpara.location^.size
|
|
|
- else
|
|
|
- pushsize:=int_cgsize(cgpara.alignment);
|
|
|
- list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],makeregsize(list,r,pushsize)));
|
|
|
- end;
|
|
|
+ hp:=cgpara.location;
|
|
|
|
|
|
- end
|
|
|
- else }
|
|
|
+ i:=0;
|
|
|
+ while i<tcgsize2size[cgpara.Size] do
|
|
|
begin
|
|
|
- if not(tcgsize2size[cgpara.Size] in [1..4]) then
|
|
|
- internalerror(2014011101);
|
|
|
+ if not(assigned(hp)) then
|
|
|
+ internalerror(2014011102);
|
|
|
|
|
|
- hp:=cgpara.location;
|
|
|
+ inc(i, tcgsize2size[hp^.Size]);
|
|
|
|
|
|
- i:=0;
|
|
|
- while i<tcgsize2size[cgpara.Size] do
|
|
|
+ if hp^.Loc=LOC_REGISTER then
|
|
|
begin
|
|
|
- if not(assigned(hp)) then
|
|
|
- internalerror(2014011102);
|
|
|
-
|
|
|
- inc(i, tcgsize2size[hp^.Size]);
|
|
|
-
|
|
|
- if hp^.Loc=LOC_REGISTER then
|
|
|
- begin
|
|
|
- load_para_loc(r,hp);
|
|
|
- hp:=hp^.Next;
|
|
|
- { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
|
|
|
- if i<tcgsize2size[cgpara.Size] then
|
|
|
- r:=GetNextReg(r);
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- load_para_loc(r,hp);
|
|
|
+ load_para_loc(r,hp);
|
|
|
+ hp:=hp^.Next;
|
|
|
+ { check if we are not in the last iteration to avoid an internalerror in GetNextReg }
|
|
|
+ if i<tcgsize2size[cgpara.Size] then
|
|
|
+ r:=GetNextReg(r);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ load_para_loc(r,hp);
|
|
|
|
|
|
- if i<tcgsize2size[cgpara.Size] then
|
|
|
- for i2:=1 to tcgsize2size[hp^.Size] do
|
|
|
- r:=GetNextReg(r);
|
|
|
+ if i<tcgsize2size[cgpara.Size] then
|
|
|
+ for i2:=1 to tcgsize2size[hp^.Size] do
|
|
|
+ r:=GetNextReg(r);
|
|
|
|
|
|
- hp:=hp^.Next;
|
|
|
- end;
|
|
|
+ hp:=hp^.Next;
|
|
|
end;
|
|
|
- if assigned(hp) then
|
|
|
- internalerror(2014011103);
|
|
|
end;
|
|
|
+ if assigned(hp) then
|
|
|
+ internalerror(2014011103);
|
|
|
end;
|
|
|
|
|
|
|
|
|
procedure tcgavr.a_load_const_cgpara(list : TAsmList;size : tcgsize;a : tcgint;const paraloc : TCGPara);
|
|
|
var
|
|
|
- i : longint;
|
|
|
+ i,j : longint;
|
|
|
hp : PCGParaLocation;
|
|
|
ref: treference;
|
|
|
+ tmpreg: TRegister;
|
|
|
begin
|
|
|
if not(tcgsize2size[paraloc.Size] in [1..4]) then
|
|
|
internalerror(2014011101);
|
|
@@ -322,11 +291,13 @@ unit cgcpu;
|
|
|
end;
|
|
|
LOC_REFERENCE,LOC_CREFERENCE:
|
|
|
begin
|
|
|
- reference_reset(ref,paraloc.alignment,[]);
|
|
|
- ref.base:=hp^.reference.index;
|
|
|
- ref.offset:=hp^.reference.offset;
|
|
|
- a_load_const_ref(list,hp^.size,a shr (8*(i-1)),ref);
|
|
|
-
|
|
|
+ for j:=1 to tcgsize2size[hp^.size] do
|
|
|
+ begin
|
|
|
+ tmpreg:=getintregister(list,OS_8);
|
|
|
+ a_load_const_reg(list,OS_8,(a shr (8*(i-1+j-1))) and $ff,tmpreg);
|
|
|
+ { as AVR allows no stack indirect addressing, everything else than a push makes no sense }
|
|
|
+ list.concat(taicpu.op_reg(A_PUSH,tmpreg));
|
|
|
+ end;
|
|
|
inc(i,tcgsize2size[hp^.size]);
|
|
|
hp:=hp^.Next;
|
|
|
end;
|
|
@@ -342,6 +313,8 @@ unit cgcpu;
|
|
|
tmpref, ref: treference;
|
|
|
location: pcgparalocation;
|
|
|
sizeleft: tcgint;
|
|
|
+ i: Integer;
|
|
|
+ tmpreg: TRegister;
|
|
|
begin
|
|
|
location := paraloc.location;
|
|
|
tmpref := r;
|
|
@@ -354,15 +327,14 @@ unit cgcpu;
|
|
|
a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
|
|
|
LOC_REFERENCE:
|
|
|
begin
|
|
|
- reference_reset_base(ref,location^.reference.index,location^.reference.offset,ctempposinvalid,paraloc.alignment,[]);
|
|
|
- { doubles in softemu mode have a strange order of registers and references }
|
|
|
- if location^.size=OS_32 then
|
|
|
- g_concatcopy(list,tmpref,ref,4)
|
|
|
- else
|
|
|
+ ref:=tmpref;
|
|
|
+ for i:=1 to sizeleft do
|
|
|
begin
|
|
|
- g_concatcopy(list,tmpref,ref,sizeleft);
|
|
|
- if assigned(location^.next) then
|
|
|
- internalerror(2005010710);
|
|
|
+ tmpreg:=getintregister(list,OS_8);
|
|
|
+ a_load_ref_reg(list,OS_8,OS_8,tmpref,tmpreg);
|
|
|
+ { as AVR allows no stack indirect addressing, everything else than a push makes no sense }
|
|
|
+ list.concat(taicpu.op_reg(A_PUSH,tmpreg));
|
|
|
+ inc(tmpref.offset);
|
|
|
end;
|
|
|
end;
|
|
|
LOC_VOID:
|
|
@@ -438,6 +410,18 @@ unit cgcpu;
|
|
|
|
|
|
|
|
|
procedure tcgavr.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister);
|
|
|
+ begin
|
|
|
+ a_op_const_reg_reg_internal(list,op,size,a,src,NR_NO,dst,NR_NO);
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ procedure tcgavr.a_op_const_reg_reg_internal(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src,srchi,dst,dsthi: tregister);
|
|
|
+ var
|
|
|
+ tmpSrc, tmpDst, countreg: TRegister;
|
|
|
+ b, b2, i, j: byte;
|
|
|
+ s1, s2, t1: integer;
|
|
|
+ l1: TAsmLabel;
|
|
|
+ oldexecutionweight: LongInt;
|
|
|
begin
|
|
|
if (op in [OP_MUL,OP_IMUL]) and (size in [OS_16,OS_S16]) and (a in [2,4,8]) then
|
|
|
begin
|
|
@@ -451,6 +435,105 @@ unit cgcpu;
|
|
|
a:=a shr 1;
|
|
|
end;
|
|
|
end
|
|
|
+
|
|
|
+ else if (op in [OP_SHL,OP_SHR]) and
|
|
|
+ { a=0 get eliminated later by tcg.optimize_op_const }
|
|
|
+ (a>0) then
|
|
|
+ begin
|
|
|
+ { number of bytes to shift }
|
|
|
+ b:=a div 8;
|
|
|
+
|
|
|
+ { Ensure that b is never larger than base type }
|
|
|
+ if b>tcgsize2size[size] then
|
|
|
+ begin
|
|
|
+ b:=tcgsize2size[size];
|
|
|
+ b2:=0;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ b2:=a mod 8;
|
|
|
+
|
|
|
+ if b < tcgsize2size[size] then
|
|
|
+ { copy from src to dst accounting for shift offset }
|
|
|
+ for i:=0 to (tcgsize2size[size]-b-1) do
|
|
|
+ if op=OP_SHL then
|
|
|
+ a_load_reg_reg(list,OS_8,OS_8,
|
|
|
+ GetOffsetReg64(src,srchi,i),
|
|
|
+ GetOffsetReg64(dst,dsthi,i+b))
|
|
|
+ else
|
|
|
+ a_load_reg_reg(list,OS_8,OS_8,
|
|
|
+ GetOffsetReg64(src,srchi,i+b),
|
|
|
+ GetOffsetReg64(dst,dsthi,i));
|
|
|
+
|
|
|
+ { remaining bit shifts }
|
|
|
+ if b2 > 0 then
|
|
|
+ begin
|
|
|
+ { Cost of loop }
|
|
|
+ s1:=3+tcgsize2size[size]-b;
|
|
|
+ t1:=b2*(tcgsize2size[size]-b+3);
|
|
|
+ { Cost of loop unrolling,t2=s2 }
|
|
|
+ s2:=b2*(tcgsize2size[size]-b);
|
|
|
+
|
|
|
+ if ((cs_opt_size in current_settings.optimizerswitches) and (s1<s2)) or
|
|
|
+ (((s2-s1)-t1/s2)>0) then
|
|
|
+ begin
|
|
|
+ { Shift non-moved bytes in loop }
|
|
|
+ current_asmdata.getjumplabel(l1);
|
|
|
+ countreg:=getintregister(list,OS_8);
|
|
|
+ a_load_const_reg(list,OS_8,b2,countreg);
|
|
|
+ cg.a_label(list,l1);
|
|
|
+ oldexecutionweight:=executionweight;
|
|
|
+ executionweight:=executionweight*b2;
|
|
|
+ if op=OP_SHL then
|
|
|
+ list.concat(taicpu.op_reg(A_LSL,GetOffsetReg64(dst,dsthi,b)))
|
|
|
+ else
|
|
|
+ list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1-b)));
|
|
|
+
|
|
|
+ if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
|
|
|
+ begin
|
|
|
+ for i:=2+b to tcgsize2size[size] do
|
|
|
+ if op=OP_SHL then
|
|
|
+ list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(dst,dsthi,i-1)))
|
|
|
+ else
|
|
|
+ list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
|
|
|
+ end;
|
|
|
+ list.concat(taicpu.op_reg(A_DEC,countreg));
|
|
|
+ a_jmp_flags(list,F_NE,l1);
|
|
|
+ executionweight:=oldexecutionweight;
|
|
|
+ { keep registers alive }
|
|
|
+ a_reg_sync(list,countreg);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ { Unroll shift loop over non-moved bytes }
|
|
|
+ for j:=1 to b2 do
|
|
|
+ begin
|
|
|
+ if op=OP_SHL then
|
|
|
+ list.concat(taicpu.op_reg(A_LSL,
|
|
|
+ GetOffsetReg64(dst,dsthi,b)))
|
|
|
+ else
|
|
|
+ list.concat(taicpu.op_reg(A_LSR,
|
|
|
+ GetOffsetReg64(dst,dsthi,tcgsize2size[size]-b-1)));
|
|
|
+
|
|
|
+ if not(size in [OS_8,OS_S8]) then
|
|
|
+ for i:=2 to tcgsize2size[size]-b do
|
|
|
+ if op=OP_SHL then
|
|
|
+ list.concat(taicpu.op_reg(A_ROL,
|
|
|
+ GetOffsetReg64(dst,dsthi,b+i-1)))
|
|
|
+ else
|
|
|
+ list.concat(taicpu.op_reg(A_ROR,
|
|
|
+ GetOffsetReg64(dst,dsthi,tcgsize2size[size]-b-i)));
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { fill skipped destination registers with 0
|
|
|
+ Do last,then optimizer can optimize register moves }
|
|
|
+ for i:=1 to b do
|
|
|
+ if op=OP_SHL then
|
|
|
+ emit_mov(list,GetOffsetReg64(dst,dsthi,i-1),GetDefaultZeroReg)
|
|
|
+ else
|
|
|
+ emit_mov(list,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i),GetDefaultZeroReg);
|
|
|
+ end
|
|
|
else
|
|
|
inherited a_op_const_reg_reg(list,op,size,a,src,dst);
|
|
|
end;
|
|
@@ -647,7 +730,7 @@ unit cgcpu;
|
|
|
if not(size in [OS_8,OS_S8]) then
|
|
|
begin
|
|
|
list.concat(taicpu.op_none(A_CLC));
|
|
|
- list.concat(taicpu.op_reg_const(A_SBRC,src,0));
|
|
|
+ list.concat(taicpu.op_reg_const(A_SBRC,dst,0));
|
|
|
list.concat(taicpu.op_none(A_SEC));
|
|
|
end;
|
|
|
list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
|
|
@@ -687,8 +770,8 @@ unit cgcpu;
|
|
|
|
|
|
list.concat(taicpu.op_reg(A_DEC,countreg));
|
|
|
a_jmp_flags(list,F_NE,l1);
|
|
|
- // keep registers alive
|
|
|
- list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
|
|
|
+ { keep registers alive }
|
|
|
+ a_reg_sync(list,countreg);
|
|
|
cg.a_label(list,l2);
|
|
|
end;
|
|
|
|
|
@@ -771,9 +854,14 @@ unit cgcpu;
|
|
|
for i:=1 to tcgsize2size[size] do
|
|
|
begin
|
|
|
if ((qword(a) and mask) shr shift)=0 then
|
|
|
- list.concat(taicpu.op_reg_reg(A_MOV,reg,NR_R1))
|
|
|
+ list.concat(taicpu.op_reg_reg(A_MOV,reg,GetDefaultZeroReg))
|
|
|
else if ((qword(a) and mask) shr shift)<>$ff then
|
|
|
- list.concat(taicpu.op_reg_const(A_ANDI,reg,(qword(a) and mask) shr shift));
|
|
|
+ begin
|
|
|
+ getcpuregister(list,NR_R26);
|
|
|
+ list.concat(taicpu.op_reg_const(A_LDI,NR_R26,(qword(a) and mask) shr shift));
|
|
|
+ list.concat(taicpu.op_reg_reg(A_AND,reg,NR_R26));
|
|
|
+ ungetcpuregister(list,NR_R26);
|
|
|
+ end;
|
|
|
{ check if we are not in the last iteration to avoid an internalerror in GetNextReg }
|
|
|
if i<tcgsize2size[size] then
|
|
|
NextRegPostInc;
|
|
@@ -786,7 +874,12 @@ unit cgcpu;
|
|
|
if ((a and mask)=1) and (tcgsize2size[size]=1) then
|
|
|
list.concat(taicpu.op_reg(A_DEC,reg))
|
|
|
else
|
|
|
- list.concat(taicpu.op_reg_const(A_SUBI,reg,a and mask));
|
|
|
+ begin
|
|
|
+ getcpuregister(list,NR_R26);
|
|
|
+ list.concat(taicpu.op_reg_const(A_LDI,NR_R26,a and mask));
|
|
|
+ list.concat(taicpu.op_reg_reg(A_SUB,reg,NR_R26));
|
|
|
+ ungetcpuregister(list,NR_R26);
|
|
|
+ end;
|
|
|
if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
|
|
|
begin
|
|
|
for i:=2 to tcgsize2size[size] do
|
|
@@ -798,7 +891,7 @@ unit cgcpu;
|
|
|
{ decrease pressure on upper half of registers by using SBC ...,R1 instead
|
|
|
of SBCI ...,0 }
|
|
|
if curvalue=0 then
|
|
|
- list.concat(taicpu.op_reg_reg(A_SBC,reg,NR_R1))
|
|
|
+ list.concat(taicpu.op_reg_reg(A_SBC,reg,GetDefaultZeroReg))
|
|
|
else
|
|
|
list.concat(taicpu.op_reg_const(A_SBCI,reg,curvalue));
|
|
|
end;
|
|
@@ -895,7 +988,7 @@ unit cgcpu;
|
|
|
begin
|
|
|
curvalue:=a and mask;
|
|
|
if curvalue=0 then
|
|
|
- list.concat(taicpu.op_reg_reg(A_ADD,reg,NR_R1))
|
|
|
+ list.concat(taicpu.op_reg_reg(A_ADD,reg,GetDefaultZeroReg))
|
|
|
else if (curvalue=1) and (tcgsize2size[size]=1) then
|
|
|
list.concat(taicpu.op_reg(A_INC,reg))
|
|
|
else
|
|
@@ -915,7 +1008,7 @@ unit cgcpu;
|
|
|
{ decrease pressure on upper half of registers by using ADC ...,R1 instead
|
|
|
of ADD ...,0 }
|
|
|
if curvalue=0 then
|
|
|
- list.concat(taicpu.op_reg_reg(A_ADC,reg,NR_R1))
|
|
|
+ list.concat(taicpu.op_reg_reg(A_ADC,reg,GetDefaultZeroReg))
|
|
|
else
|
|
|
begin
|
|
|
tmpreg:=getintregister(list,OS_8);
|
|
@@ -943,7 +1036,7 @@ unit cgcpu;
|
|
|
tmpreg:=reg;
|
|
|
for i:=1 to 4 do
|
|
|
begin
|
|
|
- list.concat(taicpu.op_reg_reg(A_MOV,tmpreg,NR_R1));
|
|
|
+ list.concat(taicpu.op_reg_reg(A_MOV,tmpreg,GetDefaultZeroReg));
|
|
|
tmpreg:=GetNextReg(tmpreg);
|
|
|
end;
|
|
|
end
|
|
@@ -971,7 +1064,7 @@ unit cgcpu;
|
|
|
for i:=1 to tcgsize2size[size] do
|
|
|
begin
|
|
|
if ((qword(a) and mask) shr shift)=0 then
|
|
|
- emit_mov(list,reg,NR_R1)
|
|
|
+ emit_mov(list,reg,GetDefaultZeroReg)
|
|
|
else
|
|
|
begin
|
|
|
getcpuregister(list,NR_R26);
|
|
@@ -998,7 +1091,6 @@ unit cgcpu;
|
|
|
|
|
|
|
|
|
function tcgavr.normalize_ref(list:TAsmList;ref: treference;tmpreg : tregister) : treference;
|
|
|
-
|
|
|
var
|
|
|
tmpref : treference;
|
|
|
l : tasmlabel;
|
|
@@ -1011,9 +1103,6 @@ unit cgcpu;
|
|
|
{ Be sure to have a base register }
|
|
|
if (ref.base=NR_NO) then
|
|
|
begin
|
|
|
- { only symbol+offset? }
|
|
|
- if ref.index=NR_NO then
|
|
|
- exit;
|
|
|
ref.base:=ref.index;
|
|
|
ref.index:=NR_NO;
|
|
|
end;
|
|
@@ -1101,7 +1190,9 @@ unit cgcpu;
|
|
|
emit_mov(list,GetNextReg(tmpreg),GetNextReg(ref.index));
|
|
|
ref.base:=tmpreg;
|
|
|
ref.index:=NR_NO;
|
|
|
- end;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ Internalerror(2020011901);
|
|
|
Result:=ref;
|
|
|
end;
|
|
|
|
|
@@ -1131,7 +1222,8 @@ unit cgcpu;
|
|
|
if not((href.addressmode=AM_UNCHANGED) and
|
|
|
(href.symbol=nil) and
|
|
|
(href.Index=NR_NO) and
|
|
|
- (href.Offset in [0..64-tcgsize2size[fromsize]])) then
|
|
|
+ (href.Offset in [0..64-tcgsize2size[fromsize]])) or
|
|
|
+ (CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
|
|
|
begin
|
|
|
href:=normalize_ref(list,href,NR_R30);
|
|
|
getcpuregister(list,NR_R30);
|
|
@@ -1181,7 +1273,7 @@ unit cgcpu;
|
|
|
else
|
|
|
href.addressmode:=AM_UNCHANGED;
|
|
|
|
|
|
- list.concat(taicpu.op_ref_reg(GetStore(href),href,NR_R1));
|
|
|
+ list.concat(taicpu.op_ref_reg(GetStore(href),href,GetDefaultZeroReg));
|
|
|
end;
|
|
|
end;
|
|
|
OS_S8:
|
|
@@ -1193,7 +1285,7 @@ unit cgcpu;
|
|
|
if tcgsize2size[tosize]>1 then
|
|
|
begin
|
|
|
tmpreg:=getintregister(list,OS_8);
|
|
|
- emit_mov(list,tmpreg,NR_R1);
|
|
|
+ emit_mov(list,tmpreg,GetDefaultZeroReg);
|
|
|
list.concat(taicpu.op_reg_const(A_SBRC,reg,7));
|
|
|
list.concat(taicpu.op_reg(A_COM,tmpreg));
|
|
|
for i:=2 to tcgsize2size[tosize] do
|
|
@@ -1235,7 +1327,7 @@ unit cgcpu;
|
|
|
else
|
|
|
href.addressmode:=AM_UNCHANGED;
|
|
|
|
|
|
- list.concat(taicpu.op_ref_reg(GetStore(href),href,NR_R1));
|
|
|
+ list.concat(taicpu.op_ref_reg(GetStore(href),href,GetDefaultZeroReg));
|
|
|
end;
|
|
|
end;
|
|
|
OS_S16:
|
|
@@ -1257,7 +1349,7 @@ unit cgcpu;
|
|
|
if tcgsize2size[tosize]>2 then
|
|
|
begin
|
|
|
tmpreg:=getintregister(list,OS_8);
|
|
|
- emit_mov(list,tmpreg,NR_R1);
|
|
|
+ emit_mov(list,tmpreg,GetDefaultZeroReg);
|
|
|
list.concat(taicpu.op_reg_const(A_SBRC,reg,7));
|
|
|
list.concat(taicpu.op_reg(A_COM,tmpreg));
|
|
|
for i:=3 to tcgsize2size[tosize] do
|
|
@@ -1283,8 +1375,11 @@ unit cgcpu;
|
|
|
// 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
|
|
|
+ // 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
|
|
|
begin
|
|
|
tmpreg:=GetNextReg(reg);
|
|
|
href.addressmode:=AM_UNCHANGED;
|
|
@@ -1348,7 +1443,8 @@ unit cgcpu;
|
|
|
if not((href.addressmode=AM_UNCHANGED) and
|
|
|
(href.symbol=nil) and
|
|
|
(href.Index=NR_NO) and
|
|
|
- (href.Offset in [0..64-tcgsize2size[fromsize]])) then
|
|
|
+ (href.Offset in [0..64-tcgsize2size[fromsize]])) or
|
|
|
+ (CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) then
|
|
|
begin
|
|
|
href:=normalize_ref(list,href,NR_R30);
|
|
|
getcpuregister(list,NR_R30);
|
|
@@ -1388,7 +1484,7 @@ unit cgcpu;
|
|
|
for i:=2 to tcgsize2size[tosize] do
|
|
|
begin
|
|
|
reg:=GetNextReg(reg);
|
|
|
- emit_mov(list,reg,NR_R1);
|
|
|
+ emit_mov(list,reg,GetDefaultZeroReg);
|
|
|
end;
|
|
|
end;
|
|
|
OS_S8:
|
|
@@ -1399,7 +1495,7 @@ unit cgcpu;
|
|
|
if tcgsize2size[tosize]>1 then
|
|
|
begin
|
|
|
reg:=GetNextReg(reg);
|
|
|
- emit_mov(list,reg,NR_R1);
|
|
|
+ emit_mov(list,reg,GetDefaultZeroReg);
|
|
|
list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
|
|
|
list.concat(taicpu.op_reg(A_COM,reg));
|
|
|
tmpreg:=reg;
|
|
@@ -1426,7 +1522,7 @@ unit cgcpu;
|
|
|
for i:=3 to tcgsize2size[tosize] do
|
|
|
begin
|
|
|
reg:=GetNextReg(reg);
|
|
|
- emit_mov(list,reg,NR_R1);
|
|
|
+ emit_mov(list,reg,GetDefaultZeroReg);
|
|
|
end;
|
|
|
end;
|
|
|
OS_S16:
|
|
@@ -1443,7 +1539,7 @@ unit cgcpu;
|
|
|
tmpreg:=reg;
|
|
|
|
|
|
reg:=GetNextReg(reg);
|
|
|
- emit_mov(list,reg,NR_R1);
|
|
|
+ emit_mov(list,reg,GetDefaultZeroReg);
|
|
|
list.concat(taicpu.op_reg_const(A_SBRC,tmpreg,7));
|
|
|
list.concat(taicpu.op_reg(A_COM,reg));
|
|
|
tmpreg:=reg;
|
|
@@ -1507,7 +1603,7 @@ unit cgcpu;
|
|
|
for i:=2 to tcgsize2size[tosize] do
|
|
|
begin
|
|
|
reg2:=GetNextReg(reg2);
|
|
|
- emit_mov(list,reg2,NR_R1);
|
|
|
+ emit_mov(list,reg2,GetDefaultZeroReg);
|
|
|
end;
|
|
|
end;
|
|
|
OS_S8:
|
|
@@ -1517,7 +1613,7 @@ unit cgcpu;
|
|
|
if tcgsize2size[tosize]>1 then
|
|
|
begin
|
|
|
reg2:=GetNextReg(reg2);
|
|
|
- emit_mov(list,reg2,NR_R1);
|
|
|
+ emit_mov(list,reg2,GetDefaultZeroReg);
|
|
|
list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
|
|
|
list.concat(taicpu.op_reg(A_COM,reg2));
|
|
|
tmpreg:=reg2;
|
|
@@ -1539,7 +1635,7 @@ unit cgcpu;
|
|
|
for i:=3 to tcgsize2size[tosize] do
|
|
|
begin
|
|
|
reg2:=GetNextReg(reg2);
|
|
|
- emit_mov(list,reg2,NR_R1);
|
|
|
+ emit_mov(list,reg2,GetDefaultZeroReg);
|
|
|
end;
|
|
|
end;
|
|
|
OS_S16:
|
|
@@ -1553,7 +1649,7 @@ unit cgcpu;
|
|
|
if tcgsize2size[tosize]>2 then
|
|
|
begin
|
|
|
reg2:=GetNextReg(reg2);
|
|
|
- emit_mov(list,reg2,NR_R1);
|
|
|
+ emit_mov(list,reg2,GetDefaultZeroReg);
|
|
|
list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
|
|
|
list.concat(taicpu.op_reg(A_COM,reg2));
|
|
|
tmpreg:=reg2;
|
|
@@ -1645,22 +1741,22 @@ unit cgcpu;
|
|
|
for i:=2 to tcgsize2size[size] do
|
|
|
reg:=GetNextReg(reg);
|
|
|
|
|
|
- list.concat(taicpu.op_reg_reg(A_CP,reg,NR_R1));
|
|
|
+ list.concat(taicpu.op_reg_reg(A_CP,reg,GetDefaultZeroReg));
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
|
if swapped then
|
|
|
- list.concat(taicpu.op_reg_reg(A_CP,NR_R1,reg))
|
|
|
+ list.concat(taicpu.op_reg_reg(A_CP,GetDefaultZeroReg,reg))
|
|
|
else
|
|
|
- list.concat(taicpu.op_reg_reg(A_CP,reg,NR_R1));
|
|
|
+ list.concat(taicpu.op_reg_reg(A_CP,reg,GetDefaultZeroReg));
|
|
|
|
|
|
for i:=2 to tcgsize2size[size] do
|
|
|
begin
|
|
|
reg:=GetNextReg(reg);
|
|
|
if swapped then
|
|
|
- list.concat(taicpu.op_reg_reg(A_CPC,NR_R1,reg))
|
|
|
+ list.concat(taicpu.op_reg_reg(A_CPC,GetDefaultZeroReg,reg))
|
|
|
else
|
|
|
- list.concat(taicpu.op_reg_reg(A_CPC,reg,NR_R1));
|
|
|
+ list.concat(taicpu.op_reg_reg(A_CPC,reg,GetDefaultZeroReg));
|
|
|
end;
|
|
|
end;
|
|
|
|
|
@@ -1761,6 +1857,8 @@ unit cgcpu;
|
|
|
var
|
|
|
l : TAsmLabel;
|
|
|
tmpflags : TResFlags;
|
|
|
+ i: Integer;
|
|
|
+ hreg: TRegister;
|
|
|
begin
|
|
|
current_asmdata.getjumplabel(l);
|
|
|
{
|
|
@@ -1768,7 +1866,7 @@ unit cgcpu;
|
|
|
begin
|
|
|
tmpflags:=f;
|
|
|
inverse_flags(tmpflags);
|
|
|
- emit_mov(reg,NR_R1);
|
|
|
+ emit_mov(reg,GetDefaultZeroReg);
|
|
|
a_jmp_flags(list,tmpflags,l);
|
|
|
list.concat(taicpu.op_reg_const(A_LDI,reg,1));
|
|
|
end
|
|
@@ -1776,8 +1874,15 @@ unit cgcpu;
|
|
|
}
|
|
|
begin
|
|
|
list.concat(taicpu.op_reg_const(A_LDI,reg,1));
|
|
|
+ hreg:=reg;
|
|
|
+ for i:=2 to tcgsize2size[size] do
|
|
|
+ begin
|
|
|
+ hreg:=GetNextReg(hreg);
|
|
|
+ emit_mov(list,hreg,GetDefaultZeroReg);
|
|
|
+ end;
|
|
|
+
|
|
|
a_jmp_flags(list,f,l);
|
|
|
- emit_mov(list,reg,NR_R1);
|
|
|
+ emit_mov(list,reg,GetDefaultZeroReg);
|
|
|
end;
|
|
|
cg.a_label(list,l);
|
|
|
end;
|
|
@@ -1793,21 +1898,21 @@ unit cgcpu;
|
|
|
{-14..-1:
|
|
|
begin
|
|
|
if ((-value) mod 2)<>0 then
|
|
|
- list.concat(taicpu.op_reg(A_PUSH,NR_R0));
|
|
|
+ list.concat(taicpu.op_reg(A_PUSH,GetDefaultTmpReg));
|
|
|
for i:=1 to (-value) div 2 do
|
|
|
list.concat(taicpu.op_const(A_RCALL,0));
|
|
|
end;
|
|
|
1..7:
|
|
|
begin
|
|
|
for i:=1 to value do
|
|
|
- list.concat(taicpu.op_reg(A_POP,NR_R0));
|
|
|
+ list.concat(taicpu.op_reg(A_POP,GetDefaultTmpReg));
|
|
|
end;}
|
|
|
else
|
|
|
begin
|
|
|
list.concat(taicpu.op_reg_const(A_SUBI,NR_R28,lo(word(-value))));
|
|
|
list.concat(taicpu.op_reg_const(A_SBCI,NR_R29,hi(word(-value))));
|
|
|
// get SREG
|
|
|
- list.concat(taicpu.op_reg_const(A_IN,NR_R0,NIO_SREG));
|
|
|
+ list.concat(taicpu.op_reg_const(A_IN,GetDefaultTmpReg,NIO_SREG));
|
|
|
|
|
|
// block interrupts
|
|
|
list.concat(taicpu.op_none(A_CLI));
|
|
@@ -1816,7 +1921,7 @@ unit cgcpu;
|
|
|
list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_HI,NR_R29));
|
|
|
|
|
|
// release interrupts
|
|
|
- list.concat(taicpu.op_const_reg(A_OUT,NIO_SREG,NR_R0));
|
|
|
+ list.concat(taicpu.op_const_reg(A_OUT,NIO_SREG,GetDefaultTmpReg));
|
|
|
|
|
|
// write low SP
|
|
|
list.concat(taicpu.op_const_reg(A_OUT,NIO_SP_LO,NR_R28));
|
|
@@ -1968,8 +2073,8 @@ unit cgcpu;
|
|
|
pd:=search_system_proc(name);
|
|
|
paraloc1.init;
|
|
|
paraloc2.init;
|
|
|
- paramanager.getintparaloc(list,pd,1,paraloc1);
|
|
|
- paramanager.getintparaloc(list,pd,2,paraloc2);
|
|
|
+ paramanager.getcgtempparaloc(list,pd,1,paraloc1);
|
|
|
+ paramanager.getcgtempparaloc(list,pd,2,paraloc2);
|
|
|
a_load_reg_cgpara(list,OS_8,src1,paraloc2);
|
|
|
a_load_reg_cgpara(list,OS_8,src2,paraloc1);
|
|
|
paramanager.freecgpara(list,paraloc2);
|
|
@@ -2065,8 +2170,8 @@ unit cgcpu;
|
|
|
pd:=search_system_proc(name);
|
|
|
paraloc1.init;
|
|
|
paraloc2.init;
|
|
|
- paramanager.getintparaloc(list,pd,1,paraloc1);
|
|
|
- paramanager.getintparaloc(list,pd,2,paraloc2);
|
|
|
+ paramanager.getcgtempparaloc(list,pd,1,paraloc1);
|
|
|
+ paramanager.getcgtempparaloc(list,pd,2,paraloc2);
|
|
|
a_load_reg_cgpara(list,OS_16,src1,paraloc2);
|
|
|
a_load_reg_cgpara(list,OS_16,src2,paraloc1);
|
|
|
paramanager.freecgpara(list,paraloc2);
|
|
@@ -2120,21 +2225,26 @@ unit cgcpu;
|
|
|
regs:=regs+[RS_R28,RS_R29];
|
|
|
|
|
|
{ we clear r1 }
|
|
|
- include(regs,RS_R1);
|
|
|
+ include(regs,getsupreg(GetDefaultZeroReg));
|
|
|
|
|
|
- regs:=regs+[RS_R0];
|
|
|
+ regs:=regs+[getsupreg(GetDefaultTmpReg)];
|
|
|
|
|
|
- for reg:=RS_R31 downto RS_R0 do
|
|
|
- if reg in regs then
|
|
|
- list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
|
|
|
+ if current_settings.cputype=cpu_avr1 then
|
|
|
+ message1(cg_w_interrupt_does_not_save_registers,current_procinfo.procdef.fullprocname(false))
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ for reg:=RS_R31 downto RS_R0 do
|
|
|
+ if reg in regs then
|
|
|
+ list.concat(taicpu.op_reg(A_PUSH,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
|
|
|
+ { Save SREG }
|
|
|
+ cg.getcpuregister(list,GetDefaultTmpReg);
|
|
|
+ list.concat(taicpu.op_reg_const(A_IN, GetDefaultTmpReg, $3F));
|
|
|
+ list.concat(taicpu.op_reg(A_PUSH, GetDefaultTmpReg));
|
|
|
+ cg.ungetcpuregister(list,GetDefaultTmpReg);
|
|
|
+ end;
|
|
|
|
|
|
- { Save SREG }
|
|
|
- cg.getcpuregister(list,NR_R0);
|
|
|
- list.concat(taicpu.op_reg_const(A_IN, NR_R0, $3F));
|
|
|
- list.concat(taicpu.op_reg(A_PUSH, NR_R0));
|
|
|
- cg.ungetcpuregister(list,NR_R0);
|
|
|
|
|
|
- list.concat(taicpu.op_reg(A_CLR,NR_R1));
|
|
|
+ list.concat(taicpu.op_reg(A_CLR,GetDefaultZeroReg));
|
|
|
|
|
|
if current_procinfo.framepointer<>NR_NO then
|
|
|
begin
|
|
@@ -2208,19 +2318,23 @@ unit cgcpu;
|
|
|
end;
|
|
|
|
|
|
{ we clear r1 }
|
|
|
- include(regs,RS_R1);
|
|
|
+ include(regs,getsupreg(GetDefaultZeroReg));
|
|
|
|
|
|
- { Reload SREG }
|
|
|
- regs:=regs+[RS_R0];
|
|
|
+ if current_settings.cputype<>cpu_avr1 then
|
|
|
+ begin
|
|
|
+ { Reload SREG }
|
|
|
+ regs:=regs+[getsupreg(GetDefaultTmpReg)];
|
|
|
|
|
|
- cg.getcpuregister(list,NR_R0);
|
|
|
- list.concat(taicpu.op_reg(A_POP, NR_R0));
|
|
|
- list.concat(taicpu.op_const_reg(A_OUT, $3F, NR_R0));
|
|
|
- cg.ungetcpuregister(list,NR_R0);
|
|
|
|
|
|
- for reg:=RS_R0 to RS_R31 do
|
|
|
- if reg in regs then
|
|
|
- list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
|
|
|
+ cg.getcpuregister(list,GetDefaultTmpReg);
|
|
|
+ list.concat(taicpu.op_reg(A_POP, GetDefaultTmpReg));
|
|
|
+ list.concat(taicpu.op_const_reg(A_OUT, $3F, GetDefaultTmpReg));
|
|
|
+ cg.ungetcpuregister(list,GetDefaultTmpReg);
|
|
|
+
|
|
|
+ for reg:=RS_R0 to RS_R31 do
|
|
|
+ if reg in regs then
|
|
|
+ list.concat(taicpu.op_reg(A_POP,newreg(R_INTREGISTER,reg,R_SUBWHOLE)));
|
|
|
+ end;
|
|
|
end;
|
|
|
list.concat(taicpu.op_none(A_RETI));
|
|
|
end
|
|
@@ -2312,9 +2426,9 @@ unit cgcpu;
|
|
|
paraloc1.init;
|
|
|
paraloc2.init;
|
|
|
paraloc3.init;
|
|
|
- paramanager.getintparaloc(list,pd,1,paraloc1);
|
|
|
- paramanager.getintparaloc(list,pd,2,paraloc2);
|
|
|
- paramanager.getintparaloc(list,pd,3,paraloc3);
|
|
|
+ paramanager.getcgtempparaloc(list,pd,1,paraloc1);
|
|
|
+ paramanager.getcgtempparaloc(list,pd,2,paraloc2);
|
|
|
+ paramanager.getcgtempparaloc(list,pd,3,paraloc3);
|
|
|
a_load_const_cgpara(list,OS_SINT,len,paraloc3);
|
|
|
a_loadaddr_ref_cgpara(list,dest,paraloc2);
|
|
|
a_loadaddr_ref_cgpara(list,source,paraloc1);
|
|
@@ -2391,34 +2505,45 @@ unit cgcpu;
|
|
|
cg.getcpuregister(list,NR_R26);
|
|
|
list.concat(taicpu.op_reg(A_POP,NR_R26));
|
|
|
cg.a_label(list,l);
|
|
|
- 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);
|
|
|
- list.concat(taicpu.op_reg(A_DEC,countreg));
|
|
|
+ cg.getcpuregister(list,GetDefaultTmpReg);
|
|
|
+ list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
|
|
|
+ list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
|
|
|
+ cg.ungetcpuregister(list,GetDefaultTmpReg);
|
|
|
+ if tcgsize2size[countregsize] = 1 then
|
|
|
+ list.concat(taicpu.op_reg(A_DEC,countreg))
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ list.concat(taicpu.op_reg_const(A_SUBI,countreg,1));
|
|
|
+ list.concat(taicpu.op_reg_reg(A_SBC,GetNextReg(countreg),GetDefaultZeroReg));
|
|
|
+ end;
|
|
|
+
|
|
|
a_jmp_flags(list,F_NE,l);
|
|
|
cg.ungetcpuregister(list,NR_R26);
|
|
|
cg.ungetcpuregister(list,NR_R27);
|
|
|
cg.ungetcpuregister(list,NR_R30);
|
|
|
cg.ungetcpuregister(list,NR_R31);
|
|
|
- // keep registers alive
|
|
|
- list.concat(taicpu.op_reg_reg(A_MOV,countreg,countreg));
|
|
|
+ { keep registers alive }
|
|
|
+ a_reg_sync(list,countreg);
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
|
SrcQuickRef:=false;
|
|
|
DestQuickRef:=false;
|
|
|
- if not((source.addressmode=AM_UNCHANGED) and
|
|
|
- (source.symbol=nil) and
|
|
|
- ((source.base=NR_R28) or
|
|
|
- (source.base=NR_R30)) and
|
|
|
- (source.Index=NR_NO) and
|
|
|
- (source.Offset in [0..64-len])) and
|
|
|
- not((source.Base=NR_NO) and (source.Index=NR_NO)) then
|
|
|
+ if ((CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) and
|
|
|
+ not((source.Base=NR_NO) and (source.Index=NR_NO) and (source.symbol=nil) and (source.Offset in [0..192-len]))) or
|
|
|
+ (
|
|
|
+ not((source.addressmode=AM_UNCHANGED) and
|
|
|
+ (source.symbol=nil) and
|
|
|
+ ((source.base=NR_R28) or
|
|
|
+ (source.base=NR_R30)) and
|
|
|
+ (source.Index=NR_NO) and
|
|
|
+ (source.Offset in [0..64-len])) and
|
|
|
+ not((source.Base=NR_NO) and (source.Index=NR_NO))
|
|
|
+ ) then
|
|
|
begin
|
|
|
cg.getcpuregister(list,NR_R30);
|
|
|
cg.getcpuregister(list,NR_R31);
|
|
|
- srcref:=normalize_ref(list,source,NR_R30)
|
|
|
+ srcref:=normalize_ref(list,source,NR_R30);
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
@@ -2426,13 +2551,17 @@ unit cgcpu;
|
|
|
srcref:=source;
|
|
|
end;
|
|
|
|
|
|
- if not((dest.addressmode=AM_UNCHANGED) and
|
|
|
+ if ((CPUAVR_16_REGS in cpu_capabilities[current_settings.cputype]) and
|
|
|
+ not((dest.Base=NR_NO) and (dest.Index=NR_NO) and (dest.symbol=nil) and (dest.Offset in [0..192-len]))) or
|
|
|
+ (
|
|
|
+ not((dest.addressmode=AM_UNCHANGED) and
|
|
|
(dest.symbol=nil) and
|
|
|
((dest.base=NR_R28) or
|
|
|
(dest.base=NR_R30)) and
|
|
|
(dest.Index=NR_No) and
|
|
|
(dest.Offset in [0..64-len])) and
|
|
|
- not((dest.Base=NR_NO) and (dest.Index=NR_NO)) then
|
|
|
+ not((dest.Base=NR_NO) and (dest.Index=NR_NO))
|
|
|
+ ) then
|
|
|
begin
|
|
|
if not(SrcQuickRef) then
|
|
|
begin
|
|
@@ -2479,10 +2608,11 @@ unit cgcpu;
|
|
|
|
|
|
// 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
|
|
|
+ // 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
|
|
|
begin
|
|
|
// If src is also a 16 bit ioreg then read low byte then high byte
|
|
|
if SrcQuickRef and (srcref.offset > 31)
|
|
@@ -2495,39 +2625,39 @@ unit cgcpu;
|
|
|
tmpreg2:=GetNextReg(tmpreg);
|
|
|
list.concat(taicpu.op_reg_ref(GetLoad(srcref),tmpreg2,srcref));
|
|
|
|
|
|
- // 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
|
|
|
+ // 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,GetDefaultTmpReg);
|
|
|
+ list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
|
|
|
+ list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
|
|
|
+ cg.ungetcpuregister(list,GetDefaultTmpReg);
|
|
|
+
|
|
|
+ if not(SrcQuickRef) then
|
|
|
+ srcref.addressmode:=AM_POSTINCREMENT
|
|
|
+ else
|
|
|
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);
|
|
|
-
|
|
|
- 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
|
|
|
+
|
|
|
+ dec(srcref.offset);
|
|
|
+ dec(dstref.offset);
|
|
|
+
|
|
|
+ cg.getcpuregister(list,GetDefaultTmpReg);
|
|
|
+ list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
|
|
|
+ list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
|
|
|
+ cg.ungetcpuregister(list,GetDefaultTmpReg);
|
|
|
+ end;
|
|
|
+ end
|
|
|
+ else
|
|
|
for i:=1 to len do
|
|
|
begin
|
|
|
if not(SrcQuickRef) and (i<len) then
|
|
@@ -2540,10 +2670,10 @@ unit cgcpu;
|
|
|
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);
|
|
|
+ cg.getcpuregister(list,GetDefaultTmpReg);
|
|
|
+ list.concat(taicpu.op_reg_ref(GetLoad(srcref),GetDefaultTmpReg,srcref));
|
|
|
+ list.concat(taicpu.op_ref_reg(GetStore(dstref),dstref,GetDefaultTmpReg));
|
|
|
+ cg.ungetcpuregister(list,GetDefaultTmpReg);
|
|
|
|
|
|
if SrcQuickRef then
|
|
|
inc(srcref.offset);
|
|
@@ -2732,6 +2862,15 @@ unit cgcpu;
|
|
|
end;
|
|
|
|
|
|
|
|
|
+ procedure tcg64favr.a_op64_const_reg_reg(list: TAsmList; op: TOpCg;size: tcgsize;value: int64;src,dst : tregister64);
|
|
|
+ begin
|
|
|
+ if op in [OP_SHL,OP_SHR] then
|
|
|
+ tcgavr(cg).a_op_const_reg_reg_internal(list,Op,size,value,src.reglo,src.reghi,dst.reglo,dst.reghi)
|
|
|
+ else
|
|
|
+ Inherited a_op64_const_reg_reg(list,op,size,value,src,dst);
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
procedure create_codegen;
|
|
|
begin
|
|
|
cg:=tcgavr.create;
|