diff --git a/compiler/avr/cgcpu.pas b/compiler/avr/cgcpu.pas index 731386be0b..c67625d62c 100644 --- a/compiler/avr/cgcpu.pas +++ b/compiler/avr/cgcpu.pas @@ -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; @@ -438,6 +441,12 @@ 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; @@ -478,12 +487,12 @@ unit cgcpu; 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,NR_NO,i), - GetOffsetReg64(dst,NR_NO,i+b)) + GetOffsetReg64(src,srchi,i), + GetOffsetReg64(dst,dsthi,i+b)) else a_load_reg_reg(list,OS_8,OS_8, - GetOffsetReg64(src,NR_NO,i+b), - GetOffsetReg64(dst,NR_NO,i)); + GetOffsetReg64(src,srchi,i+b), + GetOffsetReg64(dst,dsthi,i)); { remaining bit shifts } if b2 > 0 then @@ -503,17 +512,17 @@ unit cgcpu; a_load_const_reg(list,OS_8,b2,countreg); cg.a_label(list,l1); if op=OP_SHL then - list.concat(taicpu.op_reg(A_LSL,GetOffsetReg64(dst,NR_NO,b))) + list.concat(taicpu.op_reg(A_LSL,GetOffsetReg64(dst,dsthi,b))) else - list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(dst,NR_NO,tcgsize2size[size]-1-b))); + 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,NR_NO,i-1))) + list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(dst,dsthi,i-1))) else - list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,NR_NO,tcgsize2size[size]-i))); + 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); @@ -527,19 +536,19 @@ unit cgcpu; begin if op=OP_SHL then list.concat(taicpu.op_reg(A_LSL, - GetOffsetReg64(dst,NR_NO,b))) + GetOffsetReg64(dst,dsthi,b))) else list.concat(taicpu.op_reg(A_LSR, - GetOffsetReg64(dst,NR_NO,tcgsize2size[size]-b-1))); + 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,NR_NO,b+i-1))) + GetOffsetReg64(dst,dsthi,b+i-1))) else list.concat(taicpu.op_reg(A_ROR, - GetOffsetReg64(dst,NR_NO,tcgsize2size[size]-b-i))); + GetOffsetReg64(dst,dsthi,tcgsize2size[size]-b-i))); end; end; end; @@ -548,9 +557,9 @@ unit cgcpu; Do last,then optimizer can optimize register moves } for i:=1 to b do if op=OP_SHL then - emit_mov(list,GetOffsetReg64(dst,NR_NO,i-1),NR_R1) + emit_mov(list,GetOffsetReg64(dst,dsthi,i-1),NR_R1) else - emit_mov(list,GetOffsetReg64(dst,NR_NO,tcgsize2size[size]-i),NR_R1); + emit_mov(list,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i),NR_R1); end else inherited a_op_const_reg_reg(list,op,size,a,src,dst); @@ -2849,6 +2858,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; diff --git a/compiler/avr/navrmat.pas b/compiler/avr/navrmat.pas index 90f643c522..b0a1f508b9 100644 --- a/compiler/avr/navrmat.pas +++ b/compiler/avr/navrmat.pas @@ -34,7 +34,9 @@ interface end; tavrshlshrnode = class(tcgshlshrnode) + function pass_1: tnode;override; procedure second_integer;override; + procedure second_64bit;override; end; implementation @@ -46,7 +48,7 @@ implementation aasmbase,aasmcpu,aasmtai,aasmdata, defutil, cgbase,cgobj,hlcgobj,cgutils, - pass_2,procinfo, + pass_1,pass_2,procinfo, ncon, cpubase, ncgutil,cgcpu; @@ -129,6 +131,28 @@ implementation end; +{***************************************************************************** + TAVRSHLSHRNODE +*****************************************************************************} + + function tavrshlshrnode.pass_1 : tnode; + begin + { the avr code generator can handle 64 bit shifts by constants directly } + if is_constintnode(right) and is_64bit(resultdef) then + begin + result:=nil; + firstpass(left); + firstpass(right); + if codegenerror then + exit; + + expectloc:=LOC_REGISTER; + end + else + Result:=inherited pass_1; + end; + + procedure tavrshlshrnode.second_integer; var op : topcg; @@ -152,7 +176,13 @@ implementation (left.location.size<>opsize) then hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true); location_reset(location,LOC_REGISTER,opsize); - location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); + if is_64bit(resultdef) then + begin + location.register:=cg.getintregister(current_asmdata.CurrAsmList,OS_32); + location.registerhi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32); + end + else + location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); { shifting by a constant directly coded: } if (right.nodetype=ordconstn) then @@ -164,8 +194,12 @@ implementation shiftval:=tordconstnode(right).value.uvalue and 31 else shiftval:=tordconstnode(right).value.uvalue and 63; - hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,opdef, - shiftval,left.location.register,location.register); + if is_64bit(resultdef) then + cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,op,location.size, + shiftval,left.location.register64,location.register64) + else + hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,opdef, + shiftval,left.location.register,location.register); end else begin @@ -186,6 +220,13 @@ implementation end; end; + + procedure tavrshlshrnode.second_64bit; + begin + second_integer; + // inherited second_64bit; + end; + begin cnotnode:=tavrnotnode; cshlshrnode:=tavrshlshrnode;