+ support of 64 bit operations on avr

git-svn-id: trunk@22836 -
This commit is contained in:
florian 2012-10-23 20:15:47 +00:00
parent ecd0749d73
commit a3dff44489

View File

@ -56,7 +56,7 @@ unit cgcpu;
procedure a_call_ref(list : TAsmList;ref: treference);override;
procedure a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister); override;
procedure a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
procedure a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister); override;
{ move instructions }
procedure a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);override;
@ -107,6 +107,9 @@ unit cgcpu;
function GetStore(const ref: treference): tasmop;
procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
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);
end;
tcg64favr = class(tcg64f32)
@ -332,60 +335,22 @@ unit cgcpu;
procedure tcgavr.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: tcgint; reg: TRegister);
var
mask : qword;
shift : byte;
i : byte;
tmpreg : tregister;
begin
mask:=$ff;
shift:=0;
case op of
OP_OR:
begin
for i:=1 to tcgsize2size[size] do
begin
list.concat(taicpu.op_reg_const(A_ORI,reg,(a and mask) shr shift));
reg:=GetNextReg(reg);
mask:=mask shl 8;
inc(shift,8);
end;
end;
OP_AND:
begin
for i:=1 to tcgsize2size[size] do
begin
list.concat(taicpu.op_reg_const(A_ANDI,reg,(a and mask) shr shift));
reg:=GetNextReg(reg);
mask:=mask shl 8;
inc(shift,8);
end;
end;
OP_SUB:
begin
list.concat(taicpu.op_reg_const(A_SUBI,reg,a));
if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
begin
for i:=2 to tcgsize2size[size] do
begin
reg:=GetNextReg(reg);
mask:=mask shl 8;
inc(shift,8);
list.concat(taicpu.op_reg_const(A_SBCI,reg,(a and mask) shr shift));
end;
end;
end;
else
begin
tmpreg:=getintregister(list,size);
a_load_const_reg(list,size,a,tmpreg);
a_op_reg_reg(list,op,size,tmpreg,reg);
end;
end;
if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then
internalerror(2012102403);
a_op_const_reg_internal(list,Op,size,a,reg,NR_NO);
end;
procedure tcgavr.a_op_reg_reg(list : TAsmList; Op: TOpCG; size: TCGSize; src, dst: TRegister);
procedure tcgavr.a_op_reg_reg(list: TAsmList; Op: TOpCG; size: TCGSize; src, dst : TRegister);
begin
if not(size in [OS_S8,OS_8,OS_S16,OS_16,OS_S32,OS_32]) then
internalerror(2012102401);
a_op_reg_reg_internal(list,Op,size,src,NR_NO,dst,NR_NO);
end;
procedure tcgavr.a_op_reg_reg_internal(list : TAsmList; Op: TOpCG; size: TCGSize; src, srchi, dst, dsthi: TRegister);
var
countreg,
tmpreg: tregister;
@ -393,6 +358,30 @@ unit cgcpu;
instr : taicpu;
paraloc1,paraloc2,paraloc3 : TCGPara;
l1,l2 : tasmlabel;
procedure NextSrcDst;
begin
if i=5 then
begin
dst:=dsthi;
src:=srchi;
end
else
begin
dst:=GetNextReg(dst);
src:=GetNextReg(src);
end;
end;
{ iterates TmpReg through all registers of dst }
procedure NextTmp;
begin
if i=5 then
tmpreg:=dsthi
else
tmpreg:=GetNextReg(tmpreg);
end;
begin
case op of
OP_ADD:
@ -402,12 +391,10 @@ unit cgcpu;
begin
for i:=2 to tcgsize2size[size] do
begin
dst:=GetNextReg(dst);
src:=GetNextReg(src);
NextSrcDst;
list.concat(taicpu.op_reg_reg(A_ADC,dst,src));
end;
end
else
end;
end;
end;
OP_SUB:
@ -417,8 +404,7 @@ unit cgcpu;
begin
for i:=2 to tcgsize2size[size] do
begin
dst:=GetNextReg(dst);
src:=GetNextReg(src);
NextSrcDst;
list.concat(taicpu.op_reg_reg(A_SBC,dst,src));
end;
end;
@ -435,18 +421,16 @@ unit cgcpu;
for i:=2 to tcgsize2size[size] do
begin
list.concat(taicpu.op_reg(A_COM,tmpreg));
tmpreg:=GetNextReg(tmpreg);
NextTmp;
end;
list.concat(taicpu.op_reg(A_NEG,dst));
tmpreg:=GetNextReg(dst);
for i:=2 to tcgsize2size[size] do
begin
list.concat(taicpu.op_reg_const(A_SBCI,dst,-1));
tmpreg:=GetNextReg(tmpreg);
NextTmp;
end;
end
else
list.concat(taicpu.op_reg(A_NEG,dst));
end;
end;
OP_NOT:
@ -456,8 +440,7 @@ unit cgcpu;
if src<>dst then
a_load_reg_reg(list,OS_8,OS_8,src,dst);
list.concat(taicpu.op_reg(A_COM,dst));
src:=GetNextReg(src);
dst:=GetNextReg(dst);
NextSrcDst;
end;
end;
@ -508,11 +491,11 @@ unit cgcpu;
cg.a_label(list,l1);
case op of
OP_SHR:
list.concat(taicpu.op_reg(A_LSR,GetOffsetReg(dst,tcgsize2size[size]-1)));
list.concat(taicpu.op_reg(A_LSR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
OP_SHL:
list.concat(taicpu.op_reg(A_LSL,dst));
OP_SAR:
list.concat(taicpu.op_reg(A_ASR,GetOffsetReg(dst,tcgsize2size[size]-1)));
list.concat(taicpu.op_reg(A_ASR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
OP_ROR:
begin
{ load carry? }
@ -522,7 +505,7 @@ unit cgcpu;
list.concat(taicpu.op_reg_const(A_SBRC,src,0));
list.concat(taicpu.op_none(A_SEC));
end;
list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-1)));
list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1)));
end;
OP_ROL:
begin
@ -530,7 +513,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,GetOffsetReg(dst,tcgsize2size[size]-1),7));
list.concat(taicpu.op_reg_const(A_SBRC,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-1),7));
list.concat(taicpu.op_none(A_SEC));
end;
list.concat(taicpu.op_reg(A_ROL,dst))
@ -545,12 +528,12 @@ unit cgcpu;
case op of
OP_ROR,
OP_SHR:
list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-i)));
list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
OP_ROL,
OP_SHL:
list.concat(taicpu.op_reg(A_ROL,GetOffsetReg(dst,i-1)));
list.concat(taicpu.op_reg(A_ROL,GetOffsetReg64(dst,dsthi,i-1)));
OP_SAR:
list.concat(taicpu.op_reg(A_ROR,GetOffsetReg(dst,tcgsize2size[size]-i)));
list.concat(taicpu.op_reg(A_ROR,GetOffsetReg64(dst,dsthi,tcgsize2size[size]-i)));
else
internalerror(2011030902);
end;
@ -569,8 +552,7 @@ unit cgcpu;
for i:=1 to tcgsize2size[size] do
begin
list.concat(taicpu.op_reg_reg(topcg2asmop[op],dst,src));
dst:=GetNextReg(dst);
src:=GetNextReg(src);
NextSrcDst;
end;
end;
else
@ -578,6 +560,81 @@ unit cgcpu;
end;
end;
procedure tcgavr.a_op_const_reg_internal(list: TAsmList; Op: TOpCG;
size: TCGSize; a: tcgint; reg, reghi: TRegister);
var
mask : qword;
shift : byte;
i : byte;
tmpreg : tregister;
tmpreg64 : tregister64;
procedure NextReg;
begin
if i=5 then
reg:=reghi
else
reg:=GetNextReg(reg);
end;
begin
mask:=$ff;
shift:=0;
case op of
OP_OR:
begin
for i:=1 to tcgsize2size[size] do
begin
list.concat(taicpu.op_reg_const(A_ORI,reg,(a and mask) shr shift));
NextReg;
mask:=mask shl 8;
inc(shift,8);
end;
end;
OP_AND:
begin
for i:=1 to tcgsize2size[size] do
begin
list.concat(taicpu.op_reg_const(A_ANDI,reg,(a and mask) shr shift));
NextReg;
mask:=mask shl 8;
inc(shift,8);
end;
end;
OP_SUB:
begin
list.concat(taicpu.op_reg_const(A_SUBI,reg,a));
if size in [OS_S16,OS_16,OS_S32,OS_32,OS_S64,OS_64] then
begin
for i:=2 to tcgsize2size[size] do
begin
NextReg;
mask:=mask shl 8;
inc(shift,8);
list.concat(taicpu.op_reg_const(A_SBCI,reg,(a and mask) shr shift));
end;
end;
end;
else
begin
if size in [OS_64,OS_S64] then
begin
tmpreg64.reglo:=getintregister(list,OS_32);
tmpreg64.reghi:=getintregister(list,OS_32);
cg64.a_load64_const_reg(list,a,tmpreg64);
cg64.a_op64_reg_reg(list,op,size,tmpreg64,joinreg64(reg,reghi));
end
else
begin
tmpreg:=getintregister(list,size);
a_load_const_reg(list,size,a,tmpreg);
a_op_reg_reg(list,op,size,tmpreg,reg);
end;
end;
end;
end;
procedure tcgavr.a_load_const_reg(list : TAsmList; size: tcgsize; a : tcgint;reg : tregister);
var
@ -1020,18 +1077,20 @@ unit cgcpu;
end;
OS_S8:
begin
{ dest is always at least 16 bit at this point }
emit_mov(list,reg2,reg1);
reg2:=GetNextReg(reg2);
list.concat(taicpu.op_reg(A_CLR,reg2));
list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
list.concat(taicpu.op_reg(A_COM,reg2));
tmpreg:=reg2;
for i:=3 to tcgsize2size[tosize] do
if tcgsize2size[tosize]>1 then
begin
reg2:=GetNextReg(reg2);
emit_mov(list,reg2,tmpreg);
list.concat(taicpu.op_reg(A_CLR,reg2));
list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
list.concat(taicpu.op_reg(A_COM,reg2));
tmpreg:=reg2;
for i:=3 to tcgsize2size[tosize] do
begin
reg2:=GetNextReg(reg2);
emit_mov(list,reg2,tmpreg);
end;
end;
end;
OS_16:
@ -1050,22 +1109,24 @@ unit cgcpu;
end;
OS_S16:
begin
{ dest is always at least 32 bit at this point }
emit_mov(list,reg2,reg1);
reg1:=GetNextReg(reg1);
reg2:=GetNextReg(reg2);
emit_mov(list,reg2,reg1);
reg2:=GetNextReg(reg2);
list.concat(taicpu.op_reg(A_CLR,reg2));
list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
list.concat(taicpu.op_reg(A_COM,reg2));
tmpreg:=reg2;
for i:=4 to tcgsize2size[tosize] do
if tcgsize2size[tosize]>2 then
begin
reg2:=GetNextReg(reg2);
emit_mov(list,reg2,tmpreg);
list.concat(taicpu.op_reg(A_CLR,reg2));
list.concat(taicpu.op_reg_const(A_SBRC,reg1,7));
list.concat(taicpu.op_reg(A_COM,reg2));
tmpreg:=reg2;
for i:=4 to tcgsize2size[tosize] do
begin
reg2:=GetNextReg(reg2);
emit_mov(list,reg2,tmpreg);
end;
end;
end;
else
@ -1733,13 +1794,15 @@ unit cgcpu;
procedure tcg64favr.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
begin
{ TODO : a_op64_reg_reg }
if not(size in [OS_S64,OS_64]) then
internalerror(2012102402);
tcgavr(cg).a_op_reg_reg_internal(list,Op,size,regsrc.reglo,regsrc.reghi,regdst.reglo,regdst.reghi);
end;
procedure tcg64favr.a_op64_const_reg(list : TAsmList;op:TOpCG;size : tcgsize;value : int64;reg : tregister64);
begin
{ TODO : a_op64_const_reg }
tcgavr(cg).a_op_const_reg_internal(list,Op,size,value,reg.reglo,reg.reghi);
end;